这里是C语言的初学者。我正在尝试运行一个循环,将字符串和ints输入到struct的各个字段中。当提示输入“姓氏”时,用户可以按enter键,不需要其他输入,循环就应该结束。
问题是,使用此代码时,循环不会结束(姓氏和名字条目请求一起在同一行上运行),并且薪水的值总是错误的(0或某个较大的数字)。
while (employee_num <= 2)
{
printf("Enter last name ");
fgets(employee[employee_num].last_name, sizeof(employee[employee_num].last_name), stdin);
if(strlen(employee[employee_num].last_name) == 0)
break;
printf("Enter first name ");
fgets(employee[employee_num].first_name, sizeof(employee[employee_num].first_name), stdin);
printf("Enter title ");
fgets(employee[employee_num].title, sizeof(employee[employee_num].title), stdin);
printf("Enter salary ");
fgets(strng_buffer, 1, stdin);
sscanf(strng_buffer, "%d", &employee[employee_num].salary);
++employee_num;
getchar();
}如果我改为尝试此代码,我可以在第一次运行后正确退出循环,但在那之后无法退出(通过在姓氏部分按enter -也许\n我不能清除?):
char strng_buffer[16];
while (employee_num <= 5)
{
printf("Enter last name ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].last_name);
if(strlen(employee[employee_num].last_name) == 0)
break;
printf("Enter first name ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].first_name);
printf("Enter title ");
fgets(strng_buffer, sizeof(strng_buffer), stdin);
sscanf(strng_buffer, "%s", employee[employee_num].title);
printf("Enter salary ");
scanf("%d", &employee[employee_num].salary);
++employee_num;
getchar();
}我很好奇如何让它按预期工作,以及像这样的条目的最佳实践是什么(即使用sscanf,fgets等)。
提前感谢!
发布于 2013-01-23 12:27:27
假设Abhijit提到的修复方法,为什么要将第一个转换为第二个?您是否意识到,由于添加了sscanf,第二个应用程序的行为与第一个应用程序的行为不同?如果您的意图是缩短第一个,那么第二个似乎相当庞大。与其在场景中添加sscanf,为什么不声明一个struct employee *e = employee + employee_num;并重复使用它,而不是employee[employee_num]来缩短第一个呢
关于fgets的一个“最佳实践”是检查它的返回值。如果遇到EOF,你认为fgets会返回什么?如果fgets成功了,你认为它会返回什么?
关于scanf的一个“最佳实践”是检查它的返回值。关于scanf的返回值,我建议仔细阅读this scanf manual,回答以下问题:
int x = scanf("%d", &employee[employee_num].salary);如果我输入"fubar\n"作为输入,你认为x会是什么?"fubar\n"的'f'会去哪里?ungetc>D23ungetc>,你的下一个员工的姓氏会是什么?如果我在Windows上运行这段代码,并按CTRL+Z将D28ungetc>发送给Windows,你希望D33会是什么,假定scanf成功地将值放入两个变量y和z中
发布于 2013-01-23 11:35:10
遇到break语句时,循环过早中断
if(strlen(strng_buffer) == 0)
break;未初始化的字符缓冲区strng_buffer恰巧具有null作为导致strlen返回0的第一个字符
我相信你可能是有意
if(strlen(employee[employee_num].last_name) == 0)
break;作为循环终止符,这是您的部分中的一个打字错误导致了过早的循环退出。
发布于 2013-01-23 12:27:25
问题是fgets返回包含换行符(\n)的字符串。因此,即使用户在不输入信息的情况下按return,字符串也不会为空。此外,salary的缓冲区大小太小。
因此,要么在每个fgets上剥离\n,要么将检查更改为:
if(strlen(employee[employee_num].last_name) == 1) break;此外,在获取缓冲区时,将1更改为更大的值,例如
fgets(strng_buffer, 10, stdin);但是,如果您确实想要从每个fget中剥离\n,您可以这样做:
employee[employee_num].last_name[strlen(employee[employee_num].last_name)-1] = 0;您可以对每个字符串执行此操作,或者,更好的做法是创建一个执行此操作的函数。
编辑:如果你能保证用户在每次输入后都会按回车键,那么你就可以放心地假设这一点。但是,如果不总是这样,那么最后一个字符可能不是\n,这种剥离方式可能会导致问题。
https://stackoverflow.com/questions/14472004
复制相似问题