摘要:
  本文主要是记录C语言笔记——输入输出。

一、输出函数

1.putchar

【函数描述】:C标准库<stdio.h>中的函数,把参数 char 指定的字符(一个无符号字符)写入到标准输出stdout中。

【函数声明】:

1
int putchar(int char)

【函数参数】:

  • char :这是要被写入的字符。该字符以其对应的int 值进行传递。

【返回值】:该函数以无符号char强制转换为int的形式返回写入的字符,如果发生错误则返回 EOF(-1)

【函数实例】:

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main(int argc, char *argv[])
{
char a = 0x23; /* ascii 中 0x23 = # */
putchar(a); /* 输出字符 */
putchar('\n'); /* 输出换行符 */
return 0;
}

【注意】:putchar函数只是输出一个字符,并不会自动换行。

2.puts

【函数描述】:C标准库<stdio.h>中的函数,把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。

【函数声明】:

1
int puts(const char *str)

【函数参数】:

  • str :这是要被写入的字符串。

【返回值】:如果成功,该函数返回一个非负值为字符串长度(包括末尾的 \0),如果发生错误则返回EOF(-1)

【函数实例】:

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
char str[16] = "abcdefg";/* 最后还有一个 \0 表示字符串的结束 */
i = puts(str); /* 输出字符串 */
printf("i=%d\n",i);
return 0;
}

【注意】:puts函数输出时会自动换行

3.printf

  该函数应该是应用最多的函数,用法也极其丰富。

3.1函数说明

【函数描述】:C标准库<stdio.h>中的函数,发送格式化输出到标准输出 stdout

【函数声明】:

1
int printf(const char *format, ...)

【调用格式】:

1
printf("<格式化字符串>", <输出表>);

【函数参数】:

  • 格式化字符串(format ): 就是格式化需要输出的字符串,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format标签属性是 %[flags][width][.precision][length]specifier%[标志][最小宽度][.精度][长度]类型
  • 输出表(附加参数):根据不同的format字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了format参数中指定的每个%标签。参数的个数应与%标签的个数相同。

【返回值】:如果成功,则返回写入的字符总数,否则返回一个负数。

3.2格式化字符串详解

  • 格式字符(specifier
格式字符 形式 意义
i, d %i, %d 以十进制形式输出带符号整数(正数不输出符号)
u %u 以十进制形式输出无符号整数
o %o 以八进制形式输出无符号整数(不输出前缀0)
x, X %x, %X 以十六进制形式输出无符号整数(不输出前缀0x)
f %f 以小数形式输出单、双精度实数
e, E %e, %E 以指数形式输出单、双精度实数
g, G %g, %G 以 %f 或 %e 中较短的输出宽度输出单、双精度实数
c %c 输出单个字符
s %s 输出字符串

【注意】想要输出**%本身的话可以%%**。

  • 标识(flag
标识 描述
- 在给定的字段宽度内左对齐,默认是右对齐
+ 强制在结果之前显示加号或减号(+ 或 -),即正数前面会显示 + 号。默认情况下,只有负数前面会显示一个 - 号。
space
(空格)
有符号值若为正,则在值前显示前导空格(但是不显示符号);若为负,则在值前显示-。
# 与 o、x 或 X 说明符一起使用时,非零值前面会分别显示 0、0x 或 0X。
与 e、E 和 f 一起使用时,会强制输出包含一个小数点,即使后边没有数字时也会显示小数点。默认情况下,如果后边没有数字时候,不会显示显示小数点。
与 g 或 G 一起使用时,结果与使用 e 或 E 时相同,但是尾部的零不会被移除。
0 输出数值时指定左面不使用的空位置自动填0。
  • 最小输出宽度(width
宽度 描述
number 数值(十进制整数),数据长度 小于number,则左补空格;否则按实际输出。
* 星号,精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。
如:printf("%0*d",6,1000); 将输出:001000
  • 精度(.precision
精度 描述
.number 对于整数说明符(d、i、o、u、x、X):precision 指定了要写入的数字的最小位数。如果写入的值短于该数,结果会用前导零来填充。如果写入的值长于该数,结果不会被截断。精度为 0 意味着不写入任何字符。
对于 e、E 和 f 说明符:要在小数点后输出的小数位数。
对于 g 和 G 说明符:要输出的最大有效位数。
对于 s : 要输出的最大字符数,不足number则正常输出,超过则截断。默认情况下,所有字符都会被输出,直到遇到末尾的空字符。
对于 c 类型:没有任何影响。
当未指定任何精度时,默认为 1。如果指定时不带有一个显式值,则假定为 0。
.* 星号,精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。
但是在尝试的时候似乎有一些数据类型不匹配的情况,不过也用的不多。
【注意】

  1.精度格式符以**.**开头,后跟十进制整数。

  2.对数值型数据的来说,未指定精度(.precision)时,隐含的精度为6位。

  • 长度(length

  详情可查看该网站(含有C99标准):File input/output。

3.3转义字符

转义字符 含义 ASCII码(十进制)
\a 响铃(BEL) 007
\b 退格(BS),将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF),将当前位置移到下一行开头 010
\r 回车(CR),将当前位置移到本行开头 013
\t 水平制表(HT),跳到下一个TAB位置 009
\v 垂直制表(VT) 011
\\ 反斜线字符 \ 092
\' 单引号字符 ' 039
\" 双引号字符 " 034
\? 问号 ? 063
\0 空字符(NULL) 000
\ooo 1-3位八进制数所代表的任意字符 三位八进制
\xhh 1-2位十六进制数所代表的任意字符 二位十六进制
### 3.4实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char c, str[20];
int a = 12345;
float pi = 3.141592653589;
double b = 0.123456789123456789;
strcpy(str, "strings"); /* 将字符串复制到数组 */
c = '\x41'; /* 两位十六进制转移字符 代表A */

printf("a = %d\n", a); /* 按照十进制整数格式输出,显示 a = 12345 */
printf("a = %d%%\n", a); /* 输出%号 结果 a = 12345% */
printf("a = %7d\n", a); /* 输出7位十进制整数 左边补空格,显示 a = 12345 */
printf("a = %07d\n", a); /* 输出7位十进制整数 左边补0,显示 a = 0012345 */
printf("a = %2d\n", a); /* a超过2位,按实际输出 a = 12345 */
printf("a = %-7d\n", a); /* 输出7位十进制整数 右边补空格,显示 a = 12345 */
printf("pi = %f\n", pi); /* 浮点数默认精度6位小数,结果 f = 13.141593 */
printf("pi = %6.4f\n", pi); /* 输出6列,小数点后4位,结果 f = 3.1416 */
printf("b = %lf\n", b); /* 输出长浮点数 b = 0.123457 */
printf("b = %18.17lf\n", b); /* 输出18列,小数点后16位,b = 0.12345678912345678 */
printf("c = %c\n", c); /* 输出字符 c = A */
printf("c = %x\n", c); /* 以十六进制输出字符的ASCII码 c = 41 */
printf("str[] = %s\n", str); /* 输出数组字符串str[] = strings */
printf("str[] = %6.3s\n", str);/* 输出最多3个字符的字符串 str[] = str */
return 0;
}

打印结果如下:

image-20220105210806637

二、输入函数

1.getchar

【函数描述】:C标准库<stdio.h>中的函数,从标准输入stdin获取一个字符(一个无符号字符)。

【函数声明】:

1
int getchar(void)

【函数参数】:无

【返回值】:该函数以无符号char强制转换为int的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF(-1)(输入Ctrl+d,就会返回 EOF)。

【函数实例】:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char a;
char b;
printf("请输入字符:");
a = getchar();
b = sizeof(a);
printf("输入的字符:");
putchar(a);
printf("\n");
printf("a = %d, a = %x, b = %d\n",a, a, b);
return 0;
}

运行结果如下:

image-20220106100551934

【注意】:通过该函数输入的都是字符,例如输入数字1,实际输入的是字符1

2.gets

【函数描述】:C标准库<stdio.h>中的函数,从标准输入stdin读取一行(以<Enter>结束),并把它存储在str所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

【函数声明】:

1
char *gets(char *str)

【函数参数】:

  • str: 这是指向一个字符数组的指针,该数组存储了 C 字符串。

【返回值】:如果成功,该函数返回str。如果发生错误或者到达文件末尾时还未读取任何字符,则返回NULL

【函数实例】:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main(int argc, char *argv[])
{
char str[50];
printf("请输入字符串:");
gets(str);
printf("输入的字符串:");
puts(str);
printf("str[50] = %s,\n", str);
return 0;
}

运行结果如下:

image-20220106101538008

【注意】:

  • gets从键盘输入一以回车结束的字符串放入字符数组中,并自动加**\0**。
  • 输入字符串长度应小于字符数组维数。
  • scanf函数不同,gets函数并不以空格作为字符串输入结束的标志。
  • 产生警告的原因:在后来的标准中已经移除该函数,取而代之的是fgets

3.scanf

3.1函数说明

【函数描述】:C标准库<stdio.h>中的函数,从标准输入 stdin 读取格式化输入。

【函数声明】:

1
int scanf(const char *format, ...)

【调用格式】:

1
scanf("<格式化字符串>", <地址表>);

【函数参数】:

  • 格式化字符串(format ):这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符format 说明符形式为:%[*][width][modifiers]type
参数 描述
* 这是一个可选的星号,表示数据是从流 stream 中读取的,但是可以被忽视,即它不存储在对应的参数中。
width 这指定了在当前读取操作中读取的最大字符数。
modifiers 为对应的附加参数所指向的数据指定一个不同于整型(针对 d、i 和 n)、无符号整型(针对 o、u 和 x)或浮点型(针对 e、f 和 g)的大小。
type 一个字符,指定了要被读取的数据类型以及数据读取方式。具体参见下一个表格。
  • 附加参数(地址表):根据不同的format字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了format参数中指定的每个 %标签。参数的个数应与%标签的个数相同。

【返回值】:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回EOF(-1)

【读取结束】:

  • <space>Tab、或Enter
  • 遇非法输入
  • 遇宽度结束

3.2格式化字符串详解

  • *

  基本没有用过,这里不再说明,以后用到了再补充。

  • 格式字符(type)
格式字符 形式 意义
i, d %i, %d 输入或读取十进制整数,数字前面的 + 或 - 号是可选的。
u %u 输入或读取十进制无符号整数。
o %o 输入或读取八进制无符号整数。
x, X %x, %X 输入或读取十六进制无符号整数。
f, F %f, %F 输入或读取小数形式(指数形式浮点小数 )浮点数。
e, E %e, %E
g, G %g, %G
c %c 输入或读取单个字符。空格和转义字符作为有效字符输入。
s %s 输入或读取字符串,这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。

【注意】:

  1.输入double类型数据必须用lf,不能用f

  2.输入%,可以用%%

  • 数据宽度(width)
参数 描述
number 指定输入数据宽度,遇空格或不可转换字符结束。
  • 修饰符(modifiers)
参数 描述
h 用于d, o, x前,指定输入为short型整数。
l 用于d, o, x前,指定输入为long型整数。
用于e, f前,指定输入为double型实数。
* 抑制符,指定输入项读入后不赋给变量。

3.3地址表详解

  scanf函数读取时,后边的地址表代表的是地址,也就是说,必须是地址的形式。

类型 说明
变量 对于变量,应该加上 & 符号,如:&a, &b等。
数组 对于数组,数组名就代表了该数组的起始地址,所以不需要加 & 。如:a[12]→a即可。
指针 对于指针,指针名就代表了该指针指向的地址,所以不需要加 & 。如: *p → p 即可。

3.4一般用法实例

  • 格式字符串必须严格按书写格式输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int main(int argc, char *argv[])
{
int a, a1, a2;
int b, b1, b2;
int c, c1, c2;
printf("请输入数据:");
scanf("%d%d%d",&a, &b, &c);
printf("输入的数据为:a = %d, b = %d, c = %d\n", a, b, c);

printf("请输入数据:");
scanf("%d,%d,%d",&a1, &b1, &c1);
printf("输入的数据为:a1 = %d, b1 = %d, c1 = %d\n", a1, b1, c1);

printf("请输入数据:");
scanf("%d %d %d",&a2, &b2, &c2);
printf("输入的数据为:a2 = %d, b2 = %d, c2 = %d\n", a2, b2, c2);

return 0;
}

运行效果:

image-20220106115533901

【注意】:

  1.scanf中的格式字符串中除了%部分的格式字符,其他的自行添加的(如,其他的字母等)在输入的时候要严格按照格式一起输入,否则输入的数据会有问题。经实验证明,格式字符串中的空格似乎不会对输入结果产生影响。

  2.在同时进行多个数字变量的数据输入时,相邻数据之间可以用<space><Tab>或者<Enter>均可,但要注意自己是否添加了其他字符。

  • 字符输入时的空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main(int argc, char *argv[])
{
char a;
char b;
char c;
char d;
printf("请输入字符:");
scanf("%c%c%c",&a, &b, &c);
printf("输入的字符为:a = %c, b = %c, c = %c\n", a, b, c);

printf("请输入字符:");
scanf("%c",&d);
printf("输入的字符为:d = %c\n", d);

return 0;
}
image-20220106155105187

【注意】:

  1.在用%c进行单个字符输入时,空格和转义字符作为有效字符输入

  2.在测试过程中,若有连续两个scanf函数进行输入时,上一个scanf多余出来的数据(**包括最后的<Enter>**)将会直接作为下一个scanf的输入。

  • 字符串输入时的空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main(int argc, char *argv[])
{
char str1[20];
char str2[20];
printf("请输入字符串:");
scanf("%s",str1);
printf("输入的字符串为:str[20] = %s\n", str1);

printf("请输入字符串:");
scanf("%s",str2);
printf("输入的字符串为:str[20] = %s\n", str2);

return 0;
}
image-20220106155842151

【注意】:

  1.%s进行字符串输入时,遇到<space>即认为该数据结束。

  2.若有连续两个scanf函数进行输入时,上一个scanf输入的数据若有<space>,则<space>后的数据,将会直接作为下一个scanf的输入。

  • 其他实例(也要注意)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
int main(int argc, char *argv[])
{
int y,m,d;
int y1,m1,d1;
int a;
char b;
float c;

printf("请输入数据:");
scanf("%4d%2d%2d", &y, &m, &d);
printf("输入的数据为:y = %d, m = %d, d = %d\n", y, m, d);

printf("请输入数据:");
/* scanf("%4d%*3d%2d", &y1, &m1, &d1); 将报too many arguments for format的waring*/
scanf("%4d%*3d%2d", &y1, &d1);
printf("输入的数据为:y1 = %d, m1 = %d, d1 = %d\n", y1, m1, d1);

printf("请输入数据:");
scanf("%d%c%f",&a,&b,&c);
printf("输入的数据为:a = %d, b = %c, c = %f\n", a, b, c);
return 0;
}
image-20220106161356110

【注意】:

  1.输入数据时,要格外注意遇以下情况认为该数据结束:遇**<space>Tab、或Enter;遇非法输入;遇宽度结束**。

  2.一定要注意上一次的数据输入是否还有余留,可能会导致后续输入出现问题,具体处理方法看后文。

  • 字符输入时,最后的换行的处理
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main(int argc, char *argv[])
{
int x;
char ch;
scanf("%d", &x);
// getchar(); /* 加上此行,吸收 <Enter> 或者可以用 scanf("%*c%c", &x); */
ch = getchar();
printf("x = %d, ch=%d\n", x, ch); /* \n 的十进制为 10 */

return 0;
}
image-20220106163053444

3.5scanf缓冲区处理实例

1
2
char ch;
while ((ch = getchar()) != EOF && ch != '\n') ; //清除缓冲区的内容

【说明】:输入流中多余的字符均可通过此行代码处理。

3.6scanf其他用法实例

  • 读取带空格的字符串
1
2
3
4
5
6
7
8
9
#include <stdio.h> 
int main(int argc, char *argv[])
{
char str[30];
printf("请输入字符串:");
scanf("%[^\n]",str); //读到'\n'结束读取
printf("输入的字符串为:%s\n",str);
return 0;
}
  • 另外几种
1
scanf("%[^\n]%*c",str); /* 遇到'\n'结束读取输入的字符,并存入str,然后再抛弃一个字符 */
1
scanf("%*[^\n]%*c");/* 遇到'\n'结束读取输入的字符,并将其读到的数据抛弃,然后再抛弃一个字符(其实这个字符是'\n'),此时缓存中不存在任何字符 */
1
2
3
4
char ch;
while ((ch = getchar()) != EOF && ch != '\n') ; /* 清除缓冲区的内容 */

scanf("%*[^\n]"); /* 与上边的循环等价 */
1
2
char ch;  
scanf("%*[^a]%*c%c",&ch); /* 遇到字符a停止读取,并舍弃a, 将a后的一个字符存入变量ch */

【参考网站】

cppreference https://en.cppreference.com/w/
Cplusplus http://www.cplusplus.com/
TutorialsPoint https://www.tutorialspoint.com/index.htm