当前位置: 首页 > article >正文

C语言基础之输入输出

前言

本次博客会是最有料的博客了,这其中的问题尤其是scanf函数对新手很不友好

我们本次

1会讲解其他的一些输入输出函数,分析他们的优劣点

2本次的参考资料来自于 c primer plus

1scanf函数详解

首先大家了解过scanf的功能吗

1大家已经学到这里了,肯定知道,scanf是从输入流读取一个指定格式的数据

因为它的格式会变呀,而且它的参数也会变

关于这个参数改变其实涉及到了函数重载问题,以后会提到

1定义

它的参数先不讲,但是它的返回值得有讲头

我们看看他的返回值是个啥

scanf返回成功转换和分配的字段数;返回值不包括已读取但未分配的字段。返回值0表示未分配任何字段。如果在第一次尝试读取字符时遇到文件结尾字符或字符串结尾字符,则返回值为EOF。

那么这里又有一个问题了,scanf函数是如何读取的呢

2scanf函数的读取

接下来的这句话来自于c primer plus

1scanf读取字符

值得注意的是scanf在读取时可以用'\n' 结束

但是我们要让程序进行就必须要使用换行符

看代码

int main() {
    char ch1;
    char ch2;
    scanf("%c%c", &ch1, &ch2);
    printf("%c", ch1);
    printf("%c", ch2);
    return 0;
}

我们假设输入两个字符a 和‘ ’(空格)

看结果

结果就是只有a 空格看不见 此时读取到了两个字符

那么如果只输入一个a呢,当然在实操中还要输入'\n'来使程序继续哦

此时结果是一样的

但是读取到的不一样 scanf只读取到l一个字符

当然有很多人会有疑惑,那么多打印出来的'\n‘去哪里了

多出来的换行符就会出现在缓存区中只要你再次读取一次就不会再让你输入了

而是直接是下一个字符变为换行

看代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
    char ch1;
    char ch2;
    char ch3;
    scanf("%c%c", &ch1, &ch2);
    printf("%c", ch1);
    printf("%c", ch2);
    scanf("%c", &ch3);
    printf("%c", ch3);
    printf("理解了吗?上面有换行哦");
    return 0;
}

我们来看结果

本来要读三次的结果只读了两次,因为第三次直接把缓存区中的‘\n’读出来了

2scanf读取数字

那么读取数字有是怎样的呢

数字不像字符一样,数字有大有小,他可以是连续的

那你说怎样辨别两个不同的数字呢

既然是数字我们分辨不同的数字是使用空格 空行('\n')制表符的

举例

int main() {
    int a;
    int b;
    scanf("%d%d", &a, &b);
    printf("%d %d", a, b);
    return 0;
}

看结果

我们这里是使用空格作为区分数字,也就是一次读取的结束标志

大家可以使用其他的方式来多试几次

3scanf数字与字符混和读取

这个也同样有讲头

我们可以举例

int main() {
    int a;
    float b;
    char ch1;
    char ch2;
    scanf("%d%c%c%f", &a,&ch1,&ch2,&b);
    printf("%d %c %c %f", a,ch1,ch2,b);
	system("pause");
    return 0;
}

看看结果

这个结果是不是很奇怪呀,注意在混合使用scanf读取时一定要注意数字不要和字符通过空格分开

比如这样

是不是这样就不会出错了

当然我们细心的小伙伴发现了吗

代码中的scanf

 scanf("%d%c%c%f", &a,&ch1,&ch2,&b);

它的换位符%d%c%c%f他是不分开的

如果,我们是其分开是不是能够解决问题

直接看结果

看到吗,分开了,也同样没有问题

小总结

你们好幸运,笔者第一次遇到这个问题也是花了好多时间才解决,真的很烦

4scanf函数的读取字符串

这是在读取单词而不是字符串

在读取字符串时以空格 空行('\n')制表符结束,

当然当我们遇到文件结尾字符时可以直接结束

我们首先就得把那EOF文件结尾字符问题解决

我们先来看看EOF

EOF它的值为-1,话不多说直接验证

看代码

这个时候就可以验证了

那么我们怎么使用EOF呢

还是先初步了解一下吧

看代码

int main() {
    int num;
    int result = scanf("%d", &num);

    if (result == EOF) {
        printf("读取失败或已到达文件末尾\n");
    }
    else {
        printf("成功读取到数字:%d\n", num);
    }
	system("pause");
    return 0;
}

注意,本次代码是在vc环境下的

主要不知道为什么vs好像不支持scanf返回EOF

那让我们看看vs的结果

现在还搞不懂为什么

system("pause");是使程序不会一闪而过

要使用<stdlib.h>

我们看看vc结果 测试一番

看到没有当scanf遇到了文件结尾字符就会返回EOF

这是咱么第一次了解了文件结尾字符,以后会用作用name

当然这也同样说明了一件事

那么在告诉ctrl+z为模拟文件结尾字符

不同的编译器对于同一个代码可能会产生不同的结果

那么我们接下来看使用scanf输入字符串

首先

scanf都会从第一个非空白字符作为字符串的开始,以下一个空格 空行('\n')制表符作为结束,

大家看这个表可以看懂吗

如果说

我们后面还要继续输入字符或者字符串的话,j就会从剩余的序列中读入

这个我们前面就已经有过讲解了

还是让大家看看代码吧

大家看明明要读取两次可是只读取了一次

为什么呢

空格为第一次结束标志符

换行为第二次结束标志符

所以第二次scanf 接收的值直接为hup

所以scanf函数在接收字符串时是不能有空格的,这就是它的缺陷

那么还有一个疑问 %5s代表什么

它其实就是限定字符串的大小,如果遇到结束的标志那么即便没有达到长度

也会结束

所以呢,scanf只能接收连续的字符串

2getchar与putchar

他俩是单字符的i/o

我们直接看他们的定义

int getchar(void);

int putchar( int c );

当然他们是预处理的宏定义的代码块

putchar返回所写的字符为了指示错误或文件结束条件返回EOF

getchar返回读取的字符。为了指示读取错误或文件结束条件getchar返回EOF.

那么有了这两个就可以解决scanf不能输入接收空格的问题

他们同样也有结束条件遇到EOF就会结束

遇到'\n'就会把输入的值放入缓存区中,

看代码

我们可以输入一些字符,输出它

#include<stdio.h>
int main() {
    int ch;
    while ((ch = getchar()) != EOF)
    {
        putchar(ch);
    }
    return 0;
}

看结果

注意呀,ctrl+z不能出现在一行的末尾只能再另起一行

那么这样我们就可以使用这两个函数,输入输出带空格的字符串

当然 我们仍然要解释只要getchar不返回EOF那么就会一直输入输出

那么为什么ch是int类型的呢  原因在于EOF的值为-1

原因在于int有更大的范围

ok

再来讲解一个万能的清除缓存区代码

int ch;
while((ch=getchar())!=EOF&&ch!='\n');

这个可以把缓存区清理

3puts gets

char *gets( char *buffer );

如果成功,gets函数中的会返回其参数

也就是数组名

int puts( const char *string );

如果成功,返回一个非负值。如果失败,则返回EOF

作为接收打印字符串的函数

gets是有一定的用途的

他两也有相同的地方

gets读取输入,直到遇到换行符,丢掉换行符加入'\0'

把读到的字符串放入数组中

而puts

就是打印某个字符串

并且会自动在该字符串中加入'\n'

看代码

int main() {
 char a[100];
 gets(a);
 puts(a);
 puts("what can i say");
 puts("黑尼曼");
 system("pause");
    return 0;
}

看结果

是不是验证了

当然我们的数组必须要大于输入的字符串

否则会出现溢出的现象

所以很多编译器不支持gets的使用

从而又有一种输入函数的诞生

get_s(const char * s,int n)

就是比get多了一个整型数,其实就是为了防止越界

是把读取前n个字符防止越界其他与gets一样

最后

我们来给大家总结一波

1 输入输出是存在缓存区的

2回车是输入的结束标志,但本生是一个字符会存入到输入缓存区中

3解决scanf报错,

直接就来 #define _CRT_SECURE_NO_WARNINGS

最后祝大家开心


http://www.kler.cn/a/271795.html

相关文章:

  • Android createScaledBitmap与Canvas通过RectF drawBitmap生成马赛克/高斯模糊(毛玻璃)对比,Kotlin
  • 代码随想录算法训练营第三十八天-动态规划-完全背包-279.完全平方数
  • uniapp 地图添加,删除,编辑标记,在地图中根据屏幕范围中呈现标记
  • 最长递增——蓝桥杯
  • 智慧园区系统分类及其在提升企业管理效率中的创新应用探讨
  • C# lock使用详解
  • MongoDB从0到1:高效数据使用方法
  • python--剑指offer--10- I. 斐波那契数列
  • AtCoder ABC344 A-E题解
  • Gogs 创建新的仓库并提交代码
  • 链式二叉树--前序中序后序遍历,高度,节点个数问题
  • MyFileServer
  • 口腔管理平台 |基于springboot框架+ Mysql+Java+B/S结构的口腔管理平台 设计与实现(可运行源码+数据库+lw文档)
  • 唯一约束
  • PCM和I2S区别
  • 快速去除或提取视频中的任何声音,你学会了吗
  • linux解析域名指令 nslookup 或者 host
  • C++:菱形继承与虚继承
  • 数据分析 | NumPy
  • 爬虫的基本原理介绍,实现以及问题解决
  • Linux——线程池
  • C/C++整数和浮点数在内存中存储
  • Linux学习(4)——使用编辑器
  • 第十三届蓝桥杯省赛C++ C组《全题目+题解》
  • Xlua - 集成rapidjson(json序列化)
  • 力扣111---二叉树的最小深度(简单题,Java,递归+非递归)