динамическое указание размера числа с плавающей запятой в функциональном операторе sscanf
У меня есть файл структурированных данных, состоящий из строк заголовка, чередующихся с блоками данных. Я читаю каждый блок данных (как определено строкой заголовка) в отдельную ячейку массива ячеек. Например, предположим, что после загрузки данных сtextscan
У меня есть массив ячеекx
и массив индексов строк заголовка и EOF (headerIdx
) следующей формы:
x={'header line 1';'98.78743';'99.39717';'99.93578';'100.40125';'100.79166';'101.10525';'101.34037';'101.49553';'101.56939';'101.56072';'101.4685';'101.29184';'101.03002';'100.68249';'header line 2';'100.24887';'99.72897';'99.12274';'98.43036';'97.65215';'96.78864';'95.84054';'header line 3';'3.2';'4.31';'2.7';'4.6';'9.3'};
headerIdx=[1;16;24;30];
Затем я пытаюсь извлечь каждый блок данных ниже строки заголовка в отдельный элемент массива ячеек, используяsscanf
а такжеstr2mat
(как предложеноэта почта). Первоначально этот подход не удался, потому что элементы в данном блоке данных были разной длины. Это можно решить, включив числовой флаг для'%f'
аргумент в помощьsscanf
знать, где разграничить входные данные (как предложеноэта почта). Затем можно использовать следующую стратегию для преобразования структурных данных в массив ячеек двойных массивов, характерных для блоков:
extract_data = @(n) sscanf(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',['%' num2str(size(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',1)) 'f']);
extracted_data = arrayfun(extract_data,1:numel(headerIdx)-1,'UniformOutput',false);
Числовой флаг строки формата может быть либо установлен на что-то произвольно большое, чтобы охватить все данные, либо может быть установлен для конкретного блока, как я делал в примере выше. Последний подход приводит к избыточной оценкеstr2mat
(один раз для ввода вsscanf
и один раз для ввода в'%f'
генератор строк. Можно ли избежать этой избыточности без использования операторов цикла, которые хранят выходные данныеstr2mat
команда во временной переменной? Обратите внимание, что нельзя просто взять выводsize
Команда применяется к выводуstr2mat(x).'
на весь набор данных, потому что строки заголовка, как правило, будут строки с наибольшим количеством символов.
Наконец, я построилx
Приведенная выше матрица отражает тот факт, что некоторые блоки данных могут иметь разную точность, чем другие блоки. Это причина для установки строки формата специфичным для блока способом. Мои тесты показали, что, несмотря на точное построение строки формата для конкретного блока (['%' num2str(size(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',1)) 'f']
) данные во всех элементах результирующего массива ячеек (extracted_data
) в конечном итоге вынуждены иметь одинаковую точность (см. ниже). Почему это так, и как это можно исправить?
extracted_data{:}
ans =
98.7874
99.3972
99.9358
100.4013
100.7917
101.1052
101.3404
101.4955
101.5694
101.5607
101.4685
101.2918
101.0300
100.6825
ans =
100.2489
99.7290
99.1227
98.4304
97.6522
96.7886
95.8405
ans =
3.2000
4.3100
2.7000
4.6000
9.3000