被困在c程序中如何在进程中间停止scanf



我正在编写一个小程序,输入由3个字母组成的国家名称和该国在奥运会上获得的奖牌数量,除非输入"结束"一词,否则该程序将一直要求输入。我写了一段时间的循环来做这件事,但我似乎无法停止

//Program calculate the winner of olympics based on metal input
#include<stdio.h>
#include<string.h>
int main (void)
{
int maxMedals=0, tempGold=0, tempSilver=0, tempBronze=0,tempSum;
char country[3];
char winner[3];
printf("no o o    O L Y M P I C    o o o");
printf("n o o      S C O R E S      o on");
printf("Enter country code, # gold, # silver, # bronzen");
while ((strcmp(country,"end"))!=0)
{
printf("==>");
scanf("%s %d %d %d",&country, &tempGold, &tempSilver, &tempBronze);
tempSum=tempGold+tempSilver+tempBronze;
if (maxMedals<tempSum)
{
maxMedals = tempSum;
strcpy(winner, country);
// printf("n %s", winner);
}
else
{
maxMedals=maxMedals;
}
}
printf("nwe reached heren");
printf("nWinner is %s with %d medalsn", country, maxMedals);
return 0;
}

问题是country只有3个字符长。在C中,scanf写入一个十六进制0字符来指示字符串的末尾,而strcmp则对一直到十六进制0的字符串进行比较(至少在字符串不同之前),因此"end"至少需要4个字符。

如果只有3的空间,并且写入3+十六进制0,则会溢出到未知内存中,导致未定义的行为。通过在我的机器上打印country,它打印"endend",这意味着winner在内存中似乎直接在country之后,所以它打印这两个,因为printf也一直持续到它找到十六进制0,但是,由于这是未定义的行为,所以不能保证这种行为,并且在不同的编译器上可能会有所不同。

尝试使其成为4个字符:

char country[4];

此外,您的循环不正确-您仍然处理"end",因为您只在处理后检查它。

处理这个问题的两种方法:

  • scanf后面放一个if语句,检查"end"是否为break
  • 在while循环的前面放一个scanf,在while环路的末尾放一个(所以有两个相同的scanf)
scanf("%s",&country);
if (strcmp(country,"end") == 0)
break;
scanf("%d %d %d", &tempGold, &tempSilver, &tempBronze);

希望这个改变能奏效。首先,您获得国家的输入,如果不是end,则继续获取其他选项。即使在一行中输入了四个参数,这也会起作用。

您可以按如下方式中断scanf。。因此,当您输入"end"时,您将退出while

scanf("%s",country);
if(strcmp(country,"end")==0) 
break;
scanf("%d %d %d",&tempGold, &tempSilver, &tempBronze);

您在输入之前将country与"end"进行比较,当您输入end 1 1 1时,程序将停止。但是您的代码可能会导致缓冲区溢出,因为countrywinner被声明为char country[3];char winner[3];,C中的字符串最后需要一个额外的作为终端字符。如果您只需要输入一个"结束"就可以终止程序,只需按照您所说的拆分scanf即可。

最新更新