【发布时间】:2022-06-16 18:26:20
【问题描述】:
我正在尝试 K&R 的一个简单练习,使用指针将 string2 附加到 string1 的末尾。如果发生溢出,即 string1 的缓冲区不能包含所有 string2 我想提示用户重新输入 string2 或退出。
我写了以下代码:
#include<stdio.h>
#include<string.h>
#define MAXLINE 1000
int get_input(char *s);
int str_cat(char *s, char *t);
void main()
{
char input1[MAXLINE], input2[MAXLINE], c;
get_input(input1);
check:
get_input(input2);
if((strlen(input1) + strlen(input2) + 2) <= MAXLINE)
{
str_cat(input1, input2);
printf("%s\n", input1);
}
else
{
input2[0] = '\0';
printf("String overflow\n Press: \n 1: Re-enter string. \n 2: Exit.\n");
scanf(" %d", &c);
if(c == 1){
input2[0] = '\0';
get_input(input2);
goto check;
}
}
}
int get_input(char *arr)
{
int c;
printf("Enter the string: \n");
while(fgets(arr, MAXLINE, stdin))
{
break;
}
}
int str_cat(char *s, char *t)
{
while(*s != '\0')
{
s++;
}
while((*s++ = *t++) != '\0')
{
;
}
*s = '\0';
}
最初,我使用书中提到的标准getchar() 函数来读取get_input() 中的输入,如下所示:
int get_input(char *arr)
{
int c;
printf("Enter the string: \n");
while((c = getchar()) != '\n' && c != EOF)
{
*arr++ = c;
}
*arr = '\0';
}
-
我是新手,我阅读了this 并理解了我的错误。我知道不应该使用不同的输入函数来读取标准输入,
'\n'留在输入流中,由getchar()选择导致我的条件失败。 -
所以,我决定使用
fgets()来读取输入并修改scanf("%d", &c),如scanf(" %d", c)线程中提到的那样。这确实有效(有点),但会导致我不想要的行为。
所以,我有几个问题:
-
在遇到
'\n'时读取输入以获取fgets()的更好方法是什么?while(fgets(arr, MAXLINE, stdin)) { break; } -
fgets()在遇到'\n' or EOF时停止读取该行并将其存储为输入。但是,它最终将'\n'存储在字符串的末尾。有没有办法防止这种情况发生,还是我必须手动覆盖'\n'? -
即使我使用了
scanf(" %d", &c)的修改版本,我的输出看起来像 这个:(https://imgur.com/a/RaC2Kc6)。尽管如此,当出现溢出情况时提示重新输入第二个字符串时,我得到了两次Enter the string:。修改后的scanf()是否影响了我的输入?我该如何纠正?
【问题讨论】:
-
您不需要在
scanf(" %d", &c)中添加空格,因为说明符%d和%f和%s(及其变体)会自动过滤前导空格。您确实需要%c和%[...]和%n的空格,否则它们会读取每个字符。了解不同格式如何处理空格是避免令人讨厌的问题的关键。 -
fgets保留的换行符(如果缓冲区中有空间)请参阅Removing trailing newline character from fgets() input 以获取防弹单行。 -
欢迎来到 StackOverflow。我注意到您为使您的第一个问题写得很好而付出了很多努力,我只想感谢您。
-
如果您可能需要拒绝输入(或者用户可能会输入垃圾),请不要使用
scanf,使用fgets输入字符串并使用@987654353 解析它@ 或其他。如果您需要拒绝输入,这比scanf可能会被垃圾阻塞的缓冲区简单得多:您只需输入另一个字符串。
标签: c scanf stdin fgets getchar