所以在scanf()之后的 printf();
跳过第一行,我读过一些问题,告诉。 "%[^\n]"
必须 " %[^\n]"
来跳过换行。 我已经尝试了这两种方法,但还是打印出同样的结果,现在我不知道为什么它不工作。
Example input
Enter number of Materi: 4
Materia 1 name : a
Materia 2 name : b
materia 3 name : c
materia 4 name : d
Output:
Materia - 1 : R╒fu
Materia - 2 : a
Materia - 3 : b
Materia - 4 : c
#include<stdio.h>
#include<windows.h>
int main(int argc, const char *argv[]){
int i;
int V;
printf("Enter number of Materi: ");
scanf("%d", &V); fflush(stdin);
//Insert materia
char materia[V][50];
for(i = 0; i < V; i++){
printf("Materia %d name : ", i+1);scanf("%[^\n]", &materia[i][50]);fflush(stdin);
}
for(i = 0; i < V; i++){
printf("Materia - %d: %s\n", i+1, materia[i]);
}
system("pause");
return 0;
}
有几个错误的程序
传递给 scanf
是错误的。
fflush(stdin)
是非标准的,虽然Windows确实支持它,但它不具备可移植性。但你没有使用Windows,因为它不支持VLA------。char materia[V][50];
的新行。scanf
格式化 "%[^\n]"
将停止在,已经是输入缓冲区的下一个字符。
的返回值,已经是输入缓冲区中的下一个字符。scanf
没有被检查。它是成功扫描的项目数量。
因为输入的字符串长度不受限制,所以可以出现缓冲区溢出。
下面是调整后的代码。
#include<stdio.h>
int main(int argc, const char *argv[]){
int i;
int V;
printf("Enter number of Materi: ");
if(scanf("%d", &V) != 1) {
/* add some error message */
return 1;
}
// fflush(stdin); // removed
//Insert materia
char materia[V][50];
for(i = 0; i < V; i++){
printf("Materia %d name : ", i+1);
// add a space to filter the newline
// correct the array passed
// and restrict the length to prevent buffer overflow
if(scanf(" %49[^\n]", materia[i]) != 1) {
/* add some error message */
return 1;
}
// fflush(stdin); // removed
}
for(i = 0; i < V; i++){
printf("Materia - %d: %s\n", i+1, materia[i]);
}
return 0;
}
关于换行。格式规格 %d
和 %s
和 %f
自动过滤掉前导空格,但 %c
和 %[]
和 %n
没有。的。scanf
函数停止在它们不能转换的第一个字符上,即留在输入缓冲区中。缓冲区中的 %[^\n]
叫它停在第一个新行。但那里已经有一个了,从第一个新行开始。%d
scanf,它需要被移除,也是在后续的迭代中,添加空间就可以完成这个工作。之后再想删除它是很笨拙的,而且不保证能成功。
你必须检查 scanf
每次使用时。它是成功扫描的项目数量。这里,它应该是 1
在两个用途中。因此,如果你在一条语句中包含两个项目,它的返回值必须是 2
.
在这一行中。
scanf("%[^\n]", &materia[i][50]);
你把输入的字符串存储在了地址为 materia[i][50]
,有效地将其存储在数组的边界之外。
这里发生了一些有趣的事情,二维数组的存储是连续的,就像它是一个一维向量一样,发生的事情是你把第一个字符串存储在数组第二行的开头,第二个存储在第三行,以此类推,留下第一个空。这就是程序产生输出的合理性。
纠正你的代码与。
#include<stdlib.h>
//...
if(scanf(" %49[^\n]", materia[i] != 1) {
puts("Read error");
return EXIT_FAILURE;
}
49个字符+nul结束符以避免溢出, 在指定符的开头加一个空格以避免占用空字符 stdin
缓冲区。始终验证 scanf
返回,以避免阅读错误。
其他一些问题。
fflush(stdin)
应删除为 fflush
是为了在输出流上调用.
如果消耗了足够的内存,可变长度的数组可能会导致堆栈溢出,在这种情况下,它的可能性不大,但这是需要注意的。
使用 fgets
而不是 scanf
. 新行字符会被您后续的 scanf
. 这就是为什么你面临这个问题。