文章目录
1、sscanf与sprintf
1.1sprintf
sprintf是一个将格式化数据写入字符串的函数。
如下,sprintf第一个参数是待写入的字符串,后面两个参数和printf一样。整个函数就是把格式化的数据全部转换成字符串放入str中。
int sprintf ( char * str, const char * format, ... );
如下代码和运行结果,原本结构体中char、int、float类型的数据全部转换成了字符串放到buf里面。
#include<stdio.h>
struct info
{
char name[20];
int age;
float score;
};
int main()
{
struct info a= { "zhangsan",30,95.5f };
char buf[100] = { 0 };
//把格式化数据转换成字符串,输出到字符数组里面。
sprintf(buf, "%s %d %f", a.name, a.age, a.score);
printf(buf);
return 0;
}
1.2sscanf
sscanf是一个从字符串中读取格式化数据的函数。
其作用是:从 s 读取数据并根据参数格式将它们存储到附加参数给定的位置,就像使用了 scanf 一样,但从 s 而不是标准输入 (stdin) 读取数据。
int sscanf ( const char * s, const char * format, ...);
知道了sprintf的功能,sscanf运行结果业不难猜测,它就是把字符串中的数据,按要求转化成各种格式的数据存到对应的内存中。如下代码和运行结果,第一行运行结果是以字符串的格式输出到屏幕的,第二行是%s %d %.2f 格式输出到屏幕的。
#include<stdio.h>
struct info
{
char name[20];
int age;
float score;
};
int main()
{
struct info a= { "zhangsan",30,95.5f };
char buf[100] = { 0 };
//把格式化数据转换成字符串,输出到字符数组里面。
sprintf(buf, "%s %d %f", a.name, a.age, a.score);
printf(buf);
//从buf中按照格式输入到内存里面
sscanf(buf, "%s %d %f", a.name, &(a.age), &(a.score));
printf("\n%s %d %f", a.name, a.age, a.score);
return 0;
}
2、scanf、fscanf、sscanf区别
scanf 按照一定的格式从键盘输入数据
printf 按照一定的格式把数据打印到屏幕
适用于标准输入、输出流的格式化输入、输出语句
fscanf 按照一定格式从输入流(文件/stdin)输入数据
fprintf 按照一定格式把数据向输出流(文件/stdout)输出数据
适用于所有输入、输出流的格式化输入、输出语句sscanf 从字符串中按照一定的格式读取数据
sprintf 把格式化的数据按照一定的格式转换成字符串
3、文件的随机读取
在使用文件的顺序读取的时候,时常会发出疑问:能不能跳着读取数据呢?能不能读了这个数据,再重新读取一次该数据呢?能不能读数据到一半,再从头开始读数据呢?而对文件操作熟悉的同学,都明白这一切都要依靠文件指针的位置。文件指针在何处,就读取何处的数据。 所以,文件的随机读取,本质上就是移动文件指针。
在这里介绍一下C语言自带的几个常量:
SEEK_SET 返回 文件开头的位置
SEEK_CUR 返回 文件指针当前指向的位置
SEEK_END 返回 文件末尾的位置
3.1 fseek()函数
该函数又被称为 重新定位流位置指示器 ,其作用就是重新定位文件指针的位置,实现文件的随机读取。
int fseek ( FILE * stream, long int offset, int origin );
第一个参数是文件流
第二个参数是偏移量
第三个参数是偏移的起始位置
作用后文件指针指向某个位置(该位置是从偏移的起始位置 origin 开始,偏移了offset个位置之后 的位置)
如下,只读方式打开"test.txt"文件,该文件里面的内容是“abcdefg”,一开始用fgetc读了一个字符,然后文件指针指向b的位置。
第二步用fseek函数,将文件指针移到当前位置向后偏移1位的位置,指向 'c' 然后读取一个字符,读出的应该是“c”,打印出来正确。
第三步是用fseek函数,将文件指针移到文件开头位置向后偏移3位的位置,指向 ‘d’ 然后读取一个字符,读出来应该是'd' ,打印出来正确。
第四步是用fseek函数,将文件指针移到文件末尾位置向前偏移三位的位置,指向‘e’ ,读出来应该是‘e’ ,打印出来正确。
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen()");
return 1;
}
int ch = fgetc(pf);//现在当前文件在第二个字符的位置
printf("%c\n", ch);
fseek(pf, 1, SEEK_CUR);//文件指针在文件的当前位置,偏移1个字符
ch = getc(pf);
printf("%c\n", ch);
fseek(pf, 3, SEEK_SET);
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, -3, SEEK_END);//从最后往前偏移3个字符读取数据
ch = fgetc(pf);
printf("%c\n", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
3.2 ftell() 、rewind() 函数
ftell()函数可以获取流中的当前位置。即返回文件指针的当前指向的位置。其只有一个参数,是文件指针。
long int ftell ( FILE * stream );
rewind()函数可以将流的位置设置为开头。即可以将文件指针指向文件开头。其参数是一个文件指针,调用这个函数后,该指针指向文件初始位置。
void rewind ( FILE * stream );
如下代码和运行结果,打开一个"test.txt" 文件,其内容是 "abcdefg",首先用fseek函数把文件指针位置从最后往前移三位,即移到了"e"的前面。此时从文件起始位置看过去,该文件指针位置是4(起始位置是0)。ftell读取当前位置,符合预期。然后用rewind,再读取字符,也符合rewind将文件指针指向开头的功能。
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen()");
return 1;
}
fseek(pf, -3, SEEK_END);//从最后往前偏移3个字符读取数据
//返回当前文件指针指向的位置
int pos = ftell(pf);
printf("%d\n", pos);
rewind(pf);//文件指针返回初始位置
int ch = getc(pf);
printf("%c\n", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
4.被错用的feof
4.1feof的功能
feof 是一个检查文件结尾指示器。其参数是一个文件指针,且要指向文件末尾()。
int feof ( FILE * stream );
文件读取的过程中,我们常用 feof 来判断文件的读取是否结束。但实际上,这是错误的用法,feof 真正的用法是——当文件读取结束时,来判断:是读取失败而结束,还是读取到文件末尾结束 。feof 的功能,官方说明是:检查是否设置了与流关联的文件尾指示器,如果是,则返回与零不同的值。 翻译一下,就是:feof返回非0,那么是读到文件末尾结束。 如果返回0,那么就是读取失败而结束。
那么如何将文件指针指向文件末尾呢?可以使用fseek函数,也可以使用fgetc,直到读完文件,就到了末尾位置。
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (!pf)
{
perror("fopen()");
return 1;
}
int ch;
while (ch = fgetc(pf) != EOF)
{
putchar(ch);
}
//判断是什么原因结束的
if (ferror(pf))
{
printf("I/O error in reading!\n");
}
else if (feof(pf))//正常结束返回非0
{
printf("End of file reach successfully!\n");
}
fclose(pf);
pf = NULL;
return 0;
}
4.2 判断文件是否结束的方法
文件是否结束,主要也和文件指针关联。
比如,一个文件里的内容是“abcdefghijk”
那么使用 | 代表文件指针
“ab | cdefghijk”
“abcde | fghijk”
“abcdefghij | k”
“abcdefghijk | ”
对于上面各种情况,无疑只有最后一种情况是文件结束的,那么此时用该如何来判定呢?仔细想一下,我们使用过的文件顺序读取函数(随机读取在这里使用无意义),不可以是输出函数,因为这类函数会向文件写入内容。所以只能使用输入函数,读取文件的内容,比如 fgetc,fgets,fscanf 等等。
那么,用这些函数,就要知道,在 文件指针指向文件末尾 和 文件指针不指向文件末尾 的情况下,其返回值的区别。
文本文件判断结束:
fgetc如果读取正常, 返回该字符的ASCLL码值,读取失败,返回EOF。
fgets读取正常,返回存放数据的空间的起始地址,否则返回NULL。
fscanf读取正常,返回的是格式串指定的数据的个数,读取失败,返回的是小于格式串中指定的数据个数。二进制文件判断结束:
fread,正常,返回的是实际读取数据个数,否则返回小于设定的读取数据个数。
根据这些返回值,用 if 语句判断即可,这里不多赘述啦!!!