2016-01-24 77 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()函数,并在您读取文件时跟踪每个字段的最长长度。