C语言文件读写操作实践(一)
- 在网上找到了一个英文人名字的文件,DOC格式的,复制粘贴到了一个文本文件name.data中,做为数据源来练习一下文件读写操作!!!
- 点击下载 name.data
将文件中的有用的信息过滤出来
- 系统定义的FILE类型,文件指针,自定义fpi输入,fpo输出
- 系统默认定义的文件指针,标准输入:stdin,标准输出:stdout,标准出错:stderr
- fopen 打开文件,如果返回的指针为NULL,则打开文件出错,输出出错信息!
- fopen 第二个参数是文件的打开方式,"r"表示只读!
- fclose 关闭文件,fopen/fclose两者成对出现,只要打开了,就应该关闭!!!
- fgetc 返回从文件中读取一个字符,然后指向下一个,如果读出的字符是EOF,说明到文件结尾了!!!
- fputc 向文件中写入一个字符,默认向文件尾部添加!!!
- 这个文件中有英文也有中文还有换行等其他字符,我们的目的是将英文名字过滤出来,保存到另一个文件中,其他字符忽略,不做处理。
- 循环从文件name.data读字符,判断字符是否为大小字母,如果是则将字符写入目标文件noop.txt,达到保留大小写字母的目的!
代码如下:
/* filename: fa.c */
#include <stdio.h>
#include <stdlib.h>
/* compile : gcc fa.c -o fa
run : ./fa */
/**/
int
main (int argc, char *argv[])
{
FILE *fpi, *fpo;
char c;
//打开数据文件name.data,做为输入数据源
fpi = fopen ("name.data", "r");
if (fpi == NULL)
{
fprintf (stderr, "Open file name.data error!\n");
return 0;
}
//打开新的数据文件noop.txt,做为输出数据目的
fpo = fopen ("noop.txt", "w+");
if (fpo == NULL)
{
fprintf (stderr, "Open file noop.txt error!\n");
return 0;
}
//从文件中读一个字节
c = fgetc (fpi);
while (c != EOF) //循环直到文件结束
{
//printf ("%c", c); //显示此字符
if (c >= 'A' && c <='Z') //大写字母写入目标文件,upperletter
fputc (c, fpo);
if (c >= 'a' && c <='z') //小写字母写入目标文件,lowerletter
fputc (c, fpo);
//忽略其它字符,不做任何操作,再次读取下一个字符
c = fgetc (fpi);
}
//关闭文件
fclose (fpi);
fclose (fpo);
printf ("File operate ok!\n");
return 0;
}
/* -- end -- */
编译运行,目录中出现了新创建的文件,可以用cat命令查看一下文件内容,也可以用编辑打开看一下,由大小字母组成的巨大字符串,这当然这不是目的,我们要把单词分开!!!
songvm@ubuntu:~/works/xdn/foo$ gcc fa.c -o fa
songvm@ubuntu:~/works/xdn/foo$ ./fa
File operate ok!
songvm@ubuntu:~/works/xdn/foo$ ls
fa fa.c fb.c name.data noop.txt
将noop.txt中的单词用换行符分开
- 英文人名都是以大写字母开始的,只要在大写字母前面插入一个换行符’\n’就可以了!!!
- 源文件noop.txt,目标文件name.txt
- 打开文件name.txt的方式为"w+",表示向文件中写入
代码如下:
/* filename: fb.c */
#include <stdio.h>
#include <stdlib.h>
/* compile : gcc fb.c -o fb
run : ./fb */
/**/
int
main (int argc, char *argv[])
{
FILE *fpi, *fpo;
char c;
fpi = fopen ("noop.txt", "r"); //打开noop.txt文件
if (fpi == NULL)
{
fprintf (stderr, "Open file noop.txt error!\n");
return 0;
}
fpo = fopen ("name.txt", "w+"); //输出到文件name.txt
if (fpo == NULL)
{
fprintf (stderr, "Open file name.txt error!\n");
return 0;
}
c = fgetc (fpi); //从文件中读一个字符
while (c != EOF)
{
//printf ("%c", c); //显示字符
if (c >= 'A' && c <='Z') //大写字母,upperletter
{
fputc ('\n', fpo); //在大写字母前面插入一个换行符
fputc (c, fpo);
}
if (c >= 'a' && c <='z') //小写字母,lowerletter
fputc (c, fpo);
c = fgetc (fpi);
}
//关闭文件
fclose (fpi);
fclose (fpo);
printf ("File operate ok!\n");
return 0;
}
/* -- end -- */
编译运行,查看目录,程序创建了name.txt文件,查看一下,有773行,首行是空行!!!
songvm@ubuntu:~/works/xdn/foo$ gcc fb.c -o fb
songvm@ubuntu:~/works/xdn/foo$ ./fb
File operate ok!
songvm@ubuntu:~/works/xdn/foo$ ls
fa fa.c fb fb.c name.data name.txt noop.txt
读name.txt文件,将文件内容保存到字符串数组中
- fprintf函数,属于printf函数一类,向文件输出信息!!!
- fscanf函数,属于scanf函数一类,可以从文件中读字符串,注意,不是一个字符!!!
- tmp做为fscanf函数的返回值,如果为EOF,则说明文件结束!!!
- buff字符串数组,也就是二维字符数组,初始化为0!!!
- 循环读取,每次一个名字:-)
代码如下:
/* filename: fc.c */
#include <stdio.h>
#include <stdlib.h>
/* compile : gcc fc.c -o fc
run : ./fc */
/**/
int
main (int argc, char *argv[])
{
FILE *fpi;
char buff[1024][32] = { 0 };
int tmp = 1, i = 0;
fpi = fopen ("name.txt", "r"); //打开文件
if (fpi == NULL)
{
fprintf (stderr, "Open file name.txt error!\n");
return 0;
}
//循环读取,保存到字符串数组中
while (tmp != EOF)
{
tmp = fscanf (fpi, "%s", buff[i]);
i = i + 1;
}
//循环输出,最后输出行数
for (int j = 0; j < i; j++)
fprintf (stderr, "%s\n", buff[j]);
fprintf (stderr, "count : %d\n", i);
fclose (fpi);
return 0;
}
/* -- end -- */
编译运行,发现尾行出现了一个空行,统计结果是773!!!
songvm@ubuntu:~/works/xdn/foo$ gcc fc.c -o fc
songvm@ubuntu:~/works/xdn/foo$ ./fc
Aaron
Abel
Abelard
......
Zoey
Zoe
Zora
count : 773
songvm@ubuntu:~/works/xdn/foo$
重新排序
- 这个文件是分成两部分的,前面是男性名字,后面是女性名字,混到一起重新排一下序
- 用到qsort函数,需要四个参数:字符串数组指针,字符串数量,字符串长度,比较函数
- 按qsort函数要求自定义一个比较函数namecmp,用到strcmp函数
- 字符串比较函数strcmp,在头文件string.h中定义,包含进来!!!
/* filename: fd.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* compile : gcc fc.c -o fc
run : ./fd */
/* name compare function */
int
namecmp (const void *x, const void *y)
{
return strcmp ((const char*)x, (const char*)y);
}
/**/
int
main (int argc, char *argv[])
{
FILE *fpi;
char buff[1024][32] = { 0 };
int tmp = 1, i = 0;
fpi = fopen ("name.txt", "r"); //打开文件
if (fpi == NULL)
{
fprintf (stderr, "Open file name.txt error!\n");
return 0;
}
//循环读取,保存到字符串数组中
while (tmp != EOF)
{
tmp = fscanf (fpi, "%s", buff[i]);
i = i + 1;
}
//快速排序
qsort (buff, i, sizeof(char)*32, namecmp);
//循环输出,最后输出行数
for (int j = 0; j < i; j++)
fprintf (stderr, "%s\n", buff[j]);
fprintf (stderr, "count : %d\n", i);
fclose (fpi);
return 0;
}
/* -- end -- */
编译运行,结果如下:
songvm@ubuntu:~/works/xdn/foo$ gcc fd.c -o fd
songvm@ubuntu:~/works/xdn/foo$ ./fd
Aaron
Abby
Abel
Abelard
Abigail
Abigail
Abraham
Ada
Adalheid
Adam
Adelaide
Adelaide
.......
Zoey
Zora
count : 773
songvm@ubuntu:~/works/xdn/foo$
- 依然首行空行
- 完成了排序工作!!!
- 发现了重复的名字???
下一步,查找到重复的名字,将重复的名字排除出去!!!