2016-01-24 57 views
1

我的程序沒有響應,需要像下面的輸入。
這是我的文本文件:c編程文本文件結構和fgets時出錯

MU-547 China Eastern  10.55  1.20 Every day, via Shianghai + 1 day 
MU-541 China Eastern  13.50  1.20 Every day, via Shianghai + 1 day 
CI-835 China Airlines  9.40  16.00 Every day, via Taipei 
CI-065 China Airlines  16.25  1.10 Every day, via Taipei 
SQ-970 Singapore Airlines 20.50  8.40 Every day, via singapore 
SQ-972 Singapore Airlines 20.50  11.05 Every day, via singapore 
SQ-974 Singapore Airlines 20.50  14.35 Every day, via singapore 
SQ-976 Singapore Airlines 20.50  17.55 Every day, via singapore 
SQ-978 Singapore Airlines 20.50  20.05 Every day, via singapore 
CX-751 Cathay Pacific  9.15  16.20 Every day, via Hong Kong 
CX-701 Cathay Pacific  10.45  17.55 Every day, via Hong Kong 

enter image description here

#include <stdio.h> 
typedef struct 
{ 
    char id[7]; 
    char airlineName[31]; 
    float arrive,depart; 
    char notes[100]; 
} AIRLINE; 

void openFile(const char *data2) 
{ 
    AIRLINE plane[12] = {0}; 
    int i = 0; 
    FILE *file = fopen(data2, "r"); 
    if (file) 
    { 
    char line[83]; 
    while(fgets(line, sizeof line, file) && i < 6) 
    { 
     fputs(line, stdout); 
     if(sscanf(line, 
       "%6s %30c%f%f%99c", 
       plane[i].id, 
       plane[i].airlineName, 
       plane[i].arrive, 
       plane[i].depart, 
       plane[i].notes) == 5) 
     { 
     printf(" %s ", plane[i].id); 
     printf(" %c ", plane[i].airlineName); 
     printf(" %f ", plane[i].arrive); 
     printf(" %f ", plane[i].depart); 
     printf(" %c ", plane[i].notes); 
     i++; 
     }   
    } 
    fclose(file); 
    } 
    else 
    perror(data2); 
} 

int main(void) 
{ 
    openFile("data2.txt"); 
    return 0; 
} 
+0

我想你的'line [83]'很小。把它改成更大的東西。 – nsilent22

+1

nsilent22是正確的。你最長的線超過90個字符。 它只是沒有迴應? 您是否熟悉調試器?你有沒有一步來看看它有多遠? 錯誤消息 - 不僅僅用於調試 - 會很好。例如如果sscanf不返回預期的分配數量。 – BryanT

+0

你爲什麼選擇'83'?下一次你需要一個文本緩衝區(並且你沒有爲RAM限制的嵌入式系統開發),只需使用[256]作爲所有緩衝區的最小值。如果開發人員這樣做,緩衝區溢出的SO帖子就會減少,尤其是那些令人討厭的obi-wans。沒有留下空白終結者的空間。 –

回答

0

當掃描%f的浮點數時,需要變量的地址,並且缺少這些值的&。
使用%c進行掃描將不會以'\ 0'結束變量,並且printf可能會成爲問題。
格式「%6s%30 [^ 0-9]%f%f%99 [^ \ n]」將最多掃描六個字符,然後掃描最多30個非數字字符,然後掃描兩個浮點數,最後掃描兩個浮點數換行符最多可以有99個字符。

#include <stdio.h> 
typedef struct 
{ 
    char id[7]; 
    char airlineName[31]; 
    float arrive,depart; 
    char notes[100]; 
} AIRLINE; 

void openFile(const char *data2) 
{ 
    AIRLINE plane[12] = {{{0}}}; 
    int i = 0; 
    FILE *file = fopen(data2,"r"); 
    if (file) 
    { 
     char line[83]; 
     while(i < 6 && fgets(line,sizeof line, file)) 
     { 
      fputs(line, stdout); 
      if(sscanf(line,"%6s %30[^0-9]%f%f %99[^\n]", 
       plane[i].id, 
       plane[i].airlineName, 
       &plane[i].arrive,  // needed & 
       &plane[i].depart,  // needed & 
       plane[i].notes) == 5) 
      { 
       printf(" %s ",plane[i].id); 
       printf(" %s ",plane[i].airlineName); // use %s for string 
       printf(" %f ",plane[i].arrive); 
       printf(" %f ",plane[i].depart); 
       printf(" %s ",plane[i].notes); 
       i++; 
      } 
     } 
     fclose(file); 
    } 
    else 
    { 
     perror(data2); 
    } 
} 

int main(void) 
{ 
    openFile("data2.txt"); 
    return 0; 
} 
0

正如在評論中指出,聲明:char line[83];不夠大,可以包含一些在你的輸入文件上顯示的線,導致在buffer overflow。同樣,您的struct中的某些字段被硬編碼爲長度可能不夠大,無法包含未來輸入文件可能接收您。 (例如,this link中的部分航空公司名稱長於31個字符,且不適合char airlineName[31])類似arrive,depart等字段可能安全使用float類型。但字段notesairlines,甚至id至少有問題。你也可以而不是知道輸入文件中的行數。

您可以通過多種方式解決輸入文件行長度或行數。兩個選項立刻浮現在腦海:

1)使線路長度的估計,和行數,並希望 他們爲每個輸入文件穩定。 (如已看到的那樣,這具有 後果)
2)確定的行數,和最大線路長度爲 一個預處理步驟,然後使用該信息來創建 適當大小的輸入行字符緩衝區,並使用指向 結構的指針,創建足以包含每行數據中的數據的空間,而不管輸入文件包含多少行。

例如,創建一個函數來確定文件中的行數和文件中最長行的長度,然後使用該信息創建足以逐行讀取文件的內存,而不會有緩衝區溢出的風險:

int longestline(const char *filename, int *lc) 
{ 
    FILE *fp; 
    int cnt=0, cntKeep=0; 
    char c; 
    (*lc) = 0; 
    fp = fopen(filename, "r"); 
    if(!fp) return 0; 
    while ((c = fgetc (fp)) != EOF) 
    { 
     if(c != '\n') 
     { 
      cnt++; 
     } 
     else 
     { 
      cnt = 0; 
      (*lc)++; //update line counter 
     } 
     cntKeep = cntKeep < cnt ? cnt : cntKeep;//update longest line counter 
    } 
    if(cnt > 0) (*lc)++;//last line may not have '\n' 
    fclose(fp); 
    return cntKeep; 
} 

用例:

int line_cnt = 0; 
int longestLine = longestline("c:\\inputfile.txt", &line_cnt)//determine longest line of file. 
//char line[83]; 
char *line = calloc(longestLine + 1, 1);//create buffer to accommodate longest of lines found in file 
//AIRLINE plane[12] = {0}; 
AIRLINE *plane = calloc(line_cnt, sizeof(AIRLINE)); 

此相同的預處理方法還可以擴展到創建適當尺寸的結構體的成員變量尺寸爲好。確定最長字段長度,通過使用擴展後的類似方法,使用類似方法在每行上使用strtok()fgets()函數,並在您讀取文件時跟蹤每個字段的最長長度。