【C语言文件读写操作实践(一)】

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$ 
  • 依然首行空行
  • 完成了排序工作!!!
  • 发现了重复的名字???

下一步,查找到重复的名字,将重复的名字排除出去!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值