2013-04-10 95 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

您可以發佈與精確數據的文本文件的一個實際的例子嗎?在開始嘗試解析它之前,格式需要完美。 – 2013-04-10 02:59:00

+0

在C語言中,使用的最佳函數可能是'fscanf()'(例如,請參閱http://www.cplusplus.com/reference/cstdio/fscanf/),但是您的數據文件的一部分的實際示例將幫助我們爲您提供建議。另外,還有許多其他語言,其中文本處理比C語言更容易 - 尤其是Python或Perl(如果它們對您可用)。 – Simon 2013-04-10 02:59:55

+0

呃,我實際上只有C的經驗,所以他們對我來說真的沒有。 – user2264247 2013-04-10 03:13:20

回答

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刪除其他行中的任何字符。 ---------------- 並且一旦前兩行被跳過並且有6個數字被計數,count == 7因此您在case 7上打印? – user2264247 2013-04-10 07:04:24

+0

我添加了希望能夠解決問題的評論。我同意西蒙說的話,你可能會花更少的時間和頭痛下載python並看一些教程。這將是更容易,少於一半的代碼。但是如果你堅持C,那麼它也是非常可行的。 – Alden 2013-04-10 14:33:06