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

来源:互联网 发布:矩阵论第三版课后答案 编辑:程序博客网 时间:2024/05/17 01:34

#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);               //向文件中写入各种数据
 
 
}