C 试图扫描字符串时程序崩溃
扫描包含任意游戏结果的.dat文件中的数据时遇到问题(用于测试程序) 结果的格式如下:(#将分数表示为整数) a队#b队# a队#b队# a队#b队# . . . a队#b队# 每一排都是不同的游戏 目前我试图用我的代码做的是使用fgets()函数扫描每一场比赛/每一行,然后使用sscanf_s()函数从每一行获取数据(好像我知道它的格式),并将其存储到我定义的数据结构中 如果有一种更简单、更快和/或更可靠(万无一失)的方法,我非常乐意接受任何关于我将数据放入结构的方式的更改的建议C 试图扫描字符串时程序崩溃,c,C,扫描包含任意游戏结果的.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的safesscanf
。它在每个字符串参数之后,即%s
、%c
和的参数之后,都需要一个缓冲区大小[
格式。请参阅说明和示例。正如M Oehm指出的,您的sscanf_s
看起来可疑,请阅读:发生的是读取了文件的最后一行,而不是EOF。当循环返回时,fgets()
尝试读取一条以上的记录,但失败。数据文件行
可以保存15行,游戏结果
可以保存128条结果,但您使用相同的索引变量,i
来保存这两条结果。如果循环次数超过15次,则(!feof(inp2b))时,数据文件行
会出现缓冲区溢出
仍然是解析文件的错误逻辑,因为您不检查fgets
的返回值,之后您所做的任何操作都使用不确定的数据。您是对的,我说:程序现在运行,但您仍有工作要做,我正试图首先克服第一个问题:崩溃。干杯。使用此答案中所做的更改d上面的答案让它工作起来。谢谢Mateahhhh kay,我想知道缓冲区是什么意思,以及如何实现它。我会解决所有这些问题,然后看看我是怎么做的。此外,团队名称(例如Man Utd)在数据文件中表示为“ManUtd”,这样生活会更轻松。谢谢heaps!