我有这个问题要解决,我基本上需要允许用户输入最多 80 个字符的文本。输入字符串后,程序将必须遍历每个字符并一次打印一个,但用不同的字符($、#、@、* 和 =)更改元音。 我想我已经能够编写这样的代码了,但是如果用户输入的文本中有一个空格,程序将只打印空格之前的文本,空格之后的所有内容都不会被打印。
例子:
input: someTEXT!eg45a6I7uX
output:s*m#T#XT!#g45$6@7=X
但是:
input: Hello Students
output: H#ll*
{
char text[80];
scanf("%s", text);
int current =0;
printf(">\n");
while(text[current] != '\0')
{
switch(text[current])
{
case 'a':
printf("$");
break;
case 'A':
printf("$");
break;
case 'e':
printf("#");
break;
case 'E':
printf("#");
break;
case 'i':
printf("@");
break;
case 'I':
printf("@");
break;
case 'o':
printf("*");
break;
case 'O':
printf("*");
break;
case 'u':
printf("=");
break;
case 'U':
printf("=");
break;
default:
printf("%c", text[current]);
}
++current;
}
}
在
scanf
的调用中使用以下格式字符串
char text[80];
scanf(" %79[^\n]", text);
注意格式化字符串中的前导空格。它允许跳过空白字符,例如对应于按下的键 Enter 的新行字符
'\n'
在之前调用 scanf
. 后将保留在输入缓冲区中
至于你调用 scanf 时的格式字符串
scanf("%s", text);
然后它读取一系列字符,直到在输入缓冲区中遇到空白字符。而且它是不安全的,因为由于没有长度修饰符,可以写到字符数组之外。
还可以减少switch语句中的代码编写例如
case 'a': case 'A':
putchar( '$' );
break;
或
case 'a':
case 'A':
putchar( '$' );
break;
代替
case 'a':
printf("$");
break;
case 'A':
printf("$");
break;
正如其他答案所指出的,
scanf("%s", text)
在遇到空格时停止。我建议使用 fgets()
而不是 scanf()
。它更安全(不用担心缓冲区溢出),并且更容易阅读整行。
另外,当您需要处理这种情况时,检查可能失败的函数的返回值。
Up to 80 characters,大概意思是最多包含80个字符,但是一个字符串的末尾有一个额外的
'\0'
,这意味着你至少需要81个字节。我什至会为潜在的 '\n'
字节添加另一个字节。
C 中的字符文字是
int
类型并且具有正值(sizeof(int)==sizeof(char)
可能有一些例外,但让我们忽略这种奇怪的系统)。如果您使用 ASCII,那么所有字符在转换为 char
后仍将是正数,但是这可能会随着单字节非 ASCII 字符而改变。因此,使用unsigned char
作为缓冲区。
您可以通过这种方式改善开始:
#define TEXT_SIZE (80+1+1) //+1 for '\n', +1 for '\0'
unsigned char text[TEXT_SIZE];
if( !fgets(text,TEXT_SIZE,stdin) ) //Check for errors
{ perror("cant read from stdin"); exit(1) }
size_t current =0; //size_t is the "correct" type for array indexing
puts(">");
....
问题出在对
scanf()
的调用中。
scanf("%s", text);
scanf()
忽略空格右侧的所有内容。考虑使用 fgets()
代替:
fgets (text, sizeof text, stdin);
并检查它的返回值,它返回
NULL
表示失败。
或者,你可以做
scanf(" %79[^\n]", text);
按照@Vlad 的建议,但我不推荐这个。
这个问题是因为scanf函数遇到空格没有从缓冲区中提取字符。事实上,你只是输入了 Hello,所以这是结果。