MATLAB: невозможно проанализировать несколько значений с плавающей точкой

У меня есть GUI с UITable (встроенный в GUIDE). Я прочитал в двух числовых значениях и через серию шагов преобразовать значение с плавающей точкой в ​​строку. Я хочу, чтобы у пользователя была возможность щелкнуть по определенной ячейке в UITable, содержащей два значения (теперь как строки), и прочитать эти значения обратно как значения с плавающей точкой. По какой-то причине я могу только когда-нибудь прочитать свой код в первом значении с плавающей точкой. Мой код (по порядку) ниже.

Шаг 1: Доступ к данным и преобразование в строку и размещение строки в соответствующем столбце.

function fillAnnotRangeInfo(obj, selectedAxes)

    selectedAxesTag = selectedAxes.Tag; 
    rawAxesTag = obj.rawDataDisplayAxes.Tag; 
    psdAxesTag = obj.psdDataDisplayAxes.Tag; 

    % Depending on which axes the user clicks on, the units will either be Hz or s 
    if strcmp(selectedAxesTag, rawAxesTag)
        dataRange = strcat(num2str(obj.t1), {'s'}, {' - '}, num2str(obj.t2), {'s'});
    elseif strcmp(selectedAxesTag, psdAxesTag)
        dataRange = strcat(num2str(obj.t1), {'Hz'}, {' - '}, num2str(obj.t2), {'Hz'}); 
    end 

    obj.nextRow.AnnotRange = dataRange; 

end  

Шаг 2: Определите, щелкнул ли пользователь в правильной ячейке, и попытайтесь прочитать два значения с плавающей точкой.

% --- Executes when selected cell(s) is changed in existingAnnotationsTable.
function existingAnnotationsTable_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to existingAnnotationsTable (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.CONTROL.TABLE)
%   Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)

% AE = handles.UserData; 

Indices = eventdata.Indices; 

% Determine if column is column of interest 
if Indices(2) == 4
    rangeData = handles.existingAnnotationsTable.Data;
    rangeData = rangeData{Indices(1), Indices(2)}; 
    annoRange = sscanf(rangeData, '%f')
else

end


return

В конечном итоге, я получаю следующий результат: если у меня будет строка, точно следующая: "7,4250 Гц - 32,50 ГГц" (или заменить Гц на "s"), моя программа выдаст только "7,4250". Ни больше ни меньше. Я пробовал textcan, sscanf и strread. Каждый из них я явно устанавливаю свой фильтр с плавающей точкой (%f). С помощью strread я попытался настроить его на циклический переход более одного раза (strread('string', %f, 2)). Я понятия не имею, что еще нужно сделать или попробовать или изменить.

ОТНОСИТЕЛЬНО ОТВЕТОВ НИЖЕ ДЛЯ БУДУЩИХ ЧИТАТЕЛЕЙ: Технически любой из ответов является "правильным" (я попробовал их). Все они применимы к немного другой ситуации. Ответ Бена хорош для получения результата за один шаг, если у вас фиксированный формат. Мой собственный ответ работает для разбиения строки на несколько этапов, предоставляя доступ к данным на каждом этапе (полезно для выполнения нескольких операций), в то же время имея возможность работать с различными форматами. Ответ Андраса полезен для того, чтобы сделать это за один шаг и мгновенно получить результат, хотя он по-прежнему может работать с различными форматами.

3 ответа

Решение

Ответ Бена - правильный ответ в случае фиксированного формата. Однако в моем случае мой формат меняется. Поэтому мое предлагаемое решение (проверено и проверено) заключается в использовании strtok"разбить" строку на две отдельные строки, что делает ее намного более управляемой и более легкой для анализа. Код ниже. Мысли?

% --- Executes when selected cell(s) is changed in existingAnnotationsTable.
function existingAnnotationsTable_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to existingAnnotationsTable (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.CONTROL.TABLE)
%   Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)

% AE = handles.UserData; 

Indices = eventdata.Indices; 

% Determine if column is column of interest 
if Indices(2) == 4
    rangeData = handles.existingAnnotationsTable.Data;
    rangeData = rangeData{Indices(1), Indices(2)}; 

    [dataStart, dataRemain] = strtok(rangeData); 
    % In this case, since there will be just a '-' as the token...
    % ...we don't care about the token and only save the remainder. 
    [~, dataEnd] = strtok(dataRemain); 
    dataStart = sscanf(dataStart, '%f') 
    dataEnd = sscanf(dataEnd, '%f')

else

end

Посмотрите на sscanf документация здесь, если вы хотите набор чисел с плавающей точкой, вам необходимо указать формат. Вот пример с этой страницы, похожий на ваш:

tempString = '78°F 72°F 64°F 66°F 49°F';

degrees = char(176);
tempNumeric = sscanf(tempString, ['%d' degrees 'F'])'
tempNumeric =
    78    72    64    66    49

В вашем конкретном случае вы можете попробовать:

val = sscanf(rangedata,'%fHz - %fHz')

Мотивировано моим собственным комментарием об использовании regexp до sscanfВот решение, которое использует только первое:

str=regexp(data,'(?<dataStart>[\d\.]+)[^\d\.]+(?<dataEnd>[\d\.]+)','names');

после которого str будут поля dataStart а также dataEnd как строки (так что вам нужно num2str впоследствии). Обратите внимание, что это работает только для простых чисел с плавающей запятой (но, конечно, regexp может быть еще сложнее до тошноты, если это необходимо). Положительным моментом является то, что он может быть адаптирован к более хитрым строкам ввода, например, приведенное выше будет обрабатывать любой номер и вид нечислового (и не точечного) текста между первыми двумя числами. Недостатком является regexp,

Другие вопросы по тегам