我有这个代码可以找到房间的油漆质量。
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;
}
}
}
基本上,如果我输入
A,1
它会疯狂并继续循环。问题是什么?
答案 0 :(得分:5)
它变得“疯狂”的原因如下。当scanf
失败以a
作为数字读取时(因为它显然不是数字),它将不会推进文件指针。
这就是为什么你一般不应该使用scanf
操作的原因之一,失败会使文件指针处于不确定的位置(例如,如果你只扫描12个项目中的3个)。
另一个原因是
scanf
表示“扫描格式化”,您将很难找到比用户输入更多的未格式化。
无论如何,回到失败。由于文件指针未提前,下次您返回fscanf
时,它会尝试再次读取a
(并且一次又一次)。< / p>
如果你想要一个像样的功能来处理用户输入,那么请看这里:
#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英尺的范围内输入一个房间: - )
依赖于输入时设置为特定值的输出值通常也不是好的形式。如果长度和宽度(例如)在输入时为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;
}
答案 1 :(得分:0)
你的scanf接受两个整数。 A是一个角色,想你想要 scanf(“%c”,* room_id); scanf(“%d”,长度);
我建议你单独做它们
答案 2 :(得分:0)
试试这个:
...
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;
}
答案 3 :(得分:-1)
你不放&amp;在scanf()
语句中如何阅读
if (scanf("%d,%d", &length, &width))