2

玩转C语言:深入理解输入输出函数的奥秘 - Betty’sSweet

 6 months ago
source link: https://www.cnblogs.com/bett/p/18024951
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

pFp8UCq.jpg

✨✨ 欢迎大家来到贝蒂大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C语言学习
贝蒂的主页:Betty‘s blog

1. 单字符输出函数

在C语言中有一个函数putchar专门负责输出单个字符,其语法如下:

  1. 头文件:#include<stdio.h>

  2. 声明:int putchar(int char)

    • char -- 这是要被写入的字符。该字符以其对应的 int 值进行传递。
  3. 作用:把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中,也就是输出单个字符。

  4. 返回值:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。

以下是对putchar的具体使用示例:

#include<stdio.h>
int main()
{
	putchar('A');//输出字符A	
	putchar('1');//输出字符1
	putchar('\106');//输出转义字符F
	return 0;
}

输出结果:

3371071-20240221125109628-1207944827.png

2. 多字符输出函数

既然有单字符输出函数,那就自然有多字符输出函数——puts,其语法如下:

  1. 头文件:#include<stdio.h>
  2. 声明:int puts(const char *str)
    • str -- 这是要被写入的 C 字符串。
  3. 作用:把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。
  4. 返回值:如果成功,该函数返回一个非负值为字符串长度(包括末尾的 \0),如果发生错误则返回 EOF。

以下是对puts的具体使用示例:

int main()
{
	puts("hello world\n");
	puts("贝蒂来啦\n");
	return 0;
}

输出结果:

3371071-20240221125109927-569389278.png

3. 格式化输出函数

3.1 语法

介绍完单字符与多字符输出函数,下面我们将介绍格式化输出函数——printf,其语法如下:

  1. 头文件:#include<stdio.h>
  2. 声明:int printf(const char *format, ...)
    • format -- 这是字符串,包含了要被写入到标准输出 stdout 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。
  3. 作用:将参数⽂本输出到屏幕
  4. 返回值:如果成功,则返回写入的字符总数,否则返回一个负数。

3.2 占位符

printf() 可以在输出⽂本中指定占位符。所谓“占位符”,就是这个位置可以⽤其他值代⼊。下表是常见的占位符:

占位符 含义
%d 以十进制形式输出整数
%u 以十进制形式输出无符号整数
%x 以十六进制形式输出整数(小写字母)
%X 以十六进制形式输出整数(大写字母)
%o 以八进制形式输出整数
%f 以浮点数形式输出实数
%e 以指数形式输出实数
%g 自动选择 %f 或 %e 输出实数
%c 输出单个字符
%s 输出字符串
%p 输出指针的地址
%n 输出已经输出的字符数
%% 输出百分号本身

以下是对printf的具体使用示例:

int main()
{
	printf("%d\n", 5);//打印整型
	printf("%f\n", 5.1);//打印浮点型
	printf("%c\n", 'a');//打印字符
	printf("%s\n", "betty");//打印字符串
	printf("betty");//也可以这样打印字符串
	return 0;
}

输出结果:

3371071-20240221125110124-750901433.png

  • printf() 参数与占位符是⼀⼀对应关系,如果有 n 个占位符, printf() 的参数就应该有 n +1 个(双引号内部也算一个)。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。

3.3 限定格式

(1) 限定宽度

printf() 允许限定占位符的最⼩宽度。以下是具体的实例:

int main()
{
	printf("%4d\n", 123);
	printf("%-4d\n", 123);
	printf("%12f\n", 123.45);
	return 0;
}

3371071-20240221125110429-877913538.png

  • 上⾯⽰例中, %4d 表⽰这个占位符的宽度至少为4位。如果不满4位,对应的值的前⾯会添加空格。输出的值默认是右对⻬,即输出内容前⾯会有空格;如果希望改成左对⻬,在输出内容后⾯添加空格,可以在占位符的 % 的后⾯插⼊⼀个 - 号。
  • 对于⼩数,这个限定符会限制所有数字的最⼩显⽰宽度。上⾯⽰例中, %12f 表⽰输出的浮点数最少要占据12位。由于⼩数的默认显⽰精度是⼩数点后6位,所以 123.45 输出结果的头部会添加2个空格。

(2) 总是显示正负号

默认情况下, printf() 不对正数显示 + 号,只对负数显示 - 号。如果想让正数也输出 + 号,可以在占位符的 % 后⾯加⼀个 + 。

int main()
{
	printf("%+d\n", 13);
	printf("%+d\n", -13);
	return 0;
}

(3) 限制小数位数

输出⼩数时,有时希望限定⼩数的位数。举例来说,希望⼩数点后⾯只保留两位,占位符可以写成 %.2f

#include <stdio.h>
int main()
{
	printf("Number is %.2f\n", 0.5);//输出0.50
	return 0;
}
  • 这种写法也是可以与限定宽度结合使用的

(4) 限定字符串的输出

%s 占位符⽤来输出字符串,默认是全部输出。如果只想输出开头的部分,可以⽤ %.[m]s 指定输出的⻓度,其中 [m] 代表⼀个数字,表⽰所要输出的⻓度。

#include <stdio.h>
int main()
{
	printf("%.5s", "hello world");
	return 0;
}

输出结果:

3371071-20240221125110597-288215795.png

(5) 限定值输入

最⼩宽度和⼩数位数这两个限定值,都可以⽤ ***** 代替,通过 printf() 的参数传⼊。

#include <stdio.h>
int main()
{
    printf("%*.*f\n", 6, 2, 0.5);
    return 0;
}// 等同于printf("%6.2f\n", 0.5);

3.4 printf的返回值

我们在前面介绍printf时候就已经了解过其返回值:如果成功,则返回写入的字符总数,否则返回一个负数。

下面就让我们通过下列两道题来加深理解:

(1) 题目一

int main()
{
	int a = 43;
	printf("%d\n", printf("%d", printf("%d", a)));//输出什么??
	return 0;
}
  1. 首先肯定会执行最里面的printf("%d",43),在屏幕上打印出43。
  2. 然后执行printf("%d", printf("%d", 43)),相当于打印第一步printf的返回值,‘4’,‘3’有两个字符,所以返回值是2。
  3. 最后同理执行printf("%d", printf("%d", printf("%d", 43))),即打印第二步的‘2’返回值,一个字符,返回值为1。
  4. 所以屏幕上最后打印的就是4321

3371071-20240221125110794-1981911925.png

(2) 题目二

int main()
{
    printf("%d\n",printf("%d\n",printf("hello!\n"))); //输出??
    return 0;
}https://s11.ax1x.com/2024/02/20/pFYxXCT.png
  1. 首先肯定会打印出hello!然后换行。
  2. 然后打印printf("%d\n",printf("hello!\n")),即第一步的返回值,需要注意是‘\n’是一个字符,所以返回值是7,换行。
  3. 最后打印printf("%d\n",printf("%d\n",printf("hello!\n"))),即第二步的返回值,格式化字符串的‘\n’也会算做一个字符,一共两个字符,所以最后打印出2。

3371071-20240221125110967-513416760.png

4. 单字符输入函数

单字符输入函数——getchar,顾名思义就是读取一个字符,其用法如下:

  1. 头文件:#include<stdio.h>
  2. 声明:int getchar()
  3. 作用:从标准输入 stdin 获取一个字符(一个无符号字符)
  4. 返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。

下面的实例演示了 getchar() 函数的用法:

#include <stdio.h>

int main()
{
	char c;
	printf("请输入字符:");
	c = getchar();
	printf("输入的字符:");
	putchar(c);
	return 0 ;
}

输出结果:

3371071-20240221125111165-1725555891.png

5. 多字符输入函数

多字符输入函数——gets,顾名思义就是输入一个字符,其用法如下:

  1. 头文件:#include<stdio.h>
  2. 声明:char *gets(char *str)
    • str -- 这是指向一个字符数组的指针,该数组存储了 C 字符串。
  3. 作用:从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。
  4. 返回值:如果成功,该函数返回 str。如果发生错误或者到达文件末尾时还未读取任何字符,则返回 NULL。

下面的实例演示了 gets() 函数的用法:

#include <stdio.h>
int main()
{
	char str[20] = { 0 };
	printf("请输入一个字符串:");
	gets(str);
	printf("您输入的字符串是:%s", str);
	return(0);
}

输出结果:

3371071-20240221125111396-271420914.png

6. 格式化输入函数

6.1 语法

下列是格式化输入函数——scanf的用法:

  1. 头文件:#include<stdio.h>
  2. 声明:int scanf(const char *format, ...)
    • format -- 这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符和 format 说明符。
  3. 作用: 从标准输入 stdin 读取格式化输入
  4. 返回值:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

下面的实例演示了 scanf() 函数的用法:

#include<stdio.h>
int main()
{
    int a, b, c;
    printf("请输入三个数字:");
    scanf("%d%d%d", &a, &b, &c);
    printf("输出结果是:%d,%d,%d\n", a, b, c);
    return 0;
}
  • &a、&b、&c 中的 & 是地址运算符,分别获得这三个变量的内存地址。
  • %d%d%d 是按十进值格式输入三个数值。输入时,在两个数据之间可以用一个或多个空格、tab 键、回车键分隔。

输出结果:

3371071-20240221125111628-655563553.png

  • 并且输入数据也要与格式化内数据保持一致。什么意思呢?我们以下面这段代码举例说明:
#include<stdio.h>
int main()
{
    int a, b;
    scanf("%d,d", &a, &b);
    //输入a,b?
    //输入a b?
    printf("输出结果是:%d,%d\n", a, b, );
    return 0;
}
  • 上诉代码只能输入a,b,而不能输入a b因为要与格式化内容相匹配。

6.2 scanf与gets之间的区别

scanf在处理占位符时候,如果占位符不是%c,会忽略起始的空格(非起始的空格会停止),换行符,制表符。而gets可以将输入流的数据全部读取。比如说下面这段代码:

#include<stdio.h>
//如果输入hello betty
//分别输出什么
int main()
{
    char arr1[20];//存放字符串
    gets(arr1);
    char arr2[20];//存放字符串
    scanf("%s ", arr2);
    printf("arr1输出:%s\n",arr1);
    printf("arr2输出:%s\n", arr2);
    return 0;
}
3371071-20240221125111843-629873199.png
  • 第一次输入gets全部读取,第二次输入printf遇见空格就停止读取。

6.3 缓存区

scanf() 处理用户输⼊的原理是,用户的输⼊先放⼊一个区域,等到按下回⻋键后,按照占位符对缓存进⾏解读。而这个区域就是我们的缓存区

3371071-20240221125112035-125452136.png

注:标准输入⼀般指的就是键盘,标准输出⼀般指的就是屏幕

知道了缓冲区之后,让我们来分析一段代码:

int main()
{
	char password[20];
	printf("请输入你的密码:");
        scanf("%s", password);
	int ret = getchar();
	printf("请再次确认你的密码(Y/N):");
	if (ret == 'Y')
	{
		printf("密码正确\n");
	}
	else
	{
		printf("密码错误\n");
	}
	return 0;
}

输出结果:

3371071-20240221125112243-2101345750.png

为什么会出现这样的结果呢?这时就要运用缓冲区的知识,在我们输入abc回车(\n)时,缓冲区中的数据为abc\n,而scanf只会读取abc,\n会被一直留在缓冲区。所以在getchar再次读取时会自动读取\n,输出密码错误。

解决这个问题也很简单,我们只需要再加一个getchar提前把\n读取就行了。

int main()
{
	char password[20];
	printf("请输入你的密码:");
	scanf("%s", password);
	printf("请再次确认你的密码(Y/N):");
	getchar();//清空缓冲区
	int ret = getchar();
	if (ret == 'Y')
	{
		printf("密码正确\n");
	}
	else
	{
		printf("密码错误\n");

	}
	return 0;
}

6.4 scanf的返回值

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。这一点常常用于多组数据输入,比如说多组数据求和,可以写成如下形式:

int main()
{
	int a, b;
	while (scanf("%d%d") == 2)
	{
		int sum = a + b;
		printf("%d", sum);
	}
	return 0;
}
  • 在VS环境下可以按3次 ctrl+z 强制结束。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK