4

我想从用户的键盘输入中读取两个字符串,这是我尝试过的代码:

char nomFichier[50], emp[100], empEtNomFichier[150];
printf("\nDonner le nom du fichier : ");
fgets(nomFichier, sizeof nomFichier, stdin);
printf("\nDonner l'emplacement du fichier : ");
fgets(emp, sizeof emp, stdin)
sprintf(empEtNomFichier, "%s/%s", emp, nomFichier);

问题是当我运行这段代码时,程序不会首先等待键盘输入fgets(),这就是程序的外观:

Donner le nom du fichier : 
Donner l'emplacement du fichier : /home/ee/Desktop
/home/ee/Desktop
4

3 回答 3

7

问题实际上是 fgets() 将终止换行符读入字符串。除非缓冲区填满,或者遇到没有换行符的 EOF,否则返回字符串中的最后一个字符将是 '\n'。

通过以下方式摆脱它:

n = strlen(nomFichier);
if (n>0 && nomFichier[n-1]=='\n') { nomFichier[n-1] = 0; }

...并对 if 块中的 emp 字符串执行相同的操作。还有一些方法可以使用带有 '\n' 作为分隔符的 strtok,或者使用带有 "%xx[^\n]%*c" 格式的 sscanf,而且我相信其他人有不同的喜欢的解决方案。(“xx”是该 scanf 格式的最大字符串长度,以十进制表示。)

顺便说一句,另一个问题不能通过 fflush 便携式解决,因为 fflush 不一定做任何事情。例如,GNU C 实现将 fflush(stdin) 视为无操作。

问题很可能是由于先前的 scanf() 读取了一个值,但没有读取换行符。在面向标记的输入 (scanf/fscanf) 和面向行的输入 (fgets) 之间切换的程序必须准备好处理剩余的行。

最快的解决方法是:

scanf("%*[^\n]%*c"); /* discard up to and including the next '\n' character */

...或更直接的:

int c;
while ( (c = getchar()) != EOF && c != '\n') { }

无论哪种方式,我都会把它放在一个静态函数中,让优化器决定是否内联它。

每次从 scanf() 切换到 fgets() 输入时,您都需要这样做。

于 2013-09-29T02:14:18.210 回答
0

尝试:

char nomFichier[50], emp[100], empEtNomFichier[150];
printf("\nDonner le nom du fichier : ");
fflush(stdout);
fgets(nomFichier, sizeof nomFichier, stdin);
printf("\nDonner l'emplacement du fichier : ");
fflush(stdout);
fgets(emp, sizeof emp, stdin)
sprintf(empEtNomFichier, "%s/%s", emp, nomFichier);

stdout 是行缓冲的,因此它不会在没有 \n 字符的情况下输出 - 尝试 fflush();

或尝试:

char buf[256]={0x0};
setvbuf(stdout, buf, _IONBF, 256);
于 2013-09-29T02:11:48.487 回答
0

其他答案都不适合我。我能够得到我正在寻找的行为,如下所示:

只需制作一个一次性变量并将换行符读入它之前fgets()

// . . . code above that leaves a \n in the stdin
char str[20];
char c;
printf("Prompt: ");
scanf("%c", &c);
fgets(str, 20, stdin);
printf("str = %s\n", str);

但是,正如下面的评论指出的那样,这不是一个干净的“修复”。

于 2021-12-30T22:46:31.810 回答