目录
每次读写会改变流的位置,因此为了更好的操作,可以对流进行定位操作。
标准IO总结
一、标准IO(符合ANSI C的标准)
1、流的缓冲类型
①、全缓冲:缓冲区满才输出
②、行缓冲:遇到换行符输出
③、无缓冲:不对IO操作进行缓冲
2、流的打开
使用标准IO打开文件
函数原型:
FILE * fopen(const char * path, const char * mode);
参数:
path:要代开文件的路径及文件名
mode:打开方式,具体有以下几种:
r 或 rb:打开只读文件,注意文件必须存在。
r+ 或 r+b:打开可读可写文件,注意文件也必须存在。
w 或 wb:打开只写文件,它会自己创建文件,如果文件已经存在,他会擦除已经写入的内容。
w+ 或 w+b:打开可写可读文件,它会自己创建文件,如果文件已经存在,他会擦除已经写入的内容。
a 或 ab:以附加内容的方式打开可写文件,就是写入的数据会被加到文件的末尾,原来的文件会被保留,如果文件不存在会创建文 件。
a+ 或 a+b:以附加内容的方式打开可读可写文件,就是写入的数据会被加到文件的末尾,原来的文件会被保留,如果文件不存在会 创建文件。
返回值
成功时返回一个指向 FILE 类型的指针,表示文件流。
失败时返回 NULL,可以通过 errno 获取错误原因。
示例代码
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
perror("Error opening file");
return 1;
}
fprintf(file, "Hello, World!\n");
fclose(file);
return 0;
}
2、流的关闭
函数原型:
int fclose(FILE *stream);
参数
stream:指向 FILE 类型的指针,表示要关闭的文件流。这个指针是通过 fopen 或其他文件打开函数(如 tmpfile、fopen_s 等)返回的。
返回值
成功时返回 0。
失败时返回 EOF(通常定义为 -1),可以通过 errno 获取错误原因。
3、错误处理
下面函数打印一条错误消息,该消息包含了当前程序的错误状态。
函数原型
void perror(const char *s);
参数
s:一个指向字符串的指针,该字符串将被打印在错误消息之前。如果传入 NULL,则不会打印用户自定义的字符串,直接打印错误信息。
示例代码
#include <stdio.h>
#include <errno.h>
int main() {
FILE *file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
perror("Error opening file"); // 打印错误信息
return 1;
}
fclose(file);
return 0;
}
如果文件 "nonexistent_file.txt" 不存在,程序将输出类似以下内容:
Error opening file: No such file or directory
下面函数将错误代码转换为对应的错误信息字符串
函数原型
char *strerror(int errnum);
参数
errnum:错误代码,通常是全局变量 errno 的值。
返回值
返回一个指向错误信息字符串的指针,该字符串描述了错误代码 errnum 对应的错误。需要注意的是,返回的字符串是由 strerror 内部管理的,程序不应修改该字符串。
示例代码
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
FILE *file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
printf("Error: %s\n", strerror(errno));
}
return 0;
}
如果文件 "nonexistent_file.txt" 不存在,程序将输出类似以下内容:
Error: No such file or directory
4、流的读写
按字节输入、输出
①、输入
函数原型:
int getc (FILE * stream);//指定从流中读一个字符
int fgetc (FILE * stream);//指定从流中读一个字符
int getchar (void);//从stdin中读入一个字节
函数参数:
stream:要输入的文件流
返回值:
成功返回读取的字符
失败返回EOF
实例代码1:
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
int ch;
while ((ch = getc(file)) != EOF) { // 逐字符读取
putchar(ch); // 将读取的字符打印到标准输出
}
if (fclose(file) != 0) {
perror("Error closing file");
return 1;
}
return 0;
}
实例代码2:
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF) { // 逐字符读取
putchar(ch); // 将读取的字符打印到标准输出
}
if (ferror(file)) {
perror("Error reading file");
}
if (fclose(file) != 0) {
perror("Error closing file");
return 1;
}
return 0;
}
实例代码3:
#include <stdio.h>
int main() {
int ch;
printf("Enter some text (press Ctrl+D to end on Unix, Ctrl+Z on Windows):\n");
while ((ch = getchar()) != EOF) { // 逐字符读取
putchar(ch); // 将读取的字符打印到标准输出
}
if (ferror(stdin)) {
perror("Error reading from stdin");
}
printf("\nEnd of input.\n");
return 0;
}
②、输出
函数原型:
int putc (int c, FILE * stream);
int fputc (int c, FILE * stream);
int putchar (int c);
函数参数:
ch:要写入的字符。
stream:指向 FILE 对象的指针,标识要写入字符的流。
返回值:
成功返回写入的字符
失败返回EOF
实例代码1:
#include <stdio.h>
int main() {
FILE *pFile;
char c;
pFile = fopen("alphabet.txt", "wt");
for (c = 'A'; c <= 'Z'; c++) {
putc(c, pFile);
}
fclose(pFile);
return 0;
}
实例代码2:
#include <stdio.h>
int main() {
FILE *pFile;
char c;
pFile = fopen("alphabet.txt", "wt");
if (pFile == NULL) {
printf("文件打开失败!");
return -1;
}
for (c = 'A'; c <= 'Z'; c++) {
fputc(c, pFile);
}
fclose(pFile);
return 0;
}
实例代码3:
#include <stdio.h>
int main() {
char c;
for (c = 'A'; c <= 'Z'; c++) {
putchar(c);
}
putchar('\n'); // 写入换行符
return 0;
}
按行输入、输出
①、输入
函数原型1:
char* gets(char* s);//在C11被移除了
参数
s:指向字符数组的指针,用于存储从标准输入读取的字符串。
返回值
成功时返回参数 s,即存储输入字符串的数组的首地址。
如果发生读取错误或到达文件末尾(EOF),返回 NULL。
-
严重安全隐患:
gets不检查目标数组的大小,容易导致缓冲区溢出。如果输入的字符串长度超过了目标数组的大小,会导致内存破坏,从而引发安全漏洞。
示例代码
#include <stdio.h>
int main() {
char buffer[10];
printf("请输入一行文本:");
gets(buffer); // 不安全的函数
printf("您输入的内容是:%s\n", buffer);
return 0;
}
注意:如果输入的字符串长度超过 buffer 的大小(在这个例子中是 9 个字符,因为最后一个位置用于存储字符串结束符 \0),会导致缓冲区溢出。
函数原型2:
fgets 是 gets 的安全替代品,它允许指定目标缓冲区的大小,从而避免缓冲区溢出。
char* fgets(char* s, int size, FILE* stream);
参数:
s:目标字符数组。
size:目标数组的最大大小。
stream:输入流,默认为 stdin。
返回值:
成功时返回参数 s。
如果发生读取错误或到达文件末尾,返回 NULL。
示例代码:
#include <stdio.h>
int main() {
char buffer[10];
printf("请输入一行文本:");
if (fgets(buffer, sizeof(buffer), stdin)) {
// 去掉换行符
buffer[strcspn(buffer, "\n")] = '\0';
printf("您输入的内容是:%s\n", buffer);
}
return 0;
}
注意:fgets不能保证每次都能读出一行
②、输出
函数原型1:
int puts(const char *s);
参数
s:指向要输出的字符串的指针。该字符串必须以空字符(\0)结尾。
返回值
成功时返回非负值(通常是输出的字符数)。
如果发生输出错误,返回 EOF(通常定义为 -1)。
-
puts会将字符串输出到标准输出流stdout,并在字符串末尾自动添加一个换行符。
示例代码
#include <stdio.h>
int main() {
const char *str1 = "Hello, World!";
const char *str2 = "This is a test.";
puts(str1); // 输出 "Hello, World!" 并换行
puts(str2); // 输出 "This is a test." 并换行
return 0;
}
输出结果:
Hello, World! This is a test.
函数原型2:
int fputs(const char *s, FILE *stream);
参数
s:指向要写入的字符串的指针。该字符串必须以空字符(\0)结尾。
stream:指向 FILE 对象的指针,标识要写入的文件流。
返回值
成功时返回非负值(通常是 0 或 1,具体值取决于实现)。
如果发生写入错误,返回 EOF(通常定义为 -1)。
-
fputs将字符串写入到指定的文件流中,不会自动添加换行符。
示例代码:
#include <stdio.h>
int main() {
FILE *file;
const char *str1 = "Hello, World!";
const char *str2 = "This is a test.";
// 打开文件用于写入
file = fopen("output.txt", "w");
if (file == NULL) {
printf("文件打开失败!");
return -1;
}
// 写入字符串
fputs(str1, file);
fputs("\n", file); // 显式添加换行符
fputs(str2, file);
fputs("\n", file); // 显式添加换行符
// 关闭文件
fclose(file);
return 0;
}
运行后,output.txt 文件的内容为:
Hello, World! This is a test.
以指定大小单位读写文件
读
函数原型1:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数
ptr:指向存储读取数据的缓冲区的指针。
size:每个数据项的大小(以字节为单位)。
count:要读取的数据项的数量。
stream:指向 FILE 对象的指针,标识要从中读取数据的文件流。
返回值
成功时返回实际读取的数据项的数量。
如果到达文件末尾(EOF)或发生读取错误,返回值会小于 count。
如果返回值为 0,可能是到达文件末尾或发生错误。可以通过 feof 和 ferror 函数来区分这两种情况。
-
fread是一个通用的文件读取函数,可以读取任意类型的数据。 -
它支持二进制文件和文本文件,但通常用于二进制文件,因为文本文件的读取通常更适合使用
fgets等函数。 -
fread会根据指定的size和count参数,从文件流中读取数据,并将其存储到指定的缓冲区中。 -
如果文件流中的数据不足,
fread会读取尽可能多的数据,返回值会小于count。
示例代码1:
示例 1:读取文本文件
假设有一个文本文件 data.txt,内容如下:
Hello, World! This is a test.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
char buffer[100];
// 打开文件用于读取
file = fopen("data.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 读取数据
size_t bytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, file);
buffer[bytesRead] = '\0'; // 确保字符串以空字符结尾
// 输出读取的内容
printf("读取的内容:\n%s\n", buffer);
// 关闭文件
fclose(file);
return 0;
}
输出结果:
读取的内容: Hello, World! This is a test.
示例代码2:读取二进制文件
假设有一个二进制文件 data.bin,包含一些整数数据。
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
int buffer[10];
size_t bytesRead;
// 打开文件用于读取
file = fopen("data.bin", "rb");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 读取数据
bytesRead = fread(buffer, sizeof(int), 10, file);
// 输出读取的内容
printf("读取了 %zu 个整数:\n", bytesRead);
for (size_t i = 0; i < bytesRead; i++) {
printf("%d ", buffer[i]);
}
printf("\n");
// 关闭文件
fclose(file);
return 0;
}
写
函数原型:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
参数
ptr:指向要写入的数据的指针。
size:每个数据项的大小(以字节为单位)。
count:要写入的数据项的数量。
stream:指向 FILE 对象的指针,标识要写入数据的文件流。
返回值
成功时返回实际写入的数据项的数量。
如果发生写入错误,返回值会小于 count。
如果返回值为 0,可能是到达文件末尾或发生错误。可以通过 ferror 函数来检查是否发生错误。
-
fwrite是一个通用的文件写入函数,可以写入任意类型的数据。 -
它支持二进制文件和文本文件,但通常用于二进制文件,因为文本文件的写入通常更适合使用
fprintf或fputs等函数。 -
fwrite会根据指定的size和count参数,将数据从指定的缓冲区写入到文件流中。 -
如果文件流中的空间不足,
fwrite会写入尽可能多的数据,返回值会小于count。
示例代码1:
示例 1:写入文本数据
假设要将一个字符串写入到文本文件 output.txt 中。
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
const char *str = "Hello, World!";
// 打开文件用于写入
file = fopen("output.txt", "w");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 写入数据
size_t bytesWritten = fwrite(str, sizeof(char), strlen(str), file);
// 检查写入是否成功
if (bytesWritten != strlen(str)) {
perror("写入文件时发生错误");
}
// 关闭文件
fclose(file);
return 0;
}
运行后,output.txt 文件的内容为:
Hello, World!
代码示例 2:写入二进制数据
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
int data[] = {1, 2, 3, 4, 5};
size_t count = sizeof(data) / sizeof(data[0]);
// 打开文件用于写入
file = fopen("data.bin", "wb");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 写入数据
size_t itemsWritten = fwrite(data, sizeof(int), count, file);
// 检查写入是否成功
if (itemsWritten != count) {
perror("写入文件时发生错误");
}
// 关闭文件
fclose(file);
return 0;
}
5、流的定位
每次读写会改变流的位置,因此为了更好的操作,可以对流进行定位操作。
移动流的位置
函数原型:
int fseek(FILE *stream, long offset, int whence);
参数:
stream:指向 FILE 对象的指针,标识要操作的文件流。
offset:偏移量,表示要移动的字节数。
whence:指定偏移量的基准位置,可以取以下值:
-
SEEK_SET:文件开头(从文件开头开始计算偏移量)。 -
SEEK_CUR:当前位置(从当前位置开始计算偏移量)。 -
SEEK_END:文件末尾(从文件末尾开始计算偏移量)。
返回值:
成功时返回 0。
如果发生错误,返回非零值(通常为 -1)。
-
它通常用于二进制文件,因为文本文件的读写操作可能会受到换行符等特殊字符的影响。
-
在文本模式下使用
fseek时,只有当偏移量为零且基准位置为SEEK_SET或SEEK_END时,才能保证行为是定义良好的。 -
在二进制模式下,
fseek的行为是完全定义的,可以精确地移动文件指针。
示例代码1:
跳到文件开头
#include <stdio.h>
int main() {
FILE *file;
char buffer[100];
file = fopen("example.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 跳到文件开头
if (fseek(file, 0, SEEK_SET) != 0) {
perror("移动文件指针失败");
fclose(file);
return -1;
}
// 读取文件内容
if (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("读取的内容:%s", buffer);
}
fclose(file);
return 0;
}
实例代码2:
跳到文件末尾
#include <stdio.h>
int main() {
FILE *file;
long fileSize;
file = fopen("example.txt", "rb");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 跳到文件末尾
if (fseek(file, 0, SEEK_END) != 0) {
perror("移动文件指针失败");
fclose(file);
return -1;
}
// 获取文件大小
fileSize = ftell(file);
printf("文件大小:%ld 字节\n", fileSize);
fclose(file);
return 0;
}
示例 代码3:
从当前位置移动
#include <stdio.h>
int main() {
FILE *file;
char buffer[100];
file = fopen("example.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 跳过前 10 个字节
if (fseek(file, 10, SEEK_SET) != 0) {
perror("移动文件指针失败");
fclose(file);
return -1;
}
// 从当前位置再跳过 5 个字节
if (fseek(file, 5, SEEK_CUR) != 0) {
perror("移动文件指针失败");
fclose(file);
return -1;
}
// 读取文件内容
if (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("读取的内容:%s", buffer);
}
fclose(file);
return 0;
}
得到流的位置
函数原型:
long ftell(FILE *stream);
参数:
stream:指向 FILE 对象的指针,标识要查询的文件流。
返回值:
成功时返回当前文件位置指示符的位置(以字节为单位)。
如果发生错误,返回 -1L(负一)。
-
ftell返回的值表示从文件开头到当前文件位置指示符的距离(以字节为单位)。 -
在二进制模式下,
ftell的返回值是精确的,可以直接用于文件定位。 -
在文本模式下,
ftell的返回值可能不完全精确,因为文本模式下的文件操作会受到换行符等特殊字符的影响。 -
ftell通常与fseek配合使用,用于定位文件中的特定位置。
示例代码1:
获取文件指针的当前位置
#include <stdio.h>
int main() {
FILE *file;
long position;
file = fopen("example.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 获取文件指针的当前位置
position = ftell(file);
if (position == -1L) {
perror("获取文件位置失败");
fclose(file);
return -1;
}
printf("当前文件指针的位置:%ld 字节\n", position);
fclose(file);
return 0;
}
示例代码 2:
获取文件大小
#include <stdio.h>
int main() {
FILE *file;
long fileSize;
file = fopen("example.txt", "rb");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 跳到文件末尾
if (fseek(file, 0, SEEK_END) != 0) {
perror("移动文件指针失败");
fclose(file);
return -1;
}
// 获取文件大小
fileSize = ftell(file);
if (fileSize == -1L) {
perror("获取文件大小失败");
fclose(file);
return -1;
}
printf("文件大小:%ld 字节\n", fileSize);
fclose(file);
return 0;
}
示例 代码3:
读取文件内容并记录位置
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
char buffer[100];
long position;
file = fopen("example.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 读取文件内容
while (fgets(buffer, sizeof(buffer), file) != NULL) {
// 获取当前文件指针的位置
position = ftell(file);
if (position == -1L) {
perror("获取文件位置失败");
fclose(file);
return -1;
}
printf("读取的内容:%s", buffer);
printf("当前文件指针的位置:%ld 字节\n", position);
}
fclose(file);
return 0;
}
6、格式化的输入、输出
①、输入
函数原型1:
int scanf(const char *format, ...);
参数:
format:格式控制字符串,用于指定输入的格式。它包含格式说明符(如 %d、%s、%f 等)和普通字符。
... :可变参数列表,用于存储读取的数据。每个格式说明符对应一个变量的地址。
返回值:
成功时返回成功读取的输入项数量。
如果到达文件末尾(EOF)或发生输入错误,返回值会小于预期的输入项数量。
如果没有成功读取任何输入项,返回值可能为 0 或 EOF。
格式说明符:
scanf 使用格式说明符来指定输入的类型和格式。以下是一些常见的格式说明符:
-
%d:读取十进制整数。 -
%u:读取无符号十进制整数。 -
%f:读取浮点数。 -
%lf:读取双精度浮点数(double)。 -
%c:读取单个字符。 -
%s:读取字符串(以空字符\0结尾)。 -
%x或%X:读取十六进制整数。 -
%o:读取八进制整数。 -
%p:读取指针地址。 -
%[...]:读取字符集,直到遇到不在字符集中的字符为止。
示例 代码1:
读取整数和浮点数
#include <stdio.h>
int main() {
int num1;
float num2;
printf("请输入一个整数和一个浮点数:");
if (scanf("%d %f", &num1, &num2) == 2) {
printf("整数:%d\n", num1);
printf("浮点数:%f\n", num2);
} else {
printf("输入格式错误!\n");
}
return 0;
}
示例 代码2:
读取字符串
#include <stdio.h>
int main() {
char str[100];
printf("请输入一行文本:");
if (scanf("%s", str)) {
printf("您输入的内容:%s\n", str);
} else {
printf("输入失败!\n");
}
return 0;
}
示例代码 3:
读取多个数据类型
#include <stdio.h>
int main() {
int age;
float height;
char name[100];
printf("请输入您的姓名、年龄和身高:");
if (scanf("%s %d %f", name, &age, &height) == 3) {//这个输入有讲究,需要使用空格来隔开输入
printf("姓名:%s\n", name);
printf("年龄:%d\n", age);
printf("身高:%.2f\n", height);
} else {
printf("输入格式错误!\n");
}
return 0;
}
函数原型2:
int fscanf(FILE *stream, const char *format, ...);
参数:
stream:指向 FILE 对象的指针,标识要从中读取数据的文件流。
format:格式控制字符串,用于指定输入的格式。它包含格式说明符(如 %d、%s、%f 等)和普通字符。
... :可变参数列表,用于存储读取的数据。每个格式说明符对应一个变量的地址。
返回值:
成功时返回成功读取的输入项数量。
如果到达文件末尾(EOF)或发生输入错误,返回值会小于预期的输入项数量。
如果没有成功读取任何输入项,返回值可能为 0 或 EOF。
格式说明符:
fscanf 使用的格式说明符与 scanf 相同
示例 代码1:
从文件中读取整数和浮点数
假设有一个文件 data.txt,内容如下:
123 45.67
#include <stdio.h>
int main() {
FILE *file;
int num1;
float num2;
file = fopen("data.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 从文件中读取数据
if (fscanf(file, "%d %f", &num1, &num2) == 2) {
printf("整数:%d\n", num1);
printf("浮点数:%f\n", num2);
} else {
printf("输入格式错误!\n");
}
fclose(file);
return 0;
}
示例 代码2:
从文件中读取字符串
假设有一个文件 data.txt,内容如下:
Hello, World!
#include <stdio.h>
int main() {
FILE *file;
char str[100];
file = fopen("data.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 从文件中读取字符串
if (fscanf(file, "%s", str) == 1) {
printf("读取的字符串:%s\n", str);
} else {
printf("输入失败!\n");
}
fclose(file);
return 0;
}
示例代码3:
从文件中读取多行数据
假设有一个文件 data.txt,内容如下:
John 25 Alice 30
#include <stdio.h>
int main() {
FILE *file;
char name[100];
int age;
file = fopen("data.txt", "r");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 逐行读取数据
while (fscanf(file, "%s %d", name, &age) == 2) {
printf("姓名:%s,年龄:%d\n", name, age);
}
fclose(file);
return 0;
}
函数原型3:
int sscanf(const char *str, const char *format, ...);
参数:
str:指向要解析的字符串的指针。
format:格式控制字符串,用于指定输入的格式。它包含格式说明符(如 %d、%s、%f 等)和普通字符。
... :可变参数列表,用于存储解析后的数据。每个格式说明符对应一个变量的地址。
返回值:
成功时返回成功读取的输入项数量。
如果没有成功读取任何输入项,返回值可能为 0。
如果输入字符串格式不匹配或发生错误,返回值会小于预期的输入项数量。
格式说明符:
sscanf 使用的格式说明符与 scanf 和 fscanf 相同
示例代码 1:
从字符串中读取整数和浮点数
假设有一个字符串 "123 45.67",需要从中提取整数和浮点数。
#include <stdio.h>
int main() {
const char *str = "123 45.67";
int num1;
float num2;
// 从字符串中读取数据
if (sscanf(str, "%d %f", &num1, &num2) == 2) {
printf("整数:%d\n", num1);
printf("浮点数:%f\n", num2);
} else {
printf("输入格式错误!\n");
}
return 0;
}
示例 代码2:
从字符串中读取日期
假设有一个字符串 "2023-10-25",需要从中提取年、月、日。
#include <stdio.h>
int main() {
const char *str = "2023-10-25";
int year, month, day;
// 从字符串中读取日期
if (sscanf(str, "%d-%d-%d", &year, &month, &day) == 3) {
printf("年:%d\n", year);
printf("月:%d\n", month);
printf("日:%d\n", day);
} else {
printf("输入格式错误!\n");
}
return 0;
}
示例代码 3:
从字符串中读取多组数据
假设有一个字符串 "John 25 Alice 30",需要从中提取多组姓名和年龄。
#include <stdio.h>
int main() {
const char *str = "John 25 Alice 30";
char name1[100], name2[100];
int age1, age2;
// 从字符串中读取多组数据
if (sscanf(str, "%s %d %s %d", name1, &age1, name2, &age2) == 4) {
printf("姓名:%s,年龄:%d\n", name1, age1);
printf("姓名:%s,年龄:%d\n", name2, age2);
} else {
printf("输入格式错误!\n");
}
return 0;
}
②、输出
函数原型1:
int printf(const char *format, ...);
参数:
format:格式控制字符串,用于指定输出的格式。它包含普通字符和格式说明符。
... :可变参数列表,用于提供要输出的数据。每个格式说明符对应一个参数。
返回值:
成功时返回输出的字符数量(不包括末尾的换行符)。
如果发生错误,返回负值。
格式说明符:
printf 使用格式说明符来指定输出的类型和格式。以下是一些常见的格式说明符:
-
%d或%i:输出十进制整数。 -
%u:输出无符号十进制整数。 -
%f:输出浮点数(默认为双精度)。 -
%lf:输出双精度浮点数(与%f等效)。 -
%c:输出单个字符。 -
%s:输出字符串。 -
%x或%X:以十六进制形式输出整数(%x小写,%X大写)。 -
%o:以八进制形式输出整数。 -
%p:输出指针地址。 -
%%:输出一个百分号(%)。
格式修饰符:
printf 还支持格式修饰符,用于控制输出的宽度、精度、对齐方式等:
-
宽度:
%5d表示输出宽度为 5 个字符,不足部分用空格填充。 -
左对齐:
%-5d表示左对齐,宽度为 5 个字符。 -
精度:
%.2f表示浮点数保留两位小数。 -
填充字符:
%05d表示用0填充,宽度为 5 个字符。
示例 代码1:
输出整数和浮点数
#include <stdio.h>
int main() {
int num1 = 123;
float num2 = 45.67;
printf("整数:%d\n", num1);
printf("浮点数:%.2f\n", num2);
return 0;
}
示例代码 2:
输出字符串和字符
#include <stdio.h>
int main() {
char str[] = "Hello, World!";
char ch = 'A';
printf("字符串:%s\n", str);
printf("字符:%c\n", ch);
return 0;
}
示例代码 3:
控制输出格式
#include <stdio.h>
int main() {
int num1 = 123;
float num2 = 45.67;
printf("整数:%5d\n", num1); // 输出宽度为 5
printf("浮点数:%-10.2f\n", num2); // 左对齐,宽度为 10,保留两位小数
printf("十六进制:%X\n", num1); // 输出十六进制
return 0;
}
示例 代码4:
输出指针地址
#include <stdio.h>
int main() {
int num = 123;
int *ptr = #
printf("指针地址:%p\n", ptr);
return 0;
}
函数原型2:
int fprintf(FILE *stream, const char *format, ...);
参数:
stream:指向 FILE 对象的指针,标识要输出到的文件流。
format:格式控制字符串,用于指定输出的格式。它包含普通字符和格式说明符。
... :可变参数列表,用于提供要输出的数据。每个格式说明符对应一个参数。
返回值:
成功时返回输出的字符数量(不包括末尾的换行符)。
如果发生错误,返回负值。
格式说明符:
fprintf 使用的格式说明符与 printf 相同
格式修饰符:
fprintf 也支持格式修饰符与 printf 相同
示例 代码1:
向文件输出整数和浮点数
假设要将一些数据写入到文件 output.txt 中。
#include <stdio.h>
int main() {
FILE *file;
int num1 = 123;
float num2 = 45.67;
file = fopen("output.txt", "w");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 向文件输出数据
fprintf(file, "整数:%d\n", num1);
fprintf(file, "浮点数:%.2f\n", num2);
fclose(file);
return 0;
}
运行后,output.txt 文件的内容为:
整数:123 浮点数:45.67
示例代码2:
向文件输出字符串和字符
假设要将一些文本数据写入到文件 output.txt 中。
#include <stdio.h>
int main() {
FILE *file;
char str[] = "Hello, World!";
char ch = 'A';
file = fopen("output.txt", "w");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 向文件输出数据
fprintf(file, "字符串:%s\n", str);
fprintf(file, "字符:%c\n", ch);
fclose(file);
return 0;
}
运行后,output.txt 文件的内容为:
字符串:Hello, World! 字符:A
示例 代码3:
控制输出格式
假设要将一些格式化的数据写入到文件 output.txt 中。
#include <stdio.h>
int main() {
FILE *file;
int num1 = 123;
float num2 = 45.67;
file = fopen("output.txt", "w");
if (file == NULL) {
perror("文件打开失败");
return -1;
}
// 向文件输出格式化数据
fprintf(file, "整数:%5d\n", num1); // 输出宽度为 5
fprintf(file, "浮点数:%-10.2f\n", num2); // 左对齐,宽度为 10,保留两位小数
fprintf(file, "十六进制:%X\n", num1); // 输出十六进制
fclose(file);
return 0;
}
运行后,output.txt 文件的内容为:
整数: 123 浮点数:45.67 十六进制:7B
函数原型3:
int sprintf(char *str, const char *format, ...);
参数:
str:指向目标字符数组的指针,格式化后的字符串将存储在这个数组中。
format:格式控制字符串,用于指定输出的格式。它包含普通字符和格式说明符。
... :可变参数列表,提供要格式化的数据。每个格式说明符对应一个参数。
返回值:
成功时返回写入的字符数量(不包括字符串结束符 \0)。
如果发生错误,返回负值。
格式说明符:
sprintf 使用的格式说明符与 printf 和 fprintf 相同
示例代码1:
将整数和浮点数格式化为字符串
#include <stdio.h>
int main() {
char buffer[100];
int num1 = 123;
float num2 = 45.67;
// 将数据格式化为字符串
int count = sprintf(buffer, "整数:%d,浮点数:%.2f", num1, num2);
printf("格式化后的字符串:%s\n", buffer);
printf("写入的字符数量:%d\n", count);
return 0;
}
输出结果:
格式化后的字符串:整数:123,浮点数:45.67 写入的字符数量:22
示例代码 2:
动态生成日志信息
#include <stdio.h>
int main() {
char buffer[100];
char logLevel[] = "ERROR";
char message[] = "File not found";
// 动态生成日志信息
sprintf(buffer, "[%s] %s", logLevel, message);
printf("日志信息:%s\n", buffer);
return 0;
}
输出结果:
日志信息:[ERROR] File not found
示例代码3:
格式化日期和时间
#include <stdio.h>
int main() {
char buffer[100];
int year = 2023;
int month = 10;
int day = 25;
// 格式化日期
sprintf(buffer, "今天的日期是:%04d-%02d-%02d", year, month, day);
printf("格式化后的日期:%s\n", buffer);
return 0;
}
输出结果:
格式化后的日期:2023-10-25
参考资源:https://download.csdn.net/download/2403_82436914/90610803?spm=1001.2014.3001.5503
4336




被折叠的 条评论
为什么被折叠?



