2013-04-10 3 views
0

У меня есть массивный набор данных в текстовом файле, который мне нужно проанализировать. Тем не менее, моя проблема заключается в том, что я не знаю, как написать программу для чтения в таких данных, как я хочу.Чтение данных из текстового файла в массив

Что у меня есть текстовый файл организован следующим образом:

 Event: 23365 
    line 2 
    Q1: x,y,z= 263.25 -25.112 0.68342 
    Q2: x,y,z= 263.25 -25.112 0.68342 
    (blank line) 
    -next entry organized the same begins- 

Так что я хочу сделать, это каким-то образом получить каждый из этих переменных в несколько массивов (один массив для каждой переменной), так что я могу сделайте математику им.

О, и я кодирования в C.

У меня нет никакого опыта ввода имени файла, так что я довольно много невежественны. Я искал учебники, но это не помогло. Поэтому в основном мне нужно как-то сканировать текстовый файл и выбирать номера.

+0

Вы можете разместить конкретный пример текстового файла с точными данными? Формат должен быть идеальным, прежде чем вы начнете его анализировать. –

+0

В C лучшей функцией для использования будет, вероятно, 'fscanf()' (например, http://www.cplusplus.com/reference/cstdio/fscanf/), однако фактический пример части вашего файла данных поможет нам советовать вам. Кроме того, существует много других языков, на которых обработка текста намного проще, чем на C, особенно Python или Perl, если они доступны для вас. – Simon

+0

Ну, у меня только есть опыт работы с C, поэтому они мне не доступны. – user2264247

ответ

0

Хорошо, это не очень, но вот пример одного способа для анализа данных:

// you cant't get away from pointers in C, so might as well as force yourself to use them 
// till they make sense. Here are some examples: 

// pointer of type data 
// data* d; 

// d is assigned the address of a memory space the size of a data container 
// d = (data*)malloc(sizeof(data)); 

// d can be dereferenced with *d. 
// (*d).identifier is the same as d->identifier 

// the memory space you got earlier can (and should) be freed 
// free(d); 
// if you free d and malloced d->extra, d->extra must be freed first 



#include <stdio.h> 
#include <ctype.h> 
#include <stdlib.h> 
#include <string.h> 

// define a type to hold information for each event 
typedef struct 
{ 
    char* identifier; 
    char* extra; 
    double var[6]; 
} data; 

// returns a pointer to a new data 
data* 
new_data() 
{ 
    // You are going to eventually need to know how malloc works 
    // or at least what it does. Just google it. For now, it requests 
    // memory from the heap to use 
    data* d = (data*)malloc(sizeof(data));    // request memory the size of the type data 
    d->identifier = (char*)malloc(sizeof(char)*128); // request some space for the c string identifier 
    memset(d->identifier,'\0',sizeof(char)*128);  // set identifier to all 0's (for null terminated 
                 // strings this means that I can replace the first zero's 
                 // and wherever I stop the c string ends) 
    d->extra = (char*)malloc(sizeof(char)*128);   // request some space for the c string extra 
    memset(d->extra,'\0',sizeof(char)*128);    // set extra to all 0's 
    return d;           // return the pointer 
} 

int main(void) 
{ 
    FILE *fp; // pointer to file object 
    int c;  // char could be used too. This is what holds whatever fgetc is assigned to 
    int count = 0; // This program is a state machine and count represents a state 
    char* word = malloc(sizeof(char)*128); // holds several chars 
    int wordPosition = 0; // position of the next char to be written in word 

    fp = fopen("datafile.txt", "r"); // fp is assigned the file datafile.txt in read-only mode 
    memset(word,'\0',sizeof(char)*128); // set word to all 0's 

    data* d = new_data(); // get a new data container to write information to 

    while(c = fgetc(fp)) // loops and gets a new char each loop 
    { 
     if(!isspace(c) && c != EOF) // if the char isn't white space or the End Of File 
      word[wordPosition++] = c; // add the char to word 
     else 
     { 
      if(strlen(word) != 0) // skip if word is empty (for example if there were two spaces in a row) 
      { 
       switch(count) // determine the state 
       { 
        case(0): 
         // for case 0, you want the word that isn't "Event:", so 
         // count will stay at 0 and add every word that isn't "Event:" 
         // as long as there is only one other word then this will result 
         // in what you want 
         if(!(strcmp(word, "Event:") == 0)) 
          strcpy(d->identifier, word); 
         // when there is a new line then go to state 1 
         // '\n' is a white space 
         if(c=='\n') 
          count++; 
         break; 
        case(1): 
         // for case 1 you just want the words on the line, so every word just add 
         // to extra with a space after it. Not the neatest way to do it. 
         strcat(d->extra, word); 
         strcat(d->extra, " "); 
         if(c=='\n') 
          count++; 
         break; 
        case(2): // for case 2 - 7 you just want the numbers so you can do something with them 
        case(3): // so if the first character of the word is a digit or '-' (negative) then 
        case(4): // add it to var[]. An easy way to know which one is just count-2. 
        case(5): // When a new number is added, go to the next state. 
        case(6): // Then test if count == 8. If so, you want to reset. 
        case(7): // skipping case 2-6 is simply saying for each of these go to case 7. 
          // that's why you need to break after a case you don't want to continue. 
         if(isdigit(word[0]) || word[0]=='-') 
         { 
          d->var[count-2] = atof(word); 
          count++; 
         } 
         if (count == 8) 
         { 
          // here is where you would do something different with the data you have. 
          // I imagine you would want an array of data's that you would just add this to 
          // for example, at the beginning of main have 
          // data* events[MAX_EVENTS]; 
          // int eventCount = 0; 
          // and here do something like 
          // events[eventCount++] = d; 
          // remember that eventCount++ gets the value first and then increments 
          // after the instruction is over 

          printf("%s\n",d->identifier); 
          printf("%s\n",d->extra); 
          printf("%f\n",d->var[0]); 
          printf("%f\n",d->var[1]); 
          printf("%f\n",d->var[2]); 
          printf("%f\n",d->var[3]); 
          printf("%f\n",d->var[4]); 
          printf("%f\n",d->var[5]); 

          // set the state back to the beginning 
          count = 0; 

          // if you were doing something with the data, then don't free yet. 
          free(d->identifier); 
          free(d->extra); 
          free(d); 

          // make a new data and start over for the next event. 
          d = new_data(); 
         } 
         break; 
       } 

       // clear the word and set wordPosition to the beginning 
       memset(word,'\0',sizeof(char)*128); 
       wordPosition = 0; 
      } 
     } 
     // check if the end of the file is reached and if so then exit the loop 
     if(c == EOF) 
      break; 
    } 
    fclose(fp); 

    // here you would do something like 
    // for(i = 0; i < eventCount; i++) 
    //  total1 += events[i]->var[1]; 
    // printf("The total of var1 is: %f\n",total1); 

    return 0; 
} 
+0

Спасибо! Это дает мне в значительной степени то, что мне нужно. Можете ли вы объяснить этот код немного? Я полный noob с указателями, и я также избегал манипулирования персонажами. Что делает полная часть в скобках после new_data()? --------- И правильно ли я понимаю, что случай 0 сканирует слово «Событие», копирует строку и перемещает счет на следующую строку. Случай 1 удаляет любые символы в других строках. ---------------- и как только первые 2 строки пропущены и подсчитаны 6 чисел, счет == 7, чтобы вы печатали на футляре 7? – user2264247

+0

Я добавил комментарии, которые, надеюсь, все прояснят. Я бы согласился с тем, что Саймон сказал, хотя, вероятно, вы потратите меньше времени и головных болей на загрузку питона и посмотрите несколько руководств. Было бы намного проще и меньше половины кода. Но если вы настаиваете на C, то это тоже очень удобно. – Alden

Смежные вопросы