SCANF不断循环
嗯,我有这样的代码,以找到一个房间的油漆质量。SCANF不断循环
void get_room_size(char room_id, int * length, int * width) {
while (*length <= 0 && *width <= 0) {
printf("Enter length and width of room %c in feet: ", room_id);
if (scanf("%d,%d", length, width)) {
if (*length <= 0) {
printf("###Error! Length must be a positive value!\n");
}
if (*width <= 0) {
printf("###Error! Width must be a positive value!\n");
}
printf("\n");
} else {
printf("bad data");
*length = 0;
*width = 0;
}
}
}
基本上,如果我进入
一,1
它会发疯,并不断循环。有什么问题?
的原因,它是怎么回事“疯狂”如下。当scanf
失败以a
作为数字读取(因为它不是数字,很明显),它不会前进文件指针。
这就是为什么你不应该一般使用scanf
操作,故障可能离开文件指针在一个不确定的位置(例如,如果你只在3月12日的项目扫描)。
的另一个原因是,
scanf
意思是“扫描格式化”,你将很难找到什么比用户输入更多格式化。
不管怎样,回到失败。由于文件指针不先进,下次你再来做fscanf
,它会尝试读取a
再次(又一遍)。
如果你想为处理用户输入一个体面的功能,那没有比这里:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
这将用户的输入线,防溢保护(不像gets
或scanf
无界"%s"
)。
这也刷新到行结束时,如果输入太长,这将影响下次输入操作停止线的其余部分。
然后,您可以sscanf
缓冲你的心脏的内容没有任何的担忧重新文件指针。
下面的测试程序演示了如何使用这样的:
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
顺便说一句,你可能要重新审视你的逻辑,有效大小的房间。你现在有将允许一个房间由-42英尺:-)
输入为7这也是通常不是好的形式依靠输出值被设定为在进入特定的值。如果输入时长度和宽度为(例如)3和4,则此功能将立即退出,而不要求用户输入。
第一个问题可以通过使用||
代替&&
被固定。第二种方法是在函数开始时将变量初始化为0,以便输入循环。
为了完整起见,如果你把该原始片段上方具有以下(在include
报表及getLine()
功能)略作修改get_room_size()
功能:
static void get_room_size(char room_id, int * length, int * width) {
char buff[100];
*length = *width = 0;
while ((*length <= 0) || (*width <= 0)) {
printf("Enter length and width of room %c in feet: ", room_id);
int rc = getLine (NULL, buff, sizeof (buff));
if (rc == NO_INPUT) {
printf ("\nEnd of file encountered.\n");
return;
}
if (rc == TOO_LONG) {
printf ("\nInput too long, please retry.\n");
continue;
}
if (sscanf(buff, "%d,%d", length, width) != 2) {
*length = *width = 0;
printf ("\nInput not in desired form (<number>,<number>), "
"please retry.\n");
continue;
}
if ((*length <=0) || (*width <= 0)) {
*length = *width = 0;
printf ("\nBoth length and width must be greater than zero, "
"please retry.\n");
}
}
}
和非常简单的测试main()
,你”我将看到一个完整的程序,展示如何去做。
int main (void) {
int len, wid;
get_room_size ('x', &len, &wid);
printf ("Length is %d, width is %d.\n", len, wid);
return 0;
}
读取一个字符串,然后尝试将其解析为一个int。 –
您的scanf采取两个整数。 A是一个字符,认为你想要 scanf(“%c”,* room_id); scanf(“%d”,length);
我reccommend你单独做他们
我怀疑房间ID是已知的,因为它已经被传入(并且_not_作为可以被改变并传回的指针),并且它被用在'printf'中。 – paxdiablo
试试这个:
...
if (scanf("%d,%d", length, width) == 2) {
if (*length <= 0) {
printf("###Error! Length must be a positive value!\n");
}
if (*width <= 0) {
printf("###Error! Width must be a positive value!\n");
}
printf("\n");
} else {
printf("bad data");
*length = -1;
*width = -1;
}
你不把&在scanf()
语句,因此如何其读
if (scanf("%d,%d", &length, &width))
在你的scanf()语法中试试这个家伙的错误。 –
这不是问题...... scanf已指向长度和宽度。 – TheAJ
你有没有代码,可以读取“一个',所以它永远不会被读取。 –