scanf、fscanf 和 sscanf 是 C 语言中用于输入操作的函数,特别是用于格式化输入。它们属于标准输入/输出库,用于按照指定格式从不同来源读取数据。
以下是它们的基本详情和区别:
scanf ( ):
示例:读取一个整数和一个字符。
int i;
char c;
scanf("%d %c", &i, &c);
fscanf ( ):
示例:从文件中读取一个整数。
FILE *fp;
int n;
fp = fopen("file.txt", "r");
if(fp != NULL) {
fscanf(fp, "%d", &n);
fclose(fp);
}
sscanf 函数用于从字符串中按指定格式读取数据,这对于解析字符串中的特定数据非常有用
int sscanf(const char *str, const char *format, ...);
返回值:返回成功读取的数据项的数量。如果在读取任何数据之前遇到错误或到达字符串的结尾,则返回EOF
假设你有一个包含整数和浮点数的字符串,你想从中提取这些数值:
#include
int main() {
char *str = "100 3.14";
int i;
float f;
int result = sscanf(str, "%d %f", &i, &f);
if (result == 2) {
printf("整数:%d\n", i);
printf("浮点数:%f\n", f);
} else {
printf("格式化读取失败\n");
}
return 0;
}
在这个例子中,sscanf 会尝试从字符串 “100 3.14” 中读取一个整数和一个浮点数。如果成功,它会返回读取的项数(在这个例子中是2),并且变量 i 和 f 将分别被赋值为100和3.14。
注意事项
printf 函数
int printf(const char *format, ...);
用途:将格式化的输出发送到标准输出,通常是屏幕(控制台)。
示例:向控制台打印整数和字符串。
int num = 10;
char *arr = "Hello, world!";
printf("Number: %d, arr: %s\n", num, arr);
fprintf 函数
int fprintf(FILE *stream, const char *format, ...);
用途:将格式化的输出发送到指定的文件流中,可以是任何 FILE 类型的流,包括标准输出(stdout)和标准错误(stderr)。
示例:向文件写入格式化文本。
FILE *fp = fopen("output.txt", "w");
if (fp != NULL) {
fprintf(fp, "Number: %d\n", num);
fclose(fp);
}
sprintf 函数用于将格式化的数据写入字符串。它是标准输入输出库中的一个重要函数,特别适用于创建格式化字符串
int sprintf(char *str, const char *format, ...);
返回值:返回写入到目标字符串的字符数,不包括终结的空字符(‘\0’)。如果发生错误,则可能返回负值。
假设您想将一个整数和一个浮点数格式化为一个字符串:
#include
int main() {
int num = 25;
float pi = 3.14159;
char buffer[50];
sprintf(buffer, "%d, %f", num, pi);
printf("格式化后的字符串:%s\n", buffer);
return 0;
}
在这个例子中,sprintf 将整数 num 和浮点数 pi 按指定的格式写入字符串 buffer。之后,可以使用 printf 打印这个字符串,或者以其他方式使用它。
顺序读写数据是按照顺序一个接一个地读取或写入的,通常从文件的开始位置开始,然后逐步向后移动,直到文件结束。
而随机读写允许直接跳转到文件中的任何位置进行读取或写入。不必遵循特定的顺序,可以访问文件的任何部分
fseek 函数用于在文件中移动文件指针到指定位置,从而实现文件的随机访问
int fseek(FILE *stream, long offset, int origin);
offset:相对于 origin 参数所指定位置的偏移量,以字节为单位。
origin:起始位置,它可以是 SEEK_SET(文件开头)、==SEEK_CUR(当前位置)==或 SEEK_END(文件末尾)
先举一个例子:
int main()
{
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
在test2.txt中我们放入abcdefgh,打印结果
这里,移动文件指针按照顺序移动,那么如果我想让指针重新指向a呢?这里就得使用fseek函数:
fseek(pf,-3, SEEK_CUR);
这里从当前位置移动,-3即为向文件开头方向移动.
打印结果:
fseek(pf,0, SEEK_SET);
若现在不知道偏移量是多少,就可以使用ftell函数;
long ftell(FILE *stream);
比如上面的例子:
int main()
{
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
int n = ftell(pf);
printf("%d\n", n);
fseek(pf,0, SEEK_SET);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
这里用n来接收偏移量,打印结果:
我们也可以用这个函数来判断文件有多少个字节:
int main()
{
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fseek(pf, 0, SEEK_END);
int n = ftell(pf);
printf("%d\n", n);
fclose(pf);
pf = NULL;
return 0;
}
rewind用于将文件的位置指针重置到文件的开始位置。它的功能类似于使用 fseek 函数来将文件指针移动到文件开头,但 rewind 不返回值,因此不能用来检测错误。
void rewind(FILE *stream);
int main()
{
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
rewind(pf);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
还以这串代码为例,rewind函数调用后,移动指针指向起始位置,打印结果为a
feof 和 ferror 是用于检查文件状态的两个不同函数,它们分别用于检测文件流的结束-of-file (EOF) 状态和读写错误。
feof
int feof(FILE *stream);
feof 用于检查是否已经读取到文件的末尾。它检查与文件流关联的 EOF 标志位。
如果已经达到文件末尾,返回非零值;否则,返回 0
FILE *filePointer = fopen("file.txt", "r");
// ... 文件读取操作 ...
if (feof(filePointer)) {
// 已到达文件末尾
}
ferror
int ferror(FILE *stream)
ferror 用于检查文件流是否因为错误而无法继续读取或写入
如果文件流有错误,返回非零值;否则,返回 0
注意点
使用 fgetc 读取文件的示例:
#include
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("fopen");
return 1;
}
int c; // 注意:int 类型用于存储 EOF
// 使用 fgetc 逐字符读取文件,直到文件结束
while ((c = fgetc(file)) != EOF) {
putchar(c); // 输出字符
}
// 检查是否因为文件末尾才停止读取
if (feof(file)) {
puts("\n文件已读取完毕");
} else if (ferror(file)) {
perror("读取文件时发生错误");
}
fclose(file);
return 0;
}
使用 fread 读取文件的示例:
#include
int main() {
FILE *file;
int number;
// 打开文件用于二进制读取
file = fopen("output.txt", "rb");
if (file == NULL) {
perror("Error opening file");
return 1;
}
// 使用fread读取二进制数
size_t itemsRead = fread(&number, sizeof(int), 1, file);
if (itemsRead == 1) {
printf("读取的整数是:%d\n", number);
} else {
// 如果没有读取到一个整数,打印错误信息
if (feof(file)) {
printf("文件结束,未读取到数据。\n");
}
if (ferror(file)) {
printf("读取文件时出错。\n");
}
}
// 关闭文件
fclose(file);
return 0;
}
缓冲区在计算机科学中是一块内存区域,用于临时存放数据,目的是在数据在发送者和接收者之间传输时调节和平衡数据流。在 I/O 操作的上下文中,缓冲区的主要作用是减少对硬件设备(如硬盘、网络设备等)的直接访问次数,提高数据处理的效率和吞吐量。
标准库提供的文件操作函数(如 fread、fwrite、printf、scanf 等)通常都会使用这些缓冲区
例如,在 C 中,FILE 结构就关联了一个缓冲区。当你使用 fopen 打开一个文件时,系统会自动分配一个缓冲区,你可以使用 setvbuf 来更改其缓冲行为。当你读写数据时,例如使用 fread 或 fwrite 函数,这些数据会传递通过这个缓冲区,从而提高读写操作的效率。
在文本编辑器中,用户的输入通常存储在缓冲区内直到按下 “保存” 按钮时才写入硬盘。在网络通信中,数据包可能会首先存储在缓冲区内,然后一起发送以减少网络传输开销。在视频流媒体播放中,视频数据可以预先存储在缓冲区内,以避免播放时由于网络延迟导致的卡顿。
本章内容到此结束!感谢大家的观看!!