Я пытаюсь написать код, который будет анализировать текстовый файл с разделителями табуляции, назначая каждую строку между табуляциями заданному элементу образца структуры, который я определил. Во входном файле первая строка будет содержать все идентификаторы классов (c_name), вторая строка — все идентификаторы образцов (s_name), а остальные строки будут содержать данные.
Я знаю, что это будет немного сложнее, потому что первый столбец на самом деле будет содержать только метки, но я решил начать с попытки выяснить общую схему синтаксического анализа.
Я могу предположить, что, например, для идентификаторов классов мне, вероятно, следует использовать fscanf в цикле for, добавляя каждый идентификатор в поле класса данного образца, но я теряюсь в фактической реализации. Основываясь на одном посте, который я видел, я подумал, что могу сделать что-то вроде использования %[^\t]\t
в fscanf для чтения в массив всего, что не является вкладкой, но я не думаю, что это совершенно правильно.
Любые предложения будут ценны.
#define LENGTH 30
#define MAX_OBS 80000
typedef struct
{
char c_name[LENGTH];
char s_name[LENGTH];
double value[MAX_OBS];
}
sample;
// I've already calculated the number of columns in the file
sample sample[total_columns];
for (int i = 0; i < total_columns; i++)
{
fscanf(input, "%[^\t]\t", sample[i].s_name);
}
Изменить: я пробовал несколько различных вариантов кода ниже ("%[^\t\n\r]\t\n\r" или "%[^\t\n\r]%*1[\ t\n\r]", или " %[^\t\n\r]"), и все они, похоже, в целом работают, за исключением того, что в зависимости от размера, который я выделяю данным, и от того, как долго я итерирую , в какой-то момент это дает ошибку сегментации. Приведенный ниже код немедленно выдает ошибку сегментации, но если я произвольно изменю total_columns в обоих местах на 3, он напечатает Class Case Case. Кажется, это работает до 14, после чего происходит сбой сегментации всей программы. Я довольно запутался в этом вопросе. Я также попытался распределить память по массиву данных образца, чтобы увидеть, была ли это проблема стека или кучи, но это, похоже, тоже не помогает. Большое спасибо за Вашу помощь!
sample data[total_columns];
fseek(input, 0, SEEK_SET);
for (int i = 0; i < total_columns; i++)
{
fscanf(input, "%[^\t\n\r]\t\n\r", data[i].s_name);
printf("%s\n", data[i].s_name);
}
Пример входного файла будет выглядеть так:
Class Case Case Case Case Case Case Case Case Case Case Case Case Case Case Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control
Subject G038 G144 G135 G161 G116 G165 G133 G069 G002 G059 G039 G026 G125 G149 G108 G121 G060 G140 G127 G113 G023 G147 G011 G019 G148 G132 G010 G142 G020 G021
Data1 0.000741628 0.00308607 0.000267431 0.001418697 0.001237904 0.000761145 0.0008281 0.002426075 0.000236698 0.004924871 0.000722752 0.003758006 0.000104813 0.000986619 0.000121803 0.000666854 0 0.000171394 0.000877993 0.002717391 0.001336501 0.000812089 0.001448743 5.28E-05 0.001944298 0.000292529 0.000469631 0.001674047 0.000651526 0.000336615
Data2 0.102002396 0.108035127 0.015052531 0.079923731 0.020643362 0.086480609 0.017907667 0.016279315 0.076263965 0.034876124 0.187481931 0.090615572 0.037460171 0.143326961 0.029628502 0.049487575 0.020175439 0.122975405 0.019754837 0.006702899 0.014033264 0.040024363 0.076610375 0.069287599 0.098896479 0.011813681 0.293331246 0.037558052 0.303052867 0.137591517
Data2 0.218495065 0.242891829 0.23747851 0.101306336 0.309040188 0.237477347 0.293837554 0.34351816 0.217572429 0.168651691 0.179387106 0.166516699 0.099970652 0.181003474 0.076126675 0.10244981 0.449561404 0.139257863 0.127579104 0.355797101 0.354544105 0.262855651 0.10167146 0.186068602 0.316763006 0.187466247 0.05701315 0.123825467 0.064780343 0.069847682
Data4 0.141137543 0.090948286 0.102502388 0.013063365 0.162060849 0.166292135 0.070215996 0.063535037 0.333743609 0.131011609 0.140936687 0.150108506 0.07812762 0.230704405 0.069792935 0.120770743 0.164473684 0.448110378 0.42599534 0.074094203 0.096525097 0.157661185 0.036737518 0.213931398 0.091119285 0.438073807 0.224921728 0.187034237 0.06611442 0.086005218
Data5 0.003594044 0.003948354 0.008137536 0.001327901 0.002161974 0.003552012 0.002760334 0.001898667 0.001420186 0.003165988 0.001011853 0.001217382 0.000314439 0.004254794 0.000213155 0.003650147 0 0.002742309 0.002633978 0 0.002524503 0.002146234 0.001751465 0.006543536 0.003941146 0.00049505 0.00435191 0.001944054 0.001303053 0.004207692
Data6 0.000285242 2.27E-05 0 1.13E-05 0.0002964 3.62E-05 0.000138017 0.000210963 0.000662753 0 0 0 0 4.11E-05 0 0 0 0 0.000101307 0 0 0 0 5.28E-05 0.00152391 0 0 0 0 0
Data7 0.002624223 0.001134584 0.00095511 0.000419934 0.000401011 0.001739761 0.00272583 0.002566717 0.000520735 0.002311674 0.006287944 0 6.29E-05 0.000143882 3.05E-05 0.000491366 0 0 3.38E-05 0 0.001782002 0.000957104 0.002594763 0.000527704 0.000105097 0.001192619 3.13E-05 0 0.000744602 0.000252461
Data8 0.392777683 0.383875286 0.451499522 0.684663315 0.387394299 0.357992026 0.488406597 0.423473155 0.27267563 0.47454646 0.331020526 0.484041709 0.735955056 0.338841956 0.781699147 0.625403622 0.313596491 0.270545891 0.379259109 0.498913043 0.372438372 0.446271644 0.606698813 0.305593668 0.360535996 0.29889739 0.328710081 0.521222594 0.419924299 0.584111756
Редактировать: я, кажется, исправил это, изменив определение MAX_OBS - почти уверен, что у меня есть фундаментальное непонимание того, что это на самом деле означает. Я должен изучить это. Спасибо еще раз за помощь!
sample
как имени типа, так и имени переменной может привести к путанице, даже если компилятор это примет. - person Jonathan Leffler   schedule 03.10.2016"%[^\t\n"]%*1[\t\n]"
, который ищет не вкладки, не новые строки, за которыми следует табуляция или новая строка (*
подавляет присваивание). Вы должны проверить возвращаемое значение изfscanf()
и остановить обработку, если результат не равен 1. Таким образом, вы не получаете никакой информации о символе-разделителе; вы также можете назначить разделитель для дополнительной проверки. - person Jonathan Leffler   schedule 03.10.2016