前言:现在面临的c初学阶段,在刷题的过程中遇到很多关于字符串的输入问题, 在听了一些网课和找了一些后想自己总结一下, 希望有大佬能帮我指出文中内容的错误。(大一新生)
注释:下面的例子中的字符串数组都用arr表示。
一、scanf("%s", arr)
图一中的代码是输入一段字符串到字符串数组arr中并输出,此例中的 scanf("%s", arr) 正是起到了输入字符串的作用, scanf("%s", arr) 的局限性在于不能完整读取含有空格的字符串,如:当输入 “hello world” 时图一中的程序只能读取到 “hello” 而后面的空格和 “world” 无法一次全部读取。
//图一
#include <stdio.h>
int main() {
char arr[100] = {0};
scanf("%s", arr);
printf("%s\n", arr);
return 0;
}
如果要完整读取 “hello world” ,可以如图二中的程序所示创建两个字符串数组来分别保存 “hello” 和 “world” 。但也存在缺陷,就是 “hello world” 中的空格无法打印,这正与 scanf("%s", arr) 的特点有关 它根本不会读入空格,就算你开始输入时时只输入空格,当按下回车后, scanf("%s", arr) 并不会读取你的空格,而是继续等待你输入字符串。用图二程序输入 “hello world” 后, scanf("%s", arr) 读取了 “hello” 而遇到空格后结束读取,但并未从健盘缓冲区中跳过空格(标记句一),所以 scanf("%s", arr1) 从空格开始读取,但由于无法读取空格,最终只读取 “world” 。
//图二
#include <stdio.h>
int main() {
char arr[100] = {0};
char arr1[100] = {0};
scanf("%s", arr);
scanf("%s", arr1);
printf("%s\n", arr);
printf("%s", arr1);
return 0;
}
证明标记句一
在图三程序中输入 "hello world" ,图中的 scanf("%c", &ch) 读取到了空格,所以说明,在 scanf("%s", arr) 读取时,遇到空格后停止读取并不会跳过空格。
//图三
#include <stdio.h>
int main() {
char arr[100] = {0};
char arr1[100] = {0};
char ch = '#';
scanf("%s", arr);
scanf("%c", &ch);
scanf("%s", arr1);
printf("%s\n", arr);
printf("%s\n", arr1);
printf("%c**", ch);
return 0;
}
二、scanf("%[^\n]%*c",arr)
由于第一种方法的局限性,继续介绍另一种方法输入字符串,图四中的程序就解决了上面 scanf("%s", arr) 不能读取空格的问题,在 scanf("%[^\n]%*c",arr) 中 “%[^\n]%*c” 这句话的意思是碰见了回车就退出,然后把缓冲区里面的内容按字符串格式输入 arr 中,回车依然留在缓冲区。其中 "%[^\n]" 表示读入一个字符串,遇到 '\n' 停止,并设置末尾的 '\0' 。^ 是“非”的意思,意思就是说把一个非 “\n” 字符读入字符串,直到遇到 “\n” 停止输入。而 “%*c” 则是代表读入一个字符到缓冲区,但是不向任何地方输入。这样,就解决了字符串后边的 “\n” 对下面数据的影响,如果不加 “%*c” 的话,则大多数情况下需要在 scanf 前加一句 getchar() 来消除回车的影响。
//图四
#include <stdio.h>
int main()
{
char arr[100];
scanf("%[^\n]%*c",str);
printf("%s", str);
return 0;
}
三、用 %c 循环输入字符组成字符串
图五中 ch 为字符变量,充当字符数组 arr 的值,该程序先将字符通过 scanf("%c", &ch) 保存在 ch变量中,再通过循环将 ch 传给字符串数组 arr 。
//图五
#include <stdio.h>
int main()
{
char arr[100];
char ch;
int i = 0;
while(scanf("%c", &ch) && ch != '\n')
{
arr[i++] = ch;
}
arr[i] = '\0';
printf("%s", arr);
return 0;
}
四、 用 getchar() 函数循环输入字符组成字符串
图六中的程序与图五基本一样,在这里不过多赘述了。
//图六
#include <stdio.h>
int main()
{
char arr[100];
char ch;
int i = 0;
while((ch = getchar()) != '\n')
{
arr[i++] = ch;
}
arr[i] = '\0';
printf("%s", arr);
return 0;
}
五、gets(arr) 函数
gets() 函数的原型为 char *gets(char *str),参数类型为 char* 型,即 arr 可以是一个字符指针变量名,也可以是一个字符数组名。图七中 gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 arr 所指向的内存空间。值得注意的是,使用 gets() 时,系统会将最后输入的换行符从健盘缓冲区中取出来,然后丢弃,所以缓冲区中不会遗留换行符(标记句二)。这就意味着,如果前面使用过 gets(),而后面又要从键盘给字符变量赋值的话就不需要吸收回车清空缓冲区了,因为缓冲区的回车已经被 gets() 取出来扔掉了。
//图七
#include <stdio.h>
int main()
{
char arr[100];
char *arr1 = arr;
gets(arr1);
printf("%s\n",arr1);
return 0;
}
证明标记句二
我们看到,没有清空缓冲区照样可以输入 “!” ,因为 gets() 已经将缓冲区中的回车取出来丢掉了。如果前面使用的不是 gets() 而是 scanf,那么通过键盘给 ch 赋值前就必须先使用 getchar() 清空缓冲区。
//图八
#include <stdio.h>
int main()
{
char arr[100];
char ch;
gets(arr);
printf("%s\n", arr);
scanf("%c", &ch);
printf("ch = %c**\n", ch);
return 0;
}