循环中的C程序scanf(“%[^ \ n]%* c”,...)
我必须编写一个新文件,其中必须有多个学生信息(如:Student_name, student_Surname, school_subject
和学生人数)一行,我必须输入新的学生,直到我输入END。我不得不使用printf和scanf。姓名和科目可以是多个单词当我尝试使用scanf("[^\n]*c", name)
时,我只能输入一个学生的信息,循环只是忽略休息,对于其他学生,我只能输入整数的学号。循环中的C程序scanf(“%[^ n]%* c”,...)
我的代码有什么问题?
int main() {
FILE *outputfile = NULL;
struct imenik {
char prezime[17 + 1];
char ime[13 + 1];
char predmet[20 + 1];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "w");
printf("Ucitaj ime ucenika: ");
scanf("%[^\n]%*c", ucenik.ime);
printf("Ucitaj prezime ucenika: ");
scanf("%[^\n]%*c", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf("%[^\n]%*c", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d", &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
fclose(outputfile);
}
的问题是在这里:
scanf("%d", &ucenik.bodovi);
这读取的次数,但之后,在没有阅读的换行符。因此,当循环重复时,它将该换行读取为下一个学生名称的空行输入。
你可以把它改成:
scanf("%d ", &ucenik.bodovi);
空间告诉它的数量后,任何空白跳过。
但实际上,最好将开头的的空格放在每个scanf
处,而不是在最后忽略换行符。有关说明,请参阅http://stackoverflow.com/questions/19499060/what-is-difference-between-scanfd-and-scanfd。因此,将其更改为:
printf("Ucitaj ime ucenika: ");
scanf(" %[^\n]", ucenik.ime);
printf("Ucitaj prezime ucenika: ");
scanf(" %[^\n]", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf(" %[^\n]", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d", &ucenik.bodovi);
OP的问题似乎没有循环。第一个问题是。 –
@VidorVistrom他在评论中说,他从帖子中删除了它。 – Barmar
他不应该有。它就像......你去看医生,告诉他我的妻子正在牙痛。请开一些药 –
我建议你实现这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define S_SIZE 32
#define T_SIZE 128
int main(void) {
FILE *outputfile = NULL;
struct imenik {
char prezime[S_SIZE];
char ime[S_SIZE];
char predmet[S_SIZE];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "a");
if (outputfile == NULL) {
perror("Fopen");
exit(EXIT_FAILURE);
}
char tmp[T_SIZE];
while (1) {
printf("Enter info separated with spaces: ");
fgets(tmp, T_SIZE, stdin);
if (strcmp(tmp, "END\n") == 0) {
break;
}
sscanf(tmp, "%s %s %s %d", ucenik.ime, ucenik.prezime, ucenik.predmet, &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
}
fclose(outputfile);
return 0;
}
有意使用'strncmp'而不是'strcmp'吗?如果您不知道这将意味着输入“ENDD \ n”,“END1654 \ n”或甚至“END31d6546esf16sdf687 \ n”将与“结束”没有区别,因为只评估了3个第一个字符。这种情况不应该被评估为错误吗?如果是,我推荐使用'strcmp(tmp,“end \ n)”' – nounoursnoir
同意'fgets()'和'sscanf()'是更好的选择,但是OP说“我必须使用printf和scanf”。而且这种解决方案只允许单个单词吗? OP说,“姓名和科目可以是多个词。” –
@nounoursnoir是的,你说得对,我写得很快。编辑。 –
你行:
scanf("%d", &ucenik.bodovi);
离开输入流中的换行符。在下一次呼叫scanf()
时立即退出,并且将换行符留下,等等。不要尝试向格式字符串添加尾随空格字符,如有些人所建议的:"%d "
。这会在输入结束时消耗换行符,并等待更多输入,直到遇到非空白字符或EOF
。
最简单的方法,就是去做你已经做丢弃换行符:
scanf("%d%*c", &ucenik.bodovi);
请注意,您应该使用scanf()
时读入一个字符串,以避免缓冲区溢出指定格式字符串,最大宽度:
scanf("%13[^\n]%*c", ucenik.ime);
此外,您应该检查outputfile
以确保文件已成功打开。实施循环
一种方法是第一个电话的地方scanf()
外循环,然后使用strcmp()
在while
语句来检查"END"
。在循环结束后,重复第一次调用scanf()
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
FILE *inputfile = NULL;
FILE *outputfile = NULL;
struct imenik {
char prezime[17 + 1];
char ime[13 + 1];
char predmet[20 + 1];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "w");
/* Did file open successfully? */
if (outputfile == NULL) {
perror("Unable to open file:");
exit(EXIT_FAILURE);
}
/* Specify maximum widths in calls to scanf() */
printf("Ucitaj ime ucenika: ");
scanf("%13[^\n]%*c", ucenik.ime);
while (strcmp(ucenik.ime, "END") != 0) {
printf("Ucitaj prezime ucenika: ");
scanf("%17[^\n]%*c", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf("%20[^\n]%*c", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d%*c", &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n",
ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
printf("Ucitaj ime ucenika: ");
scanf("%13[^\n]%*c", ucenik.ime);
}
fclose(outputfile);
return 0;
}
'我要编制新file' ......好吧,thate是一个问题...... –
的[可能的复制为什么我收到一个来自scanf循环的分段错误?](https://stackoverflow.com/questions/40327254/why-am-i-getting-a-segmentation-fault-from-scanf-loop) – Badda
显示你的代码或我们不能帮助您。 – Badda