为什么是scanf();跳过第一行?
所以在scanf之后,为什么是scanf();跳过第一行?,c,string,scanf,C,String,Scanf,所以在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 M
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
#包括
#包括
int main(int argc,const char*argv[]{
int i;
INTV;
printf(“输入材料编号:”);
scanf(“%d”和“&V”);fflush(stdin);
//插入材料
炭材料[V][50];
对于(i=0;i
使用fgets
而不是scanf
。换行符作为字符被后续的scanf
使用。这就是您面临此问题的原因。使用fgets
而不是scanf
。换行符作为字符被后续的scanf
使用。这就是您面临此问题的原因。在以下行中:
scanf("%[^\n]", &materia[i][50]);
您将输入的字符串存储在materiala[i][50]
的地址中,有效地将其存储在数组的边界之外
这里发生了一些有趣的事情,2D数组存储是连续的,就像它是一个一维向量一样,发生的事情是将第一个字符串存储在数组第二行的开头,第二个字符串存储在第三行,依此类推,将第一个字符串留空。这就是程序产生的输出的合理性
使用以下命令更正您的代码:
#include<stdlib.h>
//...
if(scanf(" %49[^\n]", materia[i] != 1) {
puts("Read error");
return EXIT_FAILURE;
}
#包括
//...
如果(scanf(“%49[^\n]”,material[i]!=1){
puts(“读取错误”);
返回退出失败;
}
49个字符+nul终止符为避免溢出,说明符开头的空格可避免消耗stdin
缓冲区中的空白字符。始终验证scanf
返回以避免读取错误
其他一些问题:
fflush(stdin)
应根据需要删除
- 如果消耗了足够的内存,可变长度数组可能会导致堆栈溢出,在这种情况下不太可能,但要记住这一点
行中:
scanf("%[^\n]", &materia[i][50]);
您将输入的字符串存储在materiala[i][50]
的地址中,有效地将其存储在数组的边界之外
这里发生了一些有趣的事情,2D数组存储是连续的,就像它是一个一维向量一样,发生的事情是将第一个字符串存储在数组第二行的开头,第二个字符串存储在第三行的开头,依此类推,将第一个字符串保留为空。这就是程序生成的输出的合理性
使用以下命令更正您的代码:
#include<stdlib.h>
//...
if(scanf(" %49[^\n]", materia[i] != 1) {
puts("Read error");
return EXIT_FAILURE;
}
#包括
//...
如果(scanf(“%49[^\n]”,material[i]!=1){
puts(“读取错误”);
返回退出失败;
}
49个字符+nul终止符为避免溢出,说明符开头的空格可避免消耗stdin
缓冲区中的空白字符。始终验证scanf
返回以避免读取错误
其他一些问题:
fflush(stdin)
应根据需要删除
- 如果消耗了足够的内存,可变长度数组可能会导致堆栈溢出,在这种情况下不太可能,但要记住这一点
程序中有几个错误
- 传递给
scanf
的数组错误
fflush(stdin)
是非标准的,尽管Windows支持它,但它不可移植。但是您不使用Windows,因为它不支持VLAchar material[V][50];
scanf
format“%[^\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;
}
#包括
int main(int argc,const char*argv[]{
int i;
INTV;
printf(“输入材料编号:”);
如果(扫描频率(“%d”,&V)!=1){
/*添加一些错误消息*/
返回1;
}
//fflush(stdin);//已删除
//插入材料
炭材料[V][50];
对于(i=0;i
关于换行符。格式规范%d
和%s
和%f
会自动过滤掉前导空格,但%c
和%[]
和%n
不会。scanf
函数在无法转换的第一个字符处停止,该字符留在输入缓冲区中。%[^\n]
告诉它在第一个换行符处停止。但是已经有一个换行符,从第一个%d
scanf开始,它需要被删除,也需要在后续的迭代中删除,添加空格就可以了。之后尝试删除它是笨拙的,不能保证有效
每次使用时都必须检查scanf
中的返回值。它是成功扫描的项目数。在这里,两种用法中都应该是1
。因此,如果一条语句中有两个项目,则其返回值必须是2
程序中存在多个错误
- T