NeuSoft练习4(文件的各种操作)

本文介绍了一个C语言程序,该程序能够打开并读取文本文件的内容,统计文件中的行数、列数及行列名称,并实现数据的压缩处理。此外,程序还将处理后的数据输出到新的文件中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<memory.h>
#define MAX_ROW 20
#define MAX_COLUMN 10

typedef struct  nstTestTable //定义一个储存文件各种参数的结构体
{
 int ROW_COUNT;      //保存行数
 int COLUMN;        //保存列数
 char ROW_COUNR_NAME[MAX_ROW ][MAX_COLUMN];  //保存行的名字
 char COLUMN_NAME[MAX_ROW][MAX_COLUMN];      //保存列的名字
 int nuiTableData[MAX_ROW][MAX_COLUMN];      //储存数据的值
 int compress[MAX_ROW];      //记录压缩数据的标号
}STableContext;


STableContext MyTable;                    //实例化一个结构体

/****************************************************************************/
//名称:  OpenFile
//描述:    打开一个指定文件名的文件
//参数:    filename    char*
//返回值类型:  FILE*
//做成日期:    2007-6-16

/***************************************************************************/

FILE *OpenFile(char *filename)
{
 FILE *fp = 0;

 if( (fp = fopen(filename,"r")) == NULL)  //以只读的方式打开
 {
  printf("Read file error!");
  exit(0);
 }

 return fp;
}
/****************************************************************************/
//名称:  CountRow
//描述:    计算文件的行数
//参数:    temp    FILE*
//返回值类型:  void
//做成日期:    2007-6-16

/***************************************************************************/

void CountRow(FILE *temp)
{
 int i = 0;             //定义一个记录行数的变量
 char ch = 0;     //暂存从文件读取的字符

 ch = fgetc(temp);

 while( ch != EOF)
 {
  if( ch == '/n')    //没读到一个'/n'换,i自加一次
  {
   i++;
  }

  ch = fgetc(temp);
 }

 MyTable.ROW_COUNT = i;
}
/****************************************************************************/
//名称:  CountColumnName
//描述:    统计文件的列名
//参数:    temp    FILE*
//返回值类型:  void
//做成日期:    2007-6-16

/***************************************************************************/

void CountColumnName(FILE *temp)
{
 int index = 0;             //定义一个文件的下标,用来说明是第几列
 char ch = 0;

 ch = fgetc(temp);

 while( ch != '/n')
 {
  while( ch == '/t')     //如果读取的字符为tab那么就跳过它
  {
   ch = fgetc(temp);
  }

  fseek(temp, -1L,1);    //由于已经读取了tab后的下一个字符
          //所以要使文件指针退回一位
  fscanf( temp, "%s", &MyTable.COLUMN_NAME[index][0] );
          //从文件中读取字符串保存的到二维数组中

  index++;
  ch = fgetc(temp);
 }
}

/****************************************************************************/
//名称:  CountRowName
//描述:    统计文件的行名
//参数:    temp    FILE*
//返回值类型:  void
//做成日期:    2007-6-16

/***************************************************************************/

void CountRowName(FILE *temp)
{
 char ch = 0;
 int index = 0;

 ch = fgetc(temp);

 while(ch != EOF)
 {
  if(ch == '/n')  //由于每个换行符后面正好保存的是列名
      //如果遇到换行符,那么换行符后面的
      //字符串将被读入二维数组
  {
   fscanf( temp, "%s", &MyTable.ROW_COUNR_NAME[index][0] );
   index++;
  }

  ch = fgetc(temp);
 }
}

/****************************************************************************/
//名称:  CountColumn
//描述:    计算文件的列数
//参数:    temp    FILE*
//返回值类型:  void
//做成日期:    2007-6-16

/***************************************************************************/

void CountColumn(FILE *temp)
{
 int i = 0;
 char ch =0;
 ch = fgetc(temp);
 while(ch != '/n')    //指导读取到'/n'时停止
 {
  if( ch == '/t')  //列数是和tab的个数对应的,每读到一个tab,i自增
  {
   i++;
  }
  ch = fgetc(temp);
 }
 MyTable.COLUMN = i;
}

/************************************************************************************/
//名称:  CompressRowData
//描述:    压缩输出数据
//参数:    void
//返回值类型:  void
//做成日期:    2007-6-16

/************************************************************************************/

void CompressRowData()
{
 int comparedata[10];          //定义一个用于比较的缓存数组
 int i = 0, j = 0, k = 0, m = 0;
 for(m = 0; m < MyTable.ROW_COUNT; m++)  //依次把二维数组MyTable.nuiTableData[][]
 {          //中的内容复制到缓存数组中
  for(j = 0; j < MyTable.COLUMN; j++)
  {
   comparedata[j] = MyTable.nuiTableData[m][j];
  }
  for(i = m + 1; i < MyTable.ROW_COUNT; i++)//将缓存数组中的内容依次与
  {            //原二维数组中的内容进行比较
   k = 0;
   while(k < MyTable.COLUMN)
   { 
   
    if(comparedata[k] == MyTable.nuiTableData[i][k])//如果相等下标k自增
    {
     k++;
    }
    else                      //否则退出循环体
     break;
   
   }
   if(k >= MyTable.COLUMN)       //如果完全相等
   {
    MyTable.compress[i] = m;  //进行记录第i行与第m行相等
   }
  
  }
 }
}
/****************************************************************************/
//名称:  WriteData
//描述:    向一个指定的文件中写入数据
//参数:    temp    char*
//返回值类型:  void
//做成日期:    2007-6-16

/***************************************************************************/
void WriteData(char *temp)
{
 FILE *fp = 0;
 int i = 0;
 int j = 0;
 int m = 0;
 int n = 0;
 int find = 0;
 int row_number = 0;

 if( (fp = fopen(temp,"w")) == NULL)
 {
  printf("Read file error!");
  exit(0);
 }
 
 CompressRowData();  //调用压缩函数

 while(MyTable.ROW_COUNR_NAME[i][0] != 0) //如果二维数组里面的值不空
 {
 
   fprintf(fp, "#define ROW_%s", MyTable.ROW_COUNR_NAME[i]);//那么向文件里面输出字符串
                        //也就是行的名字
  if(MyTable.compress[i] == -1)
  {
   fprintf(fp, "    %d/n", row_number);//输出行号
   row_number++;//行号自加
  }
  else
  {
   find = MyTable.compress[i];
   fprintf(fp, "    ROW_%s/n", MyTable.ROW_COUNR_NAME[find]);
  }

  i++;
 }

 fprintf(fp, "define ROW_COUNT   %d/n/n", row_number); //输出总共的行数

 while(MyTable.COLUMN_NAME[j][0] != 0)
 {
  fprintf(fp, "#define COLUMN_%s", MyTable.COLUMN_NAME[j]);//向文件输出列名
  fprintf(fp, "    %d/n", j);
  j++;
 }

 fprintf(fp, "define COLUMN_COUNT   %d/n", j);//向文件输出总共的列数
 fprintf(fp, "/nstatic int nuiTableData_a[][COLUMN_COUNT] = {/n");

 for(m = 0; m < MyTable.ROW_COUNT; m++ )//向文件打印数据的值
 {
  for(n = 0; n < MyTable.COLUMN; n++)
  {
   fprintf(fp, "%d, ", MyTable.nuiTableData[m][n]);
  }

  fprintf(fp,"/n");
 }
 fprintf(fp, "}");
}

/****************************************************************************/
//名称:  ReadData
//描述:    从文件中读取数据到结构体中保存数据值的二维数组
//参数:    temp    FILE*
//返回值类型:  void
//做成日期:    2007-6-17

/***************************************************************************/
void ReadData(FILE *temp)
{
 char ch = 0;
 int i = 0;
 int j = 0;

 ch = fgetc(temp);
 while(ch != '/n')        //跳跃过第一行的列名
 {
  ch = fgetc(temp);
 }

 while(ch != EOF)        
 {
  if(ch < 58 && ch > 47)//如果asic码值为0~9之间的数
  {
   MyTable.nuiTableData[i][j] = ch - '0';//减去'0'的asic码值保存到二维数组
   j++;
  }

  ch =fgetc(temp);

  if(ch == '/n')//如果遇到'/n',那么行下标自增
  {
   j = 0;
   i++;
  }
 }
 

}


int  main()
{
 char readfile[10] = "file.txt";     //定义打开的文件
 char writefile[15] = "newfile.txt"; //定义写入的文件
 
 FILE *fp = OpenFile(readfile);      //调用OpenFile函数打开文件
 memset(MyTable.compress, -1, MAX_ROW*4);
 CountRow(fp);                       //计算行数
 fseek(fp, 0, 0);                    //文件指针归位

 CountColumn(fp);                    //计算列数
 fseek(fp, 0, 0);

 CountColumnName(fp);                //统计列名
 fseek(fp, 0, 0);

 CountRowName(fp);                   //统计行名
 fseek(fp, 0, 0);
 
 ReadData(fp);                       //读取数据
 printf("%d  %d", MyTable.ROW_COUNT,MyTable.COLUMN);
 WriteData(writefile);               //向文件中写入各种数据
 
 
}

 

已知前提条件有: 1. 内容是一个0到65535的数值. 2. 对应的二维表有很多个, 而且每个表的ROW COUNT和COLUMN COUNT都不固定. 3. 原始表格数据文件格式 a. 原始文件是文本格式, 文本行与上表相对应. b. 每行由多个单词构成,单词之间由空格及制表符(TAB)的组合来分割. c. 第一行的单词用于定义COLUMN VALUE的命名 d. 从第二行开始, 每文本行对应二维表的一行. 第一个单词定义ROW VALUE的命名.从第二个单词开始, 每个单词均由数字构成, 描述二维表的内容. e. 空文本行表示二维表格结束. 根据上面的表格, 下面是原始数据: AAA BBB CCC DDD AAA 0 1 1 4 BBB 2 2 5 3 CCC 8 7 6 6 DDD 9 9 9 9 4. 输出格式要求: 生成C语言格式的描述. 包含ROW VALUE定义, COLUMN VALUE定义及二维表数据结构.(根据上面的表格, 下面是个生成的例子) #define ROW_AAA 0 #define ROW_BBB 1 #define ROW_CCC 2 #define ROW_DDD 3 #define ROW_COUNT 4 #define COLUMN_AAA 0 #define COLUMN_BBB 1 #define COLUMN_CCC 2 #define COLUMN_DDD 3 #define COLUMN_COUNT 4 static <type> nuiTableData_a[][COLUMN_COUNT] = { 0, 1, 1, 4, 2, 2, 5, 3, 8, 7, 6, 6, 9, 9, 9, 9 }; 5. 原始表格数据一定是正确的, 不必考虑对原始数据的严格分析判断 6. 根据原始数据得出ROW COUNT和COLUMN COUNT 7. COLUMN VALUE从0开始, 依次递增. 8. ROW VALUE的定义和COLUMN VALUE定义类似, 但需要进行压缩判断.如果两列内容相同, ROW VALUE值也应该一样. 例如原始数据: … PPP 0 0 1 1 2 RRR 1 2 2 1 5 QQQ 0 1 2 3 4 SSS 1 2 2 1 5 TTT 9 9 8 8 7 … 那么生成的结果应是: … #define ROW_PPP 10 #define ROW_RRR 11 #define ROW_QQQ 12 #define ROW_SSS ROW_RRR #define ROW_TTT 13 … 题目: 编写一个程序。 读取一个文本表格文件, 并生成另一种格式的文件(C语言格式的H文件), 同时将表格的行列索引(AAA, BBB, CCC…,即ROW VALUE, COLUMN VALUE)以C语言的格式进行定义.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值