C语言|输入与输出

ps:字段宽度是指打印出来的“东西”所占位置大小,比如用%8.3f打印出来的浮点数,小数点前占4个字符位,其中小数点后占3个字符位,小数点算一个字符位,如果小数点前不满4个数,就用空格代替。用%08.3f打印出来的浮点数如果小数点前不满4个数,就用0代替。

#1. 输出 

#1.1 printf()函数

格式:printf(格式字符串, 待打印项1, 待打印项2,...);

要输出的内容 => 缓冲区(buffer) => 屏幕

何时发送到屏幕:

  1. buffer满时
  2. 遇到换行字符
  3. 需要输入时(旧编译器可能不支持)

在%和转换字符之间可加入修饰符,修饰基本的转换说明:

 

 

#include<stdio.h>

#define PAGES 999

int main(void)
{
    printf("%2d\n", PAGES);
    printf("%5.3d\n", 6);
    printf("%05.3d\n", 6);
    printf("%05.2d\n", 6);


    return 0;
}

结果为:

999

    006

    006

      06

#1.1.1 转换字符不匹配时

转换字符要匹配!!!!!

#include<stdio.h>

#define PAGES 336
#define WORDS 65618

int main()
{
	short int num = PAGES;
	short int mnum = -PAGES;
	
	printf("short int:%zd, int:%zd, char:%zd\n", sizeof(short int), sizeof(int), sizeof(char));
	printf("num as short and unsigned short:%hd %hu\n", num, num);
	printf("-num as short and unsigned short:%hd %hu\n", mnum, mnum);
	printf("num as int and char:%d %c\n", num, num);
	printf("WORDS as int, short and char:%d %hu %c\n", WORDS, WORDS, WORDS);
	
	return 0;
}

结果如下:

 可以看到

        short int为2字节(0~65535),用%hd打印时,范围为-32768~32767 [ -2^(15) ~ 2^(15)-1 ] ,用%hu打印时,范围为0~65535[ 0 ~ 2^(16)-1 ];

        因为num=336都在这个范围内,因此 printf("num as short and unsigned short:%hd %hu\n", num, num);  打印出来都没问题。

        对于printf("-num as short and unsigned short:%hd %hu\n", mnum, mnum); 由于mnum=-336,在用%hd打印的范围内,因此用%hd打印没问题;但是不在用%hu打印的范围内,因此出现问题,336用二进制表示为0000 0001 0101 0000,故-336为1111 1110 1011 0000,用%hu打印时,左边第一位不是符号位,因此65200。

        对于printf("num as int and char:%d %c\n", num, num); 由于int为4字节,用%d打印时,范围为-2,147,483,648~2,147,483,647 ,336在其范围内,因此输出没问题;但336用%c输出时出现问题,因为%c为1个字节也即用%c打印时,只会输出336的后八位(01010000),也即十进制的80,对应ASKII码的P。
        对于printf("WORDS as int, short and char:%d %hu %c\n", WORDS, WORDS, WORDS); WORDS=65618,包含在%d的输出里面,因此没问题;对应的二进制为0001 0000 0000 0101 0010,%hd只有两字节,因此输出 0000 0000 0101 0010=82,这种截断方式,相当于对65536(2^16)取余;%c只有一个字节,因此输出0101 0010=82,对应ASKII码的R。

#include<stdio.h>

#define PAGES 336
#define WORDS 65618

int main()
{
	float n1 = 3.0;
	double n2 = 3.0;
	long n3 = 2000000000;
	long n4 = 1234567890;

	printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
	printf("%ld %ld %ld %ld", n1, n2, n3, n4);
	
	return 0;
}

运行结果为:

 对于printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);  前两个输出没有问题,对于n3=2000000000=0111 0111 0011 0101 1001 0100 0000 0000(一共4字节),用%e打印时,不仅看这四个字节,还看相邻的四个字节,共八个字节。

printf()函数打印时,会把float转换成double类型。

对于printf("%ld %ld %ld %ld", n1, n2, n3, n4);     一种解释:

 参数传递时,把n1n2n3n4依次压入栈中,分别为8 8 4 4个字节,在输出时,printf()根据%ld从栈中按4字节依次取数,如图。

#1.1.2 printf()的返回值

printf()函数正常运行的返回值为打印字符的个数,异常时返回负数(旧版本不一定)。

#1.1.3 printf()打印较长字符串

三种字符串断行方法:

  1. 使用多个printf()函数
  2. 使用反斜杠\和ENTER换行
  3. 在两个用双引号括起来的字符串之间用空白格隔开;注意,"XJ" "X"输出XJX ; "XJ " "x"输出XJ X

#1.1.4 printf()的*修饰符

如果不想预先指定字段宽度,希望程序来指定,可以用*修饰符代替字段宽度。

如:设定一个输入width,用于确定字段宽度。

上面的语句,会根据width的值来确定后面number打印的字段宽度。

上面的语句,会根据width的值来确定weight打印的字段宽度;precision的值确定小数点后的位数。

#1.1.5 特殊归纳

printf("%d", printf("%d", printf("%d", 43)));

输出结果为:4321

#1.2 getchar()函数

一次只从缓冲区获取一个字符。

#1.3 gets()函数

获取字符串。

#2. 输入

#2.1. scanf()函数

转换说明:

 修饰符:

  

 #2.1.1. scanf()读取数据

  1. scanf()每次读取一个字符,跳过空白字符;遇到第一个非空白字符才会开始读取
  2. scanf()会根据转换说明来读取输入。如要输入数字,scanf()会识别数字或(+ -号),读到非数字和+ -号或者空白字符时,停止本次读取;如果第一个字符是A,则永远无法完成输入。如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。
  3. 如果使用字段宽度,scanf()在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。
  4. 当scanf()把字符串放进指定数组中时,它会在字符序列的末尾加上'\0',让数组中的内容成为一个C字符串。

#2.1.2. 格式字符串中的普通字符

 除了%C,其他转换说明都会自动跳过待输入值前面所有的空白。

 #2.1.3. scanf()函数的返回值

  • 返回成功读取的项数
  • 如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,返回0。
  • 当scanf()检测到“文件结尾”时,会返回EoF。

ps:可以利用返回值来判断是否输入正确以及退出。

如:

int num = 0;
while (scanf("%d", &num) == 1)
{
    ...;
}

当输入为数字时,才进入while循环;否则跳出循环。

#2.1.4 scanf()函数的*修饰符

上面的语句,会把第三个输入的值传递给n,实现跳过的功能。

#2.2 putchar()函数

输出一个字符。

#3 总结

1. printf的格式:printf(格式字符串, 待打印项1, 待打印项2,...);

    printf的运行流程:要输出的内容 => 缓冲区(buffer) => 屏幕

    何时发送到屏幕:

  1. buffer满时
  2. 遇到换行字符
  3. 需要输入时(旧编译器可能不支持)

2. printf的转换说明

3. printf()函数正常运行的返回值为打印字符的个数(换行符\n等也算一个字符),异常时返回负数(旧版本不一定);

4. printf语句过长时,可以使用\断开,也可以用写成多句;

5. scanf:数组不用加&,变量要加&;

6. 

  1. scanf()每次读取一个字符,跳过空白字符;遇到第一个非空白字符才会开始读取
  2. scanf()会根据转换说明来读取输入。如要输入数字,scanf()会识别数字或(+ -号),读到非数字和+ -号或者空白字符时,停止本次读取;如果第一个字符是A,则永远无法完成输入。如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。
  3. 如果使用字段宽度,scanf()在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。
  4. 当scanf()把字符串放进指定数组中时,它会在字符序列的末尾加上'\0',让数组中的内容成为一个C字符串。

7. scanf返回值

  • 返回成功读取的项数
  • 如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,返回0。
  • 当scanf()检测到“文件结尾”时,会返回EoF。

8. *修饰符

        对于printf来说,*修饰符可以该字段宽度交由程序的某个变量决定;对于scanf来说,*修饰符会让其跳过相应的输出项;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值