解析C语言入门基础之输入和输出

您所在的位置:网站首页 c语言数据的输入和输出 解析C语言入门基础之输入和输出

解析C语言入门基础之输入和输出

2022-06-06 12:52| 来源: 网络整理| 查看: 265

01

标准输入和标准输出

在C语言里要使用标准输入和标准输出必须包含stdio.h头文件,常用的标准输出和标准输入函数是printf和scanf,其中printf用来在标准输出中输出信息,而函数scanf则用来从标准输入中读取信息。

那么什么是标准输入和标准输出呢?

在Linux中进程通常会自动打开三个标准文件,即标准输入文件(stdin)通常对应文件描述符0;

标准输出文件(stdout)对应文件描述符1和标准错误输出文件对应文件描述符2(stderr)。进程将从标准输入文件中读取输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。02

标准输入函数

在stdio.h中scanf声明如下:

/* Read formatted input from stdin. This function is a possible cancellation point and therefore not marked with __THROW. */ extern int scanf (const char *__restrict __format, 。。.) __wur;

使用Mac或Linux的同学,在终端上输入man scanf回车即可学习scanf函数的用法。我们可以看到注释上说明,scanf从标准输入stdin输入读取数据,在glibc中stdin的定义如下:

/*stdio.c*/ FILE *stdin = (FILE *) &_IO_2_1_stdin_; /*libio.h*/ extern struct _IO_FILE_plus _IO_2_1_stdin_; /*libioP.h*/ struct _IO_FILE_plus { FILE file; const struct _IO_jump_t *vtable; };

从以上代码我们可以知道,最终stdin是一个FILE文件流指针,我能继续追踪FILE类型为何物。

/* * stdio state variables. * * The following always hold: * * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR), * _lbfsize is -_bf._size, else _lbfsize is 0 * if _flags&__SRD, _w is 0 * if _flags&__SWR, _r is 0 * * This ensures that the getc and putc macros (or inline functions) never * try to write or read from a file that is in `read‘ or `write’ mode. * (Moreover, they can, and do, automatically switch from read mode to * write mode, and back, on “r+” and “w+” files.) * * _lbfsize is used only to make the inline line-buffered output stream * code as compact as possible. * * _ub, _up, and _ur are used when ungetc() pushes back more characters * than fit in the current _bf, or when ungetc() pushes back a character * that does not match the previous one in _bf. When this happens, * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. * * NB: see WARNING above before changing the layout of this structure! */ typedef struct __sFILE { unsigned char *_p; /* current position in (some) buffer */ int _r; /* read space left for getc() */ int _w; /* write space left for putc() */ short _flags; /* flags, below; this FILE is free if 0 */ short _file; /* fileno, if Unix descriptor, else -1 */ struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ int _lbfsize; /* 0 or -_bf._size, for inline putc */ /* operations */ void *_cookie; /* cookie passed to io functions */ int (* _Nullable _close)(void *); int (* _Nullable _read) (void *, char *, int); fpos_t (* _Nullable _seek) (void *, fpos_t, int); int (* _Nullable _write)(void *, const char *, int); /* separate buffer for long sequences of ungetc() */ struct __sbuf _ub; /* ungetc buffer */ struct __sFILEX *_extra; /* additions to FILE to not break ABI */ int _ur; /* saved _r when _r is counting ungetc data */ /* tricks to meet minimum requirements even when malloc() fails */ unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ unsigned char _nbuf[1]; /* guarantee a getc() buffer */ /* separate buffer for fgetln() when line crosses buffer boundary */ struct __sbuf _lb; /* buffer for fgetln() */ /* Unix stdio files get aligned to block boundaries on fseek() */ int _blksize; /* stat.st_blksize (may be != _bf._size) */ fpos_t _offset; /* current lseek offset (see WARNING) */ } FILE;

看到这个结构体内部一大堆成员变量不要慌,我们重点关注里面的close、read、seek和write函数指针。我们在调用scanf函数时正是通过这几个函数指针间接调用系统函数close、read、seek和write实现标准输入关闭、读取、偏移和写功能。

int (* _Nullable _close)(void *); int (* _Nullable _read) (void *, char *, int); fpos_t (* _Nullable _seek) (void *, fpos_t, int); int (* _Nullable _write)(void *, const char *, int);

从函数声明我们知道scanf返回一个int型返回值,在调用时scanf,返回正整数表示从标准输入读取到的有效数据数量,返回0表示没有输入或者输入不正确,返回负数表示发生了从标准输入读取数据发生了错误。下面我们使用scanf从标准输入读取数据的代码。

int num = 0; float f_num = 0; int count = scanf(“%d”, &num); scanf(“%f”, &f_num); scanf_s(“%d”, &num);

在scanf中输入数据并将数据保存在变量num和f_num中,调用scanf输入数据必须要用%,%d表示输入一个整数,%f表示输入一个单精度浮点数,其他数据类型的数据参考C语言入门基础之变量和数据类型,count保存scanf输入数据的有效数。

看到这里可能有人会有疑问,为什么调用scanf从标准输入信息,需要对变量取地址,为什么要设计成这样?这里就要涉及到后面会学到的知识:指针。在C语言里函数传参方式有2种,一种是传值另外一种是传指针。通过传值方式形参拷贝实参,得到一个实参副本对实参副本进行修改不会影响实参,而传指针方式,将会得到实参的地址,通过指针解引用可以间接修改实参的值。

那么回到scanf函数那里,我们通过对变量进行取址,scanf函数内部有一个指针,将变量地址值赋给内部指针,再将标准输入的值赋值给实参,实参变量因此获得标准输入的值。

在代码片段我们还看到scanf_s这个函数(scanf_s不是C标准库函数),由于scanf函数并不是安全的,在有些编辑器上默认禁止使用scanf,如果使用则需要打开一个宏,而scanf_s是一些厂商提供的scanf函数安全版本,两者使用方法一模一样。

03

标准输出函数

在stdio.h中printf函数声明如下:

/* Write formatted output to stdout. This function is a possible cancellation point and therefore not marked with __THROW. */ extern int printf (const char *__restrict __format, 。。.);

看到这里是不是很熟悉?printf函数的返回值也是int型,调用printf函数将会返回输出字符个数,出错则返回一个负数。

同样在Linux/Mac平台的终端上输入man printf函数可以查看函数的详细使用方法(任何C标准函数都可以在Linux/Mac平台上输入man+函数名的方式查看函数使用方法)。下面是我们使用printf函数在标准输出中输出数据的代码。

int output_count = printf(“num = %d ”, num); printf(“output_count = %d ”, output_count); output_count = printf(“f_num = %f ”, f_num); printf(“output_count = %d ”, output_count);

在代码片段里我们看到一个 字符,在C语言里这是一个换行符。看到这里是不是又有疑问了,为什么printf函数输出变量值时不需要对变量取地址?这就回到前面我们说过的问题了,在C语言里传值,形参是实参的副本,形参修改了不会影响到实参。而printf函数只是在标准输出中输出信息,不会修改实参的值,因此使用传值方式。

那么标准输出是什么呢?从print函数声明代码注释上看,标准输出正是stdou,我们继续在glibc中继续追踪stdout到底是什么?在stdout.c中我们看到stdout和stderr定义如下:

FILE *stdout = (FILE *) &_IO_2_1_stdout_; FILE *stderr = (FILE *) &_IO_2_1_stderr_;

我们发现stdout、stderr和stdin的定义一模一样都是一个FILE类型指针,那么使用方式就和stdin一样了,区别则在于stdin和文件描述符0绑定,stdout和文件描述符1绑定,stderr和文件描述符2绑定。

04

结语

后面讲解C语言知识时我会穿插有Linux相关知识,讲解C语言不能仅仅停留在语法层面。据我的观察,很多人学习了C语言语法后很迷茫,不知道C语言能做什么,根本原因就是你没有了解某个平台的系统编程API。Linux是一个开源操作系统,结合Linux学习C语言将会更加有趣,在Linux上进行C语言开发绝对是最佳选择。

编辑:jq

原文标题:C语言入门基础之输入和输出

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

扫一扫,分享给好友

复制链接分享 评论

发布评论请先 登录

相关推荐

AWStudio社区版重大升级 支持高中低端全平台运行 今天我们迎来了AWStudio社区版的重大升级。AWStudio v1.1支持从云端获取自定义控件、.... 的头像 科技绿洲 发表于 06-06 11:55 • 49次 阅读 AWStudio社区版重大升级 支持高中低端全平台运行 SM2258XT开卡工具 SM2258XT开卡工具免费下载。 发表于 06-06 10:08 • 3次 阅读 如何给一个变量设置一个别名? 在plugin.c中,提供一个函数func_init,当动态库被main dlopen之后,这个函数.... 的头像 strongerHuang 发表于 06-06 09:33 • 100次 阅读 为什么C++单例模式不能直接全部使用static变量和static函数呢? 通过getInstance()函数获取单例对象,这种模式的关键之处不是在于强迫你用函数来获取对象。关.... 的头像 Linux爱好者 发表于 06-05 14:14 • 54次 阅读 I-Pi SMARC套件可加速工业应用的原型开发   当您准备从原型过渡到生产时,I-Pi Carrier的开源规范可以作为希望创建自己的载体的开发人.... 的头像 星星科技指导员 发表于 06-02 16:39 • 713次 阅读 I-Pi SMARC套件可加速工业应用的原型开发 动态链接过程中是如何进行符号重定位的 并且把代码中所有使用的外部符号(变量、函数),都进行了重定位(即:把变量、函数的地址,都填写到代码段.... 的头像 Linux爱好者 发表于 06-02 14:52 • 72次 阅读 List集合:多线程快速处理 抛出:SecurityException - 如果安全管理器存在并且关闭,此 ExecutorSer.... 的头像 Android编程精选 发表于 06-02 11:24 • 123次 阅读 SMTube流媒体应用 ./oschina_soft/Atraci.zip 发表于 06-02 10:43 • 10次 阅读 SMTube流媒体应用 Deepin Movie深度影院 ./oschina_soft/deepin-movie.zip 发表于 06-02 10:41 • 12次 阅读 Deepin Movie深度影院 gstreamill音视频编码转码 ./oschina_soft/gstreamill.zip 发表于 06-02 10:39 • 8次 阅读 gstreamill音视频编码转码 Pithos Pandora Radio客户端 ./oschina_soft/pithos.zip 发表于 06-02 10:35 • 9次 阅读 Pithos Pandora Radio客户端 douban.fm豆瓣电台命令行版 ./oschina_soft/douban.fm.zip 发表于 06-02 10:27 • 6次 阅读 douban.fm豆瓣电台命令行版 dtplayer多媒体播放器 ./oschina_soft/dtplayer_c.zip 发表于 06-02 10:20 • 8次 阅读 dtplayer多媒体播放器 深度影音播放器软件 ./oschina_soft/deepin-media-player.zip 发表于 06-02 10:19 • 6次 阅读 深度影音播放器软件 vokoscreen屏幕录像软件 ./oschina_soft/vokoscreen.zip 发表于 06-02 10:11 • 6次 阅读 vokoscreen屏幕录像软件 kwplayer linux音乐播放软件 ./oschina_soft/kwplayer.zip 发表于 06-02 10:10 • 7次 阅读 kwplayer linux音乐播放软件 Siren基于文本的音频播放器 ./oschina_soft/siren.zip 发表于 06-02 10:06 • 9次 阅读 Siren基于文本的音频播放器 IronGrip CD抓轨工具 ./oschina_soft/IronGrip.zip 发表于 06-02 10:03 • 6次 阅读 IronGrip CD抓轨工具 kryten自动幻灯展示工具 ./oschina_soft/kryten.zip 发表于 06-02 10:01 • 3次 阅读 kryten自动幻灯展示工具 amSynth和弦模拟建模合成器 ./oschina_soft/amsynth.zip 发表于 06-02 09:57 • 6次 阅读 amSynth和弦模拟建模合成器 Nuvola Player音乐播放器 ./oschina_soft/nuvolaplayer.zip 发表于 06-02 09:50 • 6次 阅读 Nuvola Player音乐播放器 MusE Linux虚拟演播室 ./oschina_soft/muse.zip 发表于 06-02 09:32 • 8次 阅读 MusE Linux虚拟演播室 mhWaveEdit音乐编辑程序 ./oschina_soft/mhwaveedit.zip 发表于 06-02 09:29 • 8次 阅读 mhWaveEdit音乐编辑程序 GeeXboX多媒体Linux发行版 ./oschina_soft/geexbox.zip 发表于 06-02 09:27 • 6次 阅读 GeeXboX多媒体Linux发行版 Performous卡拉OK程序 ./oschina_soft/performous.zip 发表于 06-02 09:25 • 11次 阅读 Performous卡拉OK程序 MediaInfo音视频信息工具 ./oschina_soft/MediaInfo.zip 发表于 06-02 09:15 • 7次 阅读 MediaInfo音视频信息工具 VLC media player视频播放器 ./oschina_soft/vlc.zip 发表于 06-02 09:11 • 11次 阅读 VLC media player视频播放器 嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序 本篇详细介绍了如何自己编写一个Qt程序,如何通过交叉编译,最终放到开发板中执行的过程。 的头像 码农爱学习 发表于 06-02 09:06 • 3144次 阅读 嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序 OpenHarmony短彩信Framework层代码的分析和解读 近年来,随着国内信息化市场的逐步成长,趋向成熟,以 OpenAtom OpenHarmony(简称“.... 的头像 HarmonyOS官方合作社区 发表于 06-02 08:55 • 101次 阅读 物联网安全和边缘IP保护   如果使用专用硬件(例如 GPU)运行模型,则模型可能位于一个虚拟环境(例如 Linux)中,并由.... 的头像 星星科技指导员 发表于 06-01 17:40 • 225次 阅读 如何将高级C语言编译成机器码 C编译成机器码要通过预处理,编译,汇编,链接四个步骤。这四个步骤由谁做的呢?答案是编译器。 编译器做的工作类似我们IC行... 发表于 06-01 16:53 • 2529次 阅读 console函数概述及使用方法说明 首先,C#是一种基于net.framework框架下的一种编程语言,涉及到图像化与编程的双向使用,因.... 的头像 嵌入式应用开发 发表于 06-01 16:49 • 353次 阅读 console函数概述及使用方法说明 Linux内存的分配管理与内存回收基本框架 内存对计算机系统来说是一项非常重要的资源,直接影响着系统运行的性能。最初的时候,系统是直接运行在物理.... 的头像 Linux阅码场 发表于 06-01 16:02 • 487次 阅读 BPI-R2 Pro 开源硬件开发板OpenWRT系统镜像发布 Banana Pi BPI-R2 Pro 开源路由器采用Rockchip RK3568芯片方案设计, 板载2GB LPDDR4内存和16GB eMMC存储... 发表于 06-01 14:54 • 574次 阅读 BPI-R2 Pro 开源硬件开发板OpenWRT系统镜像发布 netease-cloud-music-gtk Linux网易云音乐播放器 ./oschina_soft/gitee-netease-cloud-music-gtk.zip 发表于 06-01 14:54 • 8次 阅读 netease-cloud-music-gtk Linux网易云音乐播放器 m4b-tool有声读物文件合并分割工具 ./oschina_soft/m4b-tool.zip 发表于 06-01 14:37 • 8次 阅读 m4b-tool有声读物文件合并分割工具 Gnomecast支持转码和字幕的Linux GUI ./oschina_soft/gnomecast.zip 发表于 06-01 14:23 • 6次 阅读 Gnomecast支持转码和字幕的Linux GUI 内存溢出的原因以及解决方法 内存溢出 ,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申.... 的头像 嵌入式应用开发 发表于 06-01 11:31 • 3266次 阅读 内存溢出的原因以及解决方法 Picard音乐整理软件 ./oschina_soft/picard.zip 发表于 06-01 11:00 • 7次 阅读 Picard音乐整理软件 CasparCG Server多媒体工具 ./oschina_soft/Server.zip 发表于 06-01 10:52 • 6次 阅读 CasparCG Server多媒体工具 FFMPEG-Video-Converter-in-bash MP4视频转换脚本 ./oschina_soft/FFMPEG-Video-Converter-in-bash.zip 发表于 06-01 10:51 • 8次 阅读 FFMPEG-Video-Converter-in-bash MP4视频转换脚本 DevOps的基本知识介绍 根据Google DORA( DevOps、Research与Assessment)团队最新的《De.... 的头像 科技绿洲 发表于 06-01 10:51 • 144次 阅读 linux-kugou-client酷狗Linux客户端 ./oschina_soft/linux-kugou-client.zip 发表于 06-01 10:49 • 8次 阅读 linux-kugou-client酷狗Linux客户端 写一个公用工具来进行Excel的导入导出 导入方法需要传入file文件,以及一个Class类型,导入之后将会返回一个list集合,里面的对象就.... 的头像 Android编程精选 发表于 06-01 10:48 • 194次 阅读 XiamiForLinuxProject虾米音乐Linux版本 ./oschina_soft/XiamiForLinuxProject.zip 发表于 06-01 10:47 • 6次 阅读 XiamiForLinuxProject虾米音乐Linux版本 xiami-tools虾米工具包 ./oschina_soft/xiami-tools.zip 发表于 06-01 10:46 • 6次 阅读 xiami-tools虾米工具包 FeelUOwn Python编写的跨平台音乐播放器 ./oschina_soft/feeluown.zip 发表于 06-01 10:33 • 8次 阅读 FeelUOwn Python编写的跨平台音乐播放器 BiliDan MPV播放Bilibili视频 ./oschina_soft/BiliDan.zip 发表于 06-01 10:31 • 8次 阅读 BiliDan MPV播放Bilibili视频 华为AppCube应用魔方顺利通过信通院评估 由中国信息通信研究院(以下简称:信通院)、中国通信标准化协会主办的第二期“低代码/无代码应用深度探索.... 的头像 华为开发者社区 发表于 06-01 10:12 • 214次 阅读 CH565开发加入自定义的函数异常问题如何解决?       CH565开发加入自定义的函数,无法达到延时效果。主程序和延时函数如下。      &nb... 发表于 06-01 07:13 • 148次 阅读 CH569的HSPI代码测试的速度很慢如何处理? 看手册写的最高速度达到3.8Gbps,有测试Demo吗。 用HSPI_BurstMode代码测试的感觉速度也就300MByte/s+,不知道是哪出... 发表于 06-01 06:10 • 31次 阅读 【嵌入式开发教程1】手把手教你做平板电脑-Linux 引导过程 Linux 引导过程——疯壳·嵌入式平板开发   Linux 内核与 Android 系统 linux 内核有什么区别?   ... 发表于 05-31 15:21 • 1669次 阅读 【嵌入式开发教程1】手把手教你做平板电脑-Linux 引导过程 Linux虚拟内存和物理内存的深刻分析 让我们看下虚拟内存:第一层理解每个进程都有自己独立的4G内存空间,各个进程的内存空间具有类似的结构 一个新进程建立的时候,... 发表于 05-31 08:00 • 3146次 阅读 mStopIfError这个函数的作用是什么,会导致程序卡死在这里么?     CH565开发板中的DEMO程序,执行了get_unique_mac( local_mac );里面调用了mStopIfError函数,这个函数的... 发表于 05-31 06:30 • 45次 阅读 基于AM57x+Artix-7开发板——GStreamer视频开发案例(3) 前 言本文主要介绍AM570x基于GStreamer的视频采集、编解码、算法处理、显示以及存储案例。 本次案例测试板卡为创龙科技T... 发表于 05-30 17:32 • 2713次 阅读 如何实现在arm平台上进行c语言编译呢 安装gcc环境 测试用的unbutu平台,直接在开发板上面运行,如果在虚拟机上面运行的话又要弄交叉编译,太麻烦;直接在开发板上面联... 发表于 05-30 10:43 • 1450次 阅读 如何实现在arm平台上进行c语言编译呢 安装gcc环境 测试用的unbutu平台,直接在开发板上面运行,如果在虚拟机上面运行的话又要弄交叉编译,太麻烦;直接在开发板上面联... 发表于 05-30 10:41 • 1479次 阅读 AM4379 AM437x ARM Cortex-A9 微处理器 (MPU) TI AM437x高性能处理器基于ARM Cortex-A9内核。 这些处理器通过3D图形加速得到增强,可实现丰富的图形用户界面,还配备了协处理器,用于进行确定性实时处理(包括EtherCAT,PROFIBUS,EnDat等工业通信协议)。该器件支持高级操作系统(HLOS)。基于Linux的® 可从TI免费获取。其它HLOS可从TI的设计网络和生态系统合作伙伴处获取。 这些器件支持对采用较低性能ARM内核的系统升级,并提供更新外设,包括QSPI-NOR和LPDDR2等存储器选项。 这些处理器包含功能方框图中显示的子系统,并且后跟相应的“说明”中添加了更多信息说明。 处理器子系统基于ARM Cortex-A9内核,PowerVR SGX™图形加速器子系统提供3D图形加速功能以支持显示和高级用户界面。 可编程实时单元子系统和工业通信子系统(PRU-ICSS与ARM内核分离,允许单独操作和计时,以实现更高的效率和灵活性.PRU-ICSS支持更多外设接口和EtherCAT,PROFINET,EtherNet /IP,PROFIBUS,以太网Powerlink,Sercos,EnDat等... 发表于 09-25 11:51 • 636次 阅读 AM4379 AM437x ARM Cortex-A9 微处理器 (MPU)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3