当我从 stdin
中获取一个对于 c
来说太大的值时,重置不会按预期运行。用户将被重新提示输入代码,但在输入后会在需要输入的地方显示一个额外的新行,而不是长度检查失败。
void clear(void) {
while (getchar() != '\n')
;
}
int add_flight(code_t codes[], int lf) {
char c[MAX_CODE_LEN + 1];
int s = 0;
while (s == 0) {
printf("Enter code>\n");
if (fgets(c, sizeof c, stdin)) {
printf("%s", c);
if ('\n' == c[0]) {
printf("Invalid input\n");
} else if (c[sizeof c - 1] == '\0' && c[sizeof c - 2] != '\n') {
clear();
printf("Invalid input\n");
memset(c, 0, sizeof c);
} else {
strcpy(codes[lf].id, c);
s = 1;
break;
}
}
}
return 0;
}
如有任何帮助,我们将不胜感激。
最佳答案
你的代码有几个问题:
clear
函数不测试文件结尾,如果标准输入在没有尾随换行符的情况下关闭,则会导致无限循环,就像从空文件重定向输入时的情况一样。<- 超长输入行的测试不正确:如果输入未填充数组,则数组的最后一个字符未定义。您应该在去除尾随换行符后测试
strlen(c) == sizeof(c) - 1
。 c
是一个非常容易混淆的char
数组名称。此名称通常用于int
以接收字节值。将数组命名为buf
以提高可读性。memset
没用,因为您要将新行读入数组。- 缺少
code_t
的定义。如果其id
成员数组的大小不至少为MAX_CODE_LEN + 1
,则行为未定义。 - 此外,您将结尾的换行符复制到
codes[lf].id
,这可能是不正确的。 - 如果
id
定义为包含MAX_CODE_LEN
个字符,即char id[MAX_CODE_LEN + 1];
用于额外的空终止符,buf
应该有一个额外的字节用于用户输入的换行符,因此char buf[MAX_CODE_LEN + 2];
修改后的版本:
int clear(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int add_flight(code_t codes[], int lf) {
char buf[MAX_CODE_LEN + 2];
for (;;) {
printf("Enter code>\n");
if (fgets(buf, sizeof buf, stdin)) {
printf("%s", buf);
/* remove the trailing newline if present */
size_t len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n')
buf[--len] = '\0';
if (len == sizeof(buf) - 1) {
/* line too long: consume the rest of the input line */
printf("Invalid input\n");
if (clear() == EOF)
break;
} else if (len == 0) {
/* empty line */
printf("Invalid input\n");
} else {
strcpy(codes[lf].id, buf);
return 1; // return success
}
} else {
break;
}
}
return 0; // premature end of file: return failure
}
关于c - 使用 memset 时,数组未正确重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55783655/