C 输入 & 输出
当我们提到输入时,这意味着要向程序填充一些数据。输入可以是以文件的形式或从命令行中进行。C 语言提供了一系列内置的函数来读取给定的输入,并根据需要填充到程序中。
当我们提到输出时,这意味着要在屏幕上、打印机上或任意文件中显示一些数据。C 语言提供了一系列内置的函数来输出数据到计算机屏幕上和保存数据到文本文件或二进制文件中。
标准文件
C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕。
标准文件 | 文件指针 | 设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 屏幕 |
标准错误 | stderr | 您的屏幕 |
文件指针是访问文件的方式,本节将讲解如何从键盘上读取值以及如何把结果输出到屏幕上。
C 语言中的 I/O (输入/输出) 通常使用 printf() 和 scanf() 两个函数。
scanf() 函数用于从标准输入(键盘)读取并格式化, printf() 函数发送格式化输出到标准输出(屏幕)。
printf() 函数
printf() 函数用于将格式化的数据输出到标准输出设备(通常是屏幕)。
语法:
int printf(const char *format, ...);
参数:
format
:格式化字符串,指定输出的格式。...
:可变参数列表,根据格式化字符串中的格式说明符,提供要输出的数据。
实例
编译以上程序,输出结果为:
菜鸟教程
实例解析:
- 所有的 C 语言程序都需要包含 main() 函数。 代码从 main() 函数开始执行。
- printf() 用于格式化输出到屏幕。printf() 函数在 "stdio.h" 头文件中声明。
- stdio.h 是一个头文件 (标准输入输出头文件) and #include 是一个预处理命令,用来引入头文件。 当编译器遇到 printf() 函数时,如果没有找到 stdio.h 头文件,会发生编译错误。
- return 0; 语句用于表示退出程序。
%d 格式化输出整数
编译以上程序,输出结果为:
Number = 5
在 printf() 函数的引号中使用 "%d" (整型) 来匹配整型变量 testInteger 并输出到屏幕。
%f 格式化输出浮点型数据
scanf() 函数
scanf() 函数用于从标准输入设备(通常是键盘)读取格式化的输入。
语法:
int scanf(const char *format, ...);
参数:
format
:格式化字符串,指定输入的格式。...
:可变参数列表,根据格式化字符串中的格式说明符,提供存储输入数据的变量地址。
实例
int main() {
int a;
float b;
printf("Enter an integer and a float: ");
scanf("%d %f", &a, &b);
printf("You entered: %d and %.2f\n", a, b);
return 0;
}
执行以上代码,然后输入:
10 3.14
输出:
You entered: 10 and 3.14
字符输入输出
getchar() & putchar() 函数
int getchar(void) 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符。
请看下面的实例:
实例
当上面的代码被编译和执行时,它会等待您输入一些文本,当您输入一个文本并按下回车键时,程序会继续并只会读取一个单一的字符,显示如下:
$./a.out Enter a value :runoob You entered: r
字符串输入输出
gets() 和 fgets() 函数
gets() 函数用于从标准输入设备读取一行字符串,但不推荐使用,因为它容易导致缓冲区溢出,推荐使用 fgets() 函数。
语法:
char *fgets(char *str, int n, FILE *stream);
参数:
str
:指向字符数组的指针,用于存储读取的字符串。n
:要读取的最大字符数(包括空字符\0
)。stream
:文件流,通常使用stdin
表示标准输入。
实例
int main() {
char str[100];
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
printf("You entered: %s", str);
return 0;
}
puts() 函数
puts() 函数用于将一个字符串输出到标准输出设备,并自动在末尾添加换行符。
语法:
int puts(const char *str);
参数:
str
:要输出的字符串。
返回值:
成功时返回非负值,失败时返回
EOF
。
实例
int main() {
char str[] = "Hello, World!";
puts(str);
return 0;
}
输出:
Hello, World!
fputs() 函数
fputs() 函数用于将字符串输出到指定的流(如标准输出、文件等),但不会自动在字符串末尾添加换行符。
语法:
int fputs(const char *str, FILE *stream);
参数:
str
:要输出的字符串(以空字符\0
结尾的字符数组)。stream
:指定输出的流,可以是标准输出(stdout
)、文件流等。
返回值:
成功时返回一个非负值(通常是输出的字符数)。
失败时返回
EOF
。
特点:
不添加换行符:
fputs()
不会在输出字符串后自动添加换行符。灵活的输出流:
fputs()
可以输出到任意流,如标准输出、文件等。
实例
int main() {
char str[] = "Hello, World!";
fputs(str, stdout); // 输出 "Hello, World!",不换行
return 0;
}
puts() 和 fputs() 的区别
特性 | puts() | fputs() |
---|---|---|
换行符 | 自动在字符串末尾添加换行符 | 不添加换行符 |
输出流 | 只能输出到标准输出(屏幕) | 可以输出到任意流(如文件、屏幕) |
参数 | 只需要一个字符串参数 | 需要字符串参数和流参数 |
返回值 | 成功时返回非负值,失败时返回 EOF | 成功时返回非负值,失败时返回 EOF |
scanf() 和 printf() 函数
int scanf(const char *format, ...) 函数从标准输入流 stdin 读取输入,并根据提供的 format 来浏览输入。
int printf(const char *format, ...) 函数把输出写入到标准输出流 stdout ,并根据提供的格式产生输出。
format 可以是一个简单的常量字符串,但是您可以分别指定 %s、%d、%c、%f 等来输出或读取字符串、整数、字符或浮点数。还有许多其他可用的格式选项,可以根据需要使用。如需了解完整的细节,可以查看这些函数的参考手册。现在让我们通过下面这个简单的实例来加深理解:
实例
当上面的代码被编译和执行时,它会等待您输入一些文本,当您输入一个文本并按下回车键时,程序会继续并读取输入,显示如下:
$./a.out Enter a value :runoob 123 You entered: runoob 123
在这里,应当指出的是,scanf() 期待输入的格式与您给出的 %s 和 %d 相同,这意味着您必须提供有效的输入,比如 "string integer",如果您提供的是 "string string" 或 "integer integer",它会被认为是错误的输入。另外,在读取字符串时,只要遇到一个空格,scanf() 就会停止读取,所以 "this is test" 对 scanf() 来说是三个字符串。
文件输入与输出
C 语言还提供了文件输入输出的功能,允许从文件中读取数据或向文件中写入数据。
fopen() 函数
fopen() 函数用于打开一个文件。
语法:
FILE *fopen(const char *filename, const char *mode);
参数:
filename
:要打开的文件名。mode
:打开文件的模式,如"r"
(只读)、"w"
(只写)、"a"
(追加)等。
返回值:
成功时返回指向
FILE
对象的指针,失败时返回NULL
。
fclose() 函数
fclose() 函数用于关闭一个已打开的文件。
语法:
int fclose(FILE *stream);
参数:
stream
:指向FILE
对象的指针。
返回值:
成功时返回
0
,失败时返回EOF
。
实例
int main() {
FILE *file;
file = fopen("example.txt", "w"); // 打开文件用于写入
if (file != NULL) {
fprintf(file, "Hello, world!\n"); // 写入文件
fclose(file); // 关闭文件
}
char buffer[100];
file = fopen("example.txt", "r"); // 打开文件用于读取
if (file != NULL) {
fscanf(file, "%s", buffer); // 读取数据
printf("Read from file: %s\n", buffer);
fclose(file); // 关闭文件
}
return 0;
}
ms0
261***[email protected]
linux系统下需要这样编译:不支持 gets 与 puts, 需要用 fgets 和 fputs。
将以下代码放到 test.c 文件:
编译执行以上代码,输出结果为:
ms0
261***[email protected]
simone
183***[email protected]
参考地址
gets()与fgets()
gets()
gets函数原型:char*gets(char*buffer);//读取字符到数组:gets(str);str为数组名。
gets函数功能:从键盘上输入字符,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。
读取的换行符被转换为null值,做为字符数组的最后一个字符,来结束字符串。
注意:gets函数由于没有指定输入字符大小,所以会无限读取,一旦输入的字符大于数组长度,就会发生内存越界,
从而造成程序崩溃或其他数据的错误。
fgets()
fgets函数原型:char *fgets(char *s, int n, FILE *stream);//我们平时可以这么使用:fgets(str, sizeof(str), stdin);
其中str为数组首地址,sizeof(str)为数组大小,stdin表示我们从键盘输入数据。
fgets函数功能:从文件指针stream中读取字符,存到以s为起始地址的空间里,直到读完N-1个字符,或者读完一行。
注意:调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
借用教程实例,我把char str[100] 改为 char str[5]
如果输入123(长度小于5)结果为:
如果输入123456789(长度大于5)结果为:
虽然正常显示了,但是系统提示程序崩溃了
如果不能正确使用gets()函数,带来的危害是很大的,就如上面我们看到的,输入字符串的长度大于缓冲区长度时,并没有截断,原样输出了读入的字符串,造成程序崩溃。 考虑到程序安全性和健壮性,建议用fgets()来代替gets()。如:simone
183***[email protected]
参考地址
Mrodot
mro***@qq.com
参考地址
Windows、Unix、Mac不同操作系统的换行问题 回车符\r和换行符\n
一、概念:
换行符‘\n’和回车符‘\r’
(1)换行符就是另起一行 --- '\n' 10 换行(newline)
(2)回车符就是回到一行的开头 --- '\r' 13 回车(return)
所以我们平时编写文件的回车符应该确切来说叫做回车换行符
CR: 回车(Carriage Return) \rLF: 换行(Line Feed) \n
二、应用:
(1)在微软的MS-DOS和Windows中,使用“回车CR('\r')”和“换行LF('\n')”两个字符作为换行符;
(2)Windows系统里面,每行结尾是 回车+换行(CR+LF),即“\r\n”;
(3)Unix系统里,每行结尾只有 换行LF,即“\n”;
(4)Mac系统里,每行结尾是 回车CR 即'\r'。
Mac OS 9 以及之前的系统的换行符是 CR,从 Mac OS X (后来改名为“OS X”)开始的换行符是 LF即‘\n',和Unix/Linux统一了。
三、影响:
(1)一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;
(2)而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
(3)Linux保存的文件在windows上用记事本看的话会出现黑点。
四、可以相互转换:
在linux下,命令unix2dos 是把linux文件格式转换成windows文件格式,命令dos2unix 是把windows格式转换成linux文件格式。
在不同平台间使用FTP软件传送文件时, 在ascii文本模式传输模式下, 一些FTP客户端程序会自动对换行格式进行转换. 经过这种传输的文件字节数可能会发生变化.
如果你不想ftp修改原文件, 可以使用bin模式(二进制模式)传输文本。
一个程序在windows上运行就生成CR/LF换行格式的文本文件,而在Linux上运行就生成LF格式换行的文本文件。
Mrodot
mro***@qq.com
参考地址
halo
g51***vip.qq.com
学 C 语言的时候,字符输入曾经困扰过我,例如这段代码:
这时候变量 c 中存储的往往不是你想输入的字符,而是一个空格,然后我们又会这样来写:
这时候,我们发现,根本没有输入字符C的机会,这是为什么?因为输入流是有缓冲区的,我们输入的字符存储在那,然后再赋值给我们的变量。我们可以这样改:
这个办法是一直读取,读到没有空格和换行就跳出循环,但是有一个更好的解决办法;
这是用正则表达来控制输入格式为非空格非换行。
halo
g51***vip.qq.com
CSTwang
248***[email protected]
在进行输出时,若要用到用来输出实数的 f 格式符(以小数形式输出),有以下几种用法:
1、基本型,用 %f
不指定输出类型的长度,用系统根据情况决定,一般是实数中的整数部分全部输出,小数部分输出六位。例:
运行结果:0.333333
2、指定数据宽度和小数位数,用 %m.nf
例:将上个程序的双精度变量 a 输出 15 位小数,用 %20.15f 的格式声明,指定输出的数据占 20 列,其中包括 15 位小数。改动上面程序如下:
运行结果: 0.333333333333333
注意在 0 的前面有 3 个空格,且双精度数只保证 15 位有效数字的准确性。
3、输出的数据相左对齐,用 %-m.nf
在 m.n 前加一个负号,其作用与 %m.nf 形式作用基本相同,但当数据长度不长过 m 时,数据向左靠,右端补空格。
CSTwang
248***[email protected]
CSTwang
248***[email protected]
有关 putchar 的一个程序。
先后输出BOY三个字符。
例子1:
例子2:
两个运行结果相同,因为将一个字符赋给字符变量和将字符的 ASCII 代码赋给字符变量作用是完全相同的,但要注意其值必须在字符的 ASCII 代码范围内。
CSTwang
248***[email protected]
Jiangang
121***[email protected]
scanf 是有返回值的,例如:
测试输出:
从上边的例子中可以得到验证,这里用变量 x 接收 scanf() 函数的返回值,并输出显示出来。
Jiangang
121***[email protected]
极地
160***[email protected]
在输入时注意格式对应:
若在输入时用错空格键或者换行符,则会出现错误:
上述输入只能输出 a=1 因为空格键取代了 x 的位置 输入完 x=1.2 后空格键有取代了应该输入 c1 的位置。
正确的输入应为:
极地
160***[email protected]
dte2mdj
awe***[email protected]
gets() & puts() 函数
使用 gets() 会报警告:
gets() 不安全是因为未指定缓冲区大小。可以使用 fgets();
返回值:成功,则函数返回 buf。
如果当尝试读取一个字符时遇到了文件结尾,则 eof 被置位(feof),如果还没有成功读入任何一个字符就遇到了文件结尾,那么就会返回 null,buff 中的内容保持不变。如果读取错误发生,那么 error indicator(ferror) 被置位,还是返回 null。
dte2mdj
awe***[email protected]
hefudnd
hef***[email protected]
参考地址
c 语言中每种数据类型的输出都有各自的占位符,下面是各种数据类型的输出占位符:
short/int : %d
long: %ld (long 是 int 得修饰,不能算是一种单独的数据类型,只是比 int 多了四个字节的存储空间)
long long : %lld
char : %c
float/double : %f float 默认是 6 位小数输出;可以在 %f 中控制;例如:%.2f:输出两位小数。
char *s(字符串) :%s
unsigned: %u (signed:有符号类型, unsigned:无符号类型;默认都是有符号的)
八进制:%o 以 0 开头
十六进制:%x 以 0x 开头
地址值/指针值:%p,* 取指针里地址指向的地方的值,& 取改值存储位置的地址值。
二进制的输出没有占位符,只能通过其他方法。
hefudnd
hef***[email protected]
参考地址