C 试图扫描字符串时程序崩溃

C 试图扫描字符串时程序崩溃,c,C,扫描包含任意游戏结果的.dat文件中的数据时遇到问题(用于测试程序) 结果的格式如下:(#将分数表示为整数) a队#b队# a队#b队# a队#b队# . . . a队#b队# 每一排都是不同的游戏 目前我试图用我的代码做的是使用fgets()函数扫描每一场比赛/每一行,然后使用sscanf_s()函数从每一行获取数据(好像我知道它的格式),并将其存储到我定义的数据结构中 如果有一种更简单、更快和/或更可靠(万无一失)的方法,我非常乐意接受任何关于我将数据放入结构的方式的更改的建议 非常感谢您的

扫描包含任意游戏结果的.dat文件中的数据时遇到问题(用于测试程序)

结果的格式如下:(#将分数表示为整数)

a队#b队# a队#b队# a队#b队# . . . a队#b队#

每一排都是不同的游戏

目前我试图用我的代码做的是使用fgets()函数扫描每一场比赛/每一行,然后使用sscanf_s()函数从每一行获取数据(好像我知道它的格式),并将其存储到我定义的数据结构中

如果有一种更简单、更快和/或更可靠(万无一失)的方法,我非常乐意接受任何关于我将数据放入结构的方式的更改的建议


非常感谢您的帮助。

我简化了一点,效果很好。你的工作还没有完成。请试试这个

 #include <usual.h>

 #define MAX_NAME_CHARS 15
 #define MAX_DATA_FILE_LINE_LENGTH 32
 #define MAX_GAME_RESULTS 128

 int main( void )
 {
   FILE *inp2b;

   typedef struct game_results
   {
     char first_team_name[MAX_NAME_CHARS];
     int first_team_score;
     char second_team_name[MAX_NAME_CHARS];
     int second_team_score;
   } game_results_t;

   game_results_t game_results[MAX_GAME_RESULTS];
   char data_file_line[MAX_DATA_FILE_LINE_LENGTH][MAX_DATA_FILE_LINE_LENGTH];
   int errorcode = 0;
   int i = 0;

 //errorcode = fopen_s(&inp2b,"C:\\Users\\Cody\\Documents\\Visual Studio 2012\\DATAFILES FOR PA2\\input2b.dat","r");
   inp2b = fopen( "C:\\testdat\\input2b.dat", "r" );

   if ( inp2b == NULL )
     errorcode = 1;

   if ( errorcode != 0 )
   {
     printf( "Error opening 2nd data file!\n\n" );
     return ( 0 );
   }
   else
   {
     printf( "\n\n\nFile was opened successfully!\n\n" );
   }

   i = 0;

   while ( !feof( inp2b ) )
   {
     fgets( data_file_line[i], MAX_DATA_FILE_LINE_LENGTH, inp2b );
     puts( data_file_line[i] );
     printf( "\n" );
     //   sscanf_s(data_file_line[i],"%s %d %s %d",game_results[i].first_team_name,&game_results[i].first_team_score,game_results[i].second_team_name,&game_results[i].second_team_score);
     sscanf( data_file_line[i], "%s %d %s %d", game_results[i].first_team_name,
        &game_results[i].first_team_score,
        game_results[i].second_team_name,
        &game_results[i].second_team_score );

     printf( "\n\n %s %d %s %d \n\n", game_results[i].first_team_name,
        game_results[i].first_team_score,
        game_results[i].second_team_name,
        game_results[i].second_team_score );
     i++;
   }

   fclose( inp2b );

   return ( 0 );
 }
#包括
#定义最大名称字符数15
#定义最大数据文件行长度32
#定义最大游戏结果128
内部主(空)
{
文件*inp2b;
类型定义结构游戏结果
{
char first_team_name[MAX_name_CHARS];
国际一队得分;
char第二团队名称[MAX_name_CHARS];
国际二队成绩;
}比赛结果;
博弈结果博弈结果[最大博弈结果];
字符数据文件行[最大数据文件行长度][最大数据文件行长度];
int errorcode=0;
int i=0;
//errorcode=fopen_s(&inp2b,“C:\\Users\\Cody\\Documents\\visualstudio 2012\\PA2的数据文件\\input2b.dat”,“r”);
inp2b=fopen(“C:\\testdat\\input2b.dat”,“r”);
如果(inp2b==NULL)
错误代码=1;
如果(错误代码!=0)
{
printf(“打开第二个数据文件时出错!\n\n”);
返回(0);
}
其他的
{
printf(“\n\n\n文件已成功打开!\n\n”);
}
i=0;
而(!feof(inp2b))
{
fgets(数据文件行[i],最大数据文件行长度,inp2b);
puts(数据文件行[i]);
printf(“\n”);
//sscanf(数据文件行[i],%s%d%s%d],游戏结果[i]。第一队名称和游戏结果[i]。第一队得分,游戏结果[i]。第二队名称和游戏结果[i]。第二队得分);
sscanf(数据文件行[i],%s%d%s%d],游戏结果[i]。第一队名称,
&比赛结果[i]。一队得分,
比赛结果[i]。第二队名称,
&比赛结果[i]。第二组(队)得分);
printf(“\n\n%s%d%s%d\n\n”,游戏结果[i]。第一队名称,
比赛结果[i]。一队得分,
比赛结果[i]。第二队名称,
比赛结果[i]。第二组(队)得分);
i++;
}
fclose(inp2b);
返回(0);
}
对格式说明符和参数的解释方式略有不同:为了防止缓冲区溢出,每个字符串格式(
%s
%c
%[
)必须在缓冲区后传递相应的缓冲区大小

因此,您的扫描命令应为:

    sscanf_s(data_file_line[i],
        "%s %d %s %d",
        game_results[i].first_team_name,
        sizeof(game_results[i].first_team_name),
        &game_results[i].first_team_score,
        game_results[i].second_team_name,
        sizeof(game_results[i].second_team_name),
        &game_results[i].second_team_score);
您的代码还存在一些其他问题:

  • 您应该检查
    sscanf_s
    的返回值,以便知道该行已成功解析。返回值是转换的项目数,因此在您的情况下应该是4。还请注意
    %s
    扫描单词和团队名称,如“曼Utd”和“斯托克城”有两个单词,无法正确解析
  • 正如其他人所指出的,
    feof
    构造将使您读取文件的次数过多。忘记
    foef
    ,而是使用读取函数的返回值。对于eample,
    fgets
    在到达文件结尾时返回
    NULL
    ,因此您可以将其用作循环条件:
    while(fgets(buf,sizeof(buf,f))…
  • 您不检查
    i
    是否溢出。如果您有一个长文件,
    i
    可能不够大
  • 如果您正在立即解析和存储行,则不需要有行数组;只需反复使用一行缓冲区即可

Plase read。看到我的错误答案了吗,这是因为你没有在每个
之后使用空格,
你的代码因此很难阅读。很难看到标识符在哪里结束或下一个标识符在哪里开始,所以
游戏结果[i]。第一队的名字和游戏结果[i]。第一队的得分
让我想到了
游戏结果[i],first_team_name,&game_results[i]。first_team_score
,正如您所见,这将使我的答案正确。我认为问题可能出在
sscanf s
、Microsoft的safe
sscanf
。它在每个字符串参数之后,即
%s
%c
的参数之后,都需要一个缓冲区大小[
格式。请参阅说明和示例。正如M Oehm指出的,您的
sscanf_s
看起来可疑,请阅读:发生的是读取了文件的最后一行,而不是EOF。当循环返回时,
fgets()
尝试读取一条以上的记录,但失败。
数据文件行
可以保存15行,
游戏结果
可以保存128条结果,但您使用相同的索引变量,
i
来保存这两条结果。如果循环次数超过15次,则(!feof(inp2b))时,
数据文件行
会出现缓冲区溢出
仍然是解析文件的错误逻辑,因为您不检查
fgets
的返回值,之后您所做的任何操作都使用不确定的数据。您是对的,我说:程序现在运行,但您仍有工作要做,我正试图首先克服第一个问题:崩溃。干杯。使用此答案中所做的更改d上面的答案让它工作起来。谢谢Mateahhhh kay,我想知道缓冲区是什么意思,以及如何实现它。我会解决所有这些问题,然后看看我是怎么做的。此外,团队名称(例如Man Utd)在数据文件中表示为“ManUtd”,这样生活会更轻松。谢谢heaps!