scanf 和 getchar 中对字符串的操作

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


字符串的特点

字符串,最大的几个特点就是

  1. 常用字符数组储存
  2. 可以使用指针指向第一个元素地址直接打印,(解引用是一个字符)
  3. 结尾是 \0
  4. print() 传参直接传输地址就可以
    在这里插入图片描述
    通过调试,使用 strcpy 后 看看 arr1
    在这里插入图片描述
    在一群 #### 中有一个 \0 ,说明字符时用 \0来结尾的,我们的 printf 也是检测到 \0 就停止打印, strlen 也是统计到 \0 前的字符场长度

输入函数使用的原理

这里的输入函数主要是 getchar 和 scanf
是从缓冲区读取输入,而不是从键盘中直接读取
我们打键盘,所有的都会保留在缓冲区中,然后程序执行的时候读取缓冲区
这就往往会导致一个情况,如果你是连续输入,除了第一次输入,其他输入时缓冲区不是空缓冲区
在这里插入图片描述

为啥要有缓冲区?

为了让低速的输入输出设备和高速的用户程序能够协调工作,并降低输入输出设备的读写次数。
理解仅供参考

  1. 我们键盘输入,如果直接读取键盘,那么我们每一次输入都要让程序去和硬件打交道,cpu要切换模式,这里耗费的时间长
    使用缓冲区,就减少了模式切换,大大提升效率
  2. 使用缓冲区,用户输入的全部输入到缓冲区中,如果是字符串,程序可以直接一次就把有效字符读取出来,如果使用读取键盘方式,用户输入一个字符,就要读取一个字符,要读取多次

getchar的使用

getchar

使用和使用原理

(int) getchar (void);

  1. 返回值是读取字符的 ascii 码值
  2. getchar在读取结束或者失败的时候,会返回EOF(定义为 -1)
    当我们要读取字符时
ch =  getchar()

用一个例子讲透getchar

写一个程序,输入一个密码,然后确认

  1. 第一个版本
    这个例子是有问题的,问题在哪里嘞?
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char ch = 0;
	char arr[20];
	printf("请输入密码:>");
	scanf("%s", arr);
	printf("请确认(Y/N)");
	ch = getchar();
	if (ch == 'Y')
	{
		printf("输入成功");
	}
	else
	{
		printf("输入失败");
	}
	return 0;
}

看看现象
在这里插入图片描述
输入密码之后,我还没来得及输入 Y/N 就直接输入失败了
为什么?
从原理看,我最后终止 scanf 输入是按了 回车键 但是 scanf 不会读取回车键 ,回车键就保留在缓冲区了
然后 getchar 读取缓冲区的回车键
直接输出 输入失败


  1. 第二个版本
    清空回车键,但是用例还是有问题
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char ch = 0;
	char arr[20];
	printf("请输入密码:>");
	scanf("%s", arr);
	printf("请确认(Y/N)");
	getchar();
	ch = getchar();
	if (ch == 'Y')
	{
		printf("输入成功");
	}
	else
	{
		printf("输入失败");
	}
	return 0;
}

我加了一个没有返回的 getchar 最后结果是这样的
在这里插入图片描述
但是,如果我添加空格,就会出问题
在这里插入图片描述
同理,scanf 读取到字符串的时候 会停下来,之后getchar 清空,但是缓冲区中有 ’ 456’ 一个getchar 无法清空,最终直接输入失败


  1. 第三个版本
#include<stdio.h>
int main()
{
	char password[20] = {0};

	printf("请输入密码:>");
	scanf("%s", password);

	//把缓冲区中的内容全读走
	while ( getchar() != '\n')
	{
		;
	}
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}

	return 0;
}

这个使用 while 将缓冲区中的剩余字符全部清空,应为 while 把执行写在条件中,所以 getchar 也把 回车 取出了

总结getchar

  1. 如何使用 getchar
  2. 缓冲区的概念
  3. 清空缓冲区的操作和原因

scanf的使用

scanf(“格式控制字符串”, 地址表列);

根据格式,放在指定地址中
格式控制常添加 %,如 %d,%f,%u,%c,%s 等
地址列表 常为变量地址 &a ,&b… 或者是字符串

常见使用

s字符串,读取到空白字符为止
c下一个字符,包括空白字符也读取
d/ud是 signed int ,u 是 unsigned int
^character任何字符非 character 都读取,读到 character 为止
p指针

空白字符:
在这里插入图片描述
常见的就是空格和回车

连续读取

常见的有全部读取到数组中

int main()
{
	char arr[20] = 0;
	int i = 0;
	while(scanf("%c",arr+i)!= EOF)
	{
		i++;
		dosomething();//某些操作
	}

}

值得注意的是,读取之后立刻就能够对读取的数据进行判断或者是其他操作
相对于先读取,再判断可以减少循环的次数


例子
要求:
在这里插入图片描述
链接:判断数组是不是有序数组

int main()
{
	int n = 0;
	int i = 0;
	int arr[51] = { 0 };
	int flag1 = 1;//升序,如果不升序了就换成0
	int flag2 = 1;//降序,如果不是降序就是0
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d", &arr[i]);
        if(i>0)
        {
            if (arr[i - 1] > arr[i])
		flag2 = 0;
	else if (arr[i - 1] < arr[i])
		flag1 = 0;
        }
     }
		
	if ((flag1 + flag2) >= 1)
		printf("sorted");
	else
		printf("unsorted");
	return 0;
}

解析:
在这里插入图片描述

scanf 读取字符和字符串

scanf 读取字符

读取字符和 getchar 的时候是一样的,缓冲区有什么读什么,需要在使用的时候清理缓冲区

	while ( getchar() != '\n')//清理字符串的模块
	{
		;
	}

读取字符串

有空格

test

int main()
{
	char s[20];
	char ch;
	gets(s);
	printf("%s\n", s);
	scanf("%s",s);
	printf("%s\n", s);
	while ((ch = getchar()) != '\n')
	{
		;
	}
	scanf("%[^\n]", s);
	printf("%s\n", s);
	scanf("%s\n", s);
	printf("%s\n", s);
	return 0;
}

结果
在这里插入图片描述
解析
在这里插入图片描述
有人可能会问,scanf不是要取地址吗?这里是字符数组,读取字符串会顺着将字符储存到相应的字符数组中
打印字符串直接使用地址就可以

总结scanf

  1. 注意字符和字符串输入的区别
  2. 清空缓冲区
  3. 连续读取和连续读取操作的方法
  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值