IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 其他类型 输入输出函数 -> 正文阅读

[系统运维]其他类型 输入输出函数

***其他输入输出函数***

首先,C语言输入输出的对象,主要就是标准输出流(stdout)与标准输入流(stdin)。所谓标准输出流通俗地说就是屏幕输出,标准输入流就是键盘输入。除了这两种之外,C语言还可以对磁盘文件和外部设备输入输出。

磁盘输入输出函数

类似于标准输入输出函数,文件输入输出函数包括:

a)单个字符输入输出函数:fgetchar与fputchar(或者getc与putc);

b)单行字符串输入输出函数:fgets与fputs;

c)格式化输入输出函数:fscanf与fprintf;

[3-12]测试文件输出功能

#include <stdio.h>

int main( )

{

char s[80];

FILE* pf = fopen("./1.txt", "w");

puts("请输入一行文字:"); //fputs("请输入一行文字:", stdout);

scanf("%s", s); //fgets(s, sizeof(s), stdin);

fputs(s, pf);

fclose(pf);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后根据提示输入一行文字后回车,查看执行文件或者工程目录下是否生成了一个“1.txt”文件;

b)用记事本或其他文本工具打“1.txt”文件,观察fputs和fclose哪个函数执行之后文件的内容发生变化;

c)使用注释中的fputs替换puts函数,使用fgets替换scanf函数,思考两种函数的等价关系。

[3-13]测试文件输入功能

#include <stdio.h>

int main()

{

int?c;

FILE* pf = fopen("./1.txt", "r");

if (!pf)

{

puts("打开文件失败!");

return -1;

}

while (1)

{

c = getc(pf);

if (c == -1)

break;

if (c == '\r')

continue;

putchar(c); //putc(c,stdout);

}

fclose(pf);

return 0;

}

//linux文本文件的换行符是:\n

//windows文本文件的换行符是:\r\n

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之前先要拷贝一个1.txt文件(含有多行文字内容),到执行文件所在目录下或者工程目录下;

b)运行之后观察程序输出内容,与原文本文件中的内容是否完全一致;

c)使用注释中的fputc替换putchar函数,思考两种函数的等价关系。

d)最好能在调试模式下单步执行,在监视器内观察getc函数执行后变量的变化,尤其是含有中文的文件。

...........................................................................................................................................................

总结:本节对磁盘文件的读写只做初步认识,更多磁盘文件操作编程,参见后续章节“C语言文件”。在C语言中,把标准输出流定义为一个文件指针stdout,把标准输入流也定义为一个文件指针stdin。因此,就产生了以下的文件输入输出函数的一些等价关系:

a)单个字符输入输出函数:

getchar()与fgetchar(stdin)以及getc(stdin)三者是等价的;

putchar(c)与fputchar(c, stdout)以及putc(c,stdout)三者是等价的;

b)单行字符串输入输出函数:

gets(s)与fgets(s,sizeof(s),stdin)两者是等价的;

puts(s)与fputs(s,stdout)两者是等价的;

c)格式化输入输出函数:

scanf(x,…)与fscanf(stdin,x,…)是等价的;

printf(x,…)与fprintf(stdout,x,…)是等价的;

VS2015安全版本输入输出函数

微软的编译器从VS2005和VS2008开始,对关于字符串输入的相关函数增加了安全版本。例如:scanf_s和gets_s等。这些函数只限于在微软的各个VS版本中使用,目的是增加字符串输入时的安全性,防止用户录入的字符串过长破坏缓冲区意外的内存数据。

在VS2015编译器中,当代码中出现scanf、gets和fopen等函数时,(编译时报错)被强制使用安全版本。错误提示的内容是:“error C4996: 'fopen': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details”。

解决这个问题有两种办法:

a)在代码的最上方增加一行代码,取消安全版本的强制警告:#define _CRT_SECURE_NO_WARNINGS;

b)使用安全版本的函数替代非安全版本函数,例如:scanf_s、gets_s以及fopen_s等。

[3-14]测试非安全版本函数

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()

{

int nNumb = 0;

char sName[20];

char cSex = 0;

double fSala = 0.0;

puts("请输入一个员工的工号、姓名、性别、工资【性别(m代表男、f代表女)】:");

scanf("%d%s %c%lf", &nNumb, sName,&cSex,&fSala);

//注意在scanf函数的%c之前要加一个空格

printf("%-6s%10s%6s%10s\n", "工号", "姓名", "性别", "工资");

printf("%-6d%10s%6c%10.2lf\n",nNumb,sName,cSex,fSala);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入一组数据(例如:1041 王五?m 5802.51),观察输入之后打印的结果是否正常;

b)去掉%c之前的空格重新编译和运行,观察输入数值后打印的结果是否正常;

c)最好能在调试模式下单步执行,在监视器内观察scanf函数执行后,几个变量内的数据变化情况。

去掉最上面安全警告这行(#define _CRT_SECURE_NO_WARNINGS),并且把代码中的scanf和printf函数都改为安全版本的scanf_s和printf_s函数。编译后出现大量警告,例如:

warning C4477: “scanf_s”: 格式字符串“%s”需要类型“unsigned int”的参数,但可变参数?3 拥有了……;

warning C4477: “scanf_s”: 格式字符串“%c”需要类型“char *”的参数,但可变参数?4 拥有了类型“……”;

warning C4473: “scanf_s”: 没有为格式字符串传递足够的参数

note: 占位符和其参数预计?6 可变参数,但提供的却是?4 参数……

这些编译器的警告信息描述的问题都是非常准确的。安全版本的输入函数scanf_s,每一处的“%s”或“%c”控制符在参数列表中都要配备两个参数。目的主要是为了防止用户对字符串或字符输入时,超出参数可接受的输入字符的数量。

?[3-15]测试测试安全版本函数

//去除?#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()

{

int nNumb = 0;

char sName[20];

char cSex = 0;

double fSala = 0.0;

puts("请输入一个员工的工号、姓名、性别、工资【性别(m代表男、f代表女)】:");

scanf_s("%d%s %c%lf", &nNumb, sName,sizeof(sName),&cSex,sizeof(cSex),&fSala);

//注意在scanf_s函数的%c之前要加一个空格

printf_s("%-6s%10s%6s%10s\n", "工号", "姓名", "性别", "工资");

printf_s("%-6d%10s%6c%10.2lf\n",nNumb,sName,cSex,fSala);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入一组数据(例如:1041 王五?m 5802.51),观察输入之后打印的结果是否正常;

b)去掉%c之前的空格重新编译和运行,观察输入数值后打印的结果是否正常;

c)最好能在调试模式下单步执行,在监视器内观察scanf_s函数执行后,几个变量内的数据变化情况。

d)思考调用printf_s时是否需要像scanf_s那样,为控制符“%s”与“%c”在参数列表中配备两个参数。

getchar失效问题

在初学C语言时经常会遇到这样的问题,在scanf或gets函数执行之后,再执行getchar函数就会被跳过。为什么会出现这种情况呢?

[3-16]测试getchar函数失效问题

#include <stdio.h>

int main()

{

int nNumb = 0;

char sName[20];

char cSex = 0;

puts("请输入一个员工的工号、姓名:");

scanf_s("%d%s", &nNumb, sName,sizeof(sName));

printf("请输入该员工的性别(m代表男、f代表女):");

cSex = getchar();

printf_s("%-6s%10s%6s\n", "工号", "姓名", "性别");

printf_s("%-6d%10s%6c\n",nNumb,sName,cSex);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入一组数据(例如:1041 王五),观察输入之后程序的运行过程是否正常;

b)最好能在调试模式下单步执行,观察scanf_s函数执行后getchar函数是否正常执行;

c)将getchar函数放在scanf_s函数之前执行,观察getchar函数是否能正常执行。

...........................................................................................................................................................

结论:当scanf、gets以及getchar各种输入函数执行之后,标准输入缓冲区内总是残留了“\n”回车符。如果没有及时清理的情况下,调用getchar或scanf(“%c”…)等单字符输入函数时,得到的字符总是缓冲区内残留的回车符或空格等。

解决getchar失效问题,有两种办法:

a)在调用单字符输入函数getchar或者scanf("%c "…)之前,执行fflush函数清理一下输入缓冲区;

b)使用scanf("\n%c"…)代替getchar函数,可以很好地解决单字符输入失效的问题。

[3-17]解决getchar函数失效问题

#include <stdio.h>

int main()

{

int nNumb = 0;

char sName[20];

char cSex = 0;

puts("请输入一个员工的工号、姓名:");

scanf_s("%d%s", &nNumb, sName,sizeof(sName));

printf("请输入该员工的性别(m代表男、f代表女):");

fflush(stdin);

cSex = getchar();

printf_s("%-6s%10s%6s\n", "工号", "姓名", "性别");

printf_s("%-6d%10s%6c\n",nNumb,sName,cSex);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入一组数据(例如:1041 王五),观察输入之后程序的运行过程是否正常;

b)最好能在调试模式下单步执行,观察scanf_s函数执行后getchar函数是否正常执行;

c)将getchar函数放在scanf_s函数之前执行,观察getchar函数是否能正常执行。

在某些编译器中调用fflush函数之后,getchar函数或scanf("%c",…)等单字节输入函数仍然还仍然失效。

[3-18]解决getchar函数失效问题

#include <stdio.h>

int main()

{

int nNumb = 0;

char sName[20];

char cSex = 0;

puts("请输入一个员工的工号、姓名:");

scanf_s("%d%s", &nNumb, sName,sizeof(sName));

printf("请输入该员工的性别(m代表男、f代表女):");

scanf_s("\n%c", &cSex);

printf_s("%-6s%10s%6s\n", "工号", "姓名", "性别");

printf_s("%-6d%10s%6c\n",nNumb,sName,cSex);

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入一组数据(例如:1038 赵六),观察输入之后程序的运行过程是否正常;

b)最好能在调试模式下单步执行,观察前两项数据输入之后性别输入过程是否正常执行;

c)将性别输入函数放在前两项数据输入之前执行,观察单字符输入函数scanf("\n%c"…)是否能正常执行。

无回显的输入函数

什么是无回显的输入函数?有些DOS软件的菜单“1、……2、……”,当键盘刚一触碰就立即显示了结果。而不像getchar函数那样,可以输入几个字符之后再回车。无回显输入函数不是C语言标准函数,很多编译器不提供这类功能的函数。在VS2015中只要包含conio.h的头文件,就可以调用_getchar函数,实现无回显的输入功能。

无回显输入函数常用于软件菜单的选项输入,或者用户登录时的密码输入。

[3-19]测试无回显的输入函数

#include <stdio.h>

#include <conio.h>

int main()

{

puts("请输入密码(回车):");

while (1)

{

char ch = _getch();

if (ch == '\n' || ch == '\r')

break;

putchar('*');

}

puts("");

return 0;

}

将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

a)运行之后输入输入一串密码,观察每个字符输入之后是否都被显示为*符号;

b)最好能在调试模式下单步执行,观察_getch函数返回的单个字符是否与输入的字符一致;

c)思考如何将输入的密码记录到一个字符串数组内,并且用于之后的密码验证程序。

在Linux操作系统中,gcc编译器没有提供无回显的输入函数。因此我们需要自制无回显的输入函数。

[3-20]Linux操作系统中自制无回显输入函数

#include <stdlib.h>

#include <stdio.h>

#include <termios.h>

#include <string.h>

static struct termios stored_settings1;

static struct termios stored_settings2;

void echo_off(void)

{

struct termios new_settings;

tcgetattr(0, &stored_settings1);

new_settings = stored_settings1;

new_settings.c_lflag &= (~ECHO);

tcsetattr(0, TCSANOW, &new_settings);

return;

}

void echo_on(void)

{

tcsetattr(0, TCSANOW, &stored_settings1);

return;

}

void set_keypress(void)

{

struct termios new_settings;

tcgetattr(0, &stored_settings2);

new_settings = stored_settings2;

/*Disable canornical mode, and set buffer size to 1 byte */

new_settings.c_lflag &= (~ICANON);

new_settings.c_cc[VTIME] = 0;

new_settings.c_cc[VMIN] = 1;

tcsetattr(0, TCSANOW, &new_settings);

return;

}

void reset_keypress(void)

{

tcsetattr(0, TCSANOW, &stored_settings2);

return;

}

int _getch()

{

echo_off();

set_keypress();

int nRet = getchar();

reset_keypress();

echo_on();

return nRet;

}

int main()

{

puts("Please input password(Enter):");

char ch;

while ((ch = _getch()) != '\n')

putchar('*');

puts("");

return 0;

}

将以上代码输入到Linux操作系统中,使用gcc编译器进行编译、运行并查看打印结果:

a)运行之后输入输入一串密码,观察每个字符输入之后是否都被显示为*符号;

b)最好能在调试模式下单步执行,观察_getch函数返回的单个字符是否与输入的字符一致;

c)思考如何将输入的密码记录到一个字符串数组内,并且用于之后的密码验证程序。

接下来小结一下:

一、单字符输入输出:

getchar函数:?c=getchar();等价于scanf("%c",&c) ;

putchar函数:putchar(c);等价于printf("%c",c);

getc函数:c=getchar();等价于getc(stdin);

putc函数:putchar(c);等价于putc(c,stdout);

二、单行输入输出:

gets函数:gets(str);等价于scanf("%s",str);

puts函数:puts(str);等价于printf("%s\n",str);

三、格式化输入输出:

printf包括:%d、%u、%x、%c、%s等;

scanf包括:?%d、%u、%x、%c、%s等;

四、占位控制:

对于整数和字符串在%和控制符之间的数字代表占位,负号代表左对齐;

对于浮点数除了用数字代表占位,负号代表左对齐,还有小数位数的管理。

BY 白巾-子木

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:50:40  更:2021-08-10 13:52:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:17:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码