Анализ текстового файла с разделителями табуляции
Я пытаюсь написать код, который будет анализировать текстовый файл с разделителями табуляции, назначая каждую строку между табуляциями определенному элементу образца структуры, который я определил. Во входном файле первая строка будет иметь все идентификаторы класса (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, он напечатает 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 - почти уверен, что у меня есть фундаментальное неправильное понимание того, что это на самом деле означает. Я должен разобраться в этом. Спасибо еще раз за помощь!
1 ответ
Попробуй это:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 30
#define MAX_OBS 80000
typedef struct{
char c_name[LENGTH];
char s_name[LENGTH];
double value[MAX_OBS];
} Sample;//Duplication of type and variable names should be avoided. pointed out by Jonathan Leffler.
int main(void){
char line[1024];
FILE *input = fopen("data.txt", "r");
fgets(line, sizeof(line), input);
int total_columns = 0;
char *p = strtok(line, "\t\n");
while(p){
++total_columns;
p = strtok(NULL, "\t\n");
}
--total_columns;//first column is field name
rewind(input);
//*******************************************************************************
Sample *sample = malloc(total_columns * sizeof(*sample));//To allocate in the stack is large. So allocate by malloc.
fscanf(input, "%*s\t");//skip first column
for (int i = 0; i < total_columns; i++){
fscanf(input, "%[^\t\n]\t", sample[i].c_name);//\n for last column
}
fscanf(input, "%*s\t");//skip first column
for (int i = 0; i < total_columns; i++){
fscanf(input, "%[^\t\n]\t", sample[i].s_name);
}
int r;
for(r = 0; r < MAX_OBS; ++r){
if(EOF==fscanf(input, "%*s")) break;
for (int i = 0; i < total_columns; i++){
fscanf(input, "%lf", &sample[i].value[r]);
}
}
fclose(input);
//test print
printf("%s\n", sample[0].c_name);
printf("%s\n", sample[0].s_name);
for(int i = 0; i < r; ++i)
printf("%f\n", sample[0].value[i]);
printf("\n%s\n", sample[total_columns-1].c_name);
printf("%s\n", sample[total_columns-1].s_name);
for(int i = 0; i < r; ++i)
printf("%f\n", sample[total_columns-1].value[i]);
free(sample);
}