编程会经常和文件打交道,今天来介绍一下怎样实现用C读取“A X Y Z”类型(中间有几个空格都不要紧,"," 也可以)的文件:
1.首先定义一个结构体:
typedef struct {
double x,y,z; //点的坐标
char name[10]; //点的名字
}Point; //点类型
2.由于C里面没有现成的字符数组转 double 的函数,所以再写一个小函数:
double S2D(char *st)
{
int i=1,count=1;//i是状态参量,小数点前i=1,小数点后i=0,count是小数后位数计数器
int j=0,t=0; //j是状态参量,j=1表示有'-',j=0表示无'-',t来记录字符数组的历程
double f=0;
while(st[t]>='-'&st[t]<='9')
{
if (st[t]=='-') j=1;//是负数
else if (st[t]=='.') i=0;//小数时代打开
else if(i==0)
{f=f+((int)st[t]-48)*pow(0.1,count); count++;}
else f=f*10+((int)st[t]-48);//(int)'1'=49
t++;
}
if(j==1) return f*(-1);
else return f;
}
3.接着传入文件地址,传出一个点数组:
Point* Read(FILE *fp)
{
Point P[n];//n是一个宏,即点数组的最大容量
char ch;
ch=getc(fp);
char st[20]="";
int t=0;//t用来记录读到第几个点
while(ch!=EOF)//文件结束标记
{
Point pt;strcpy(pt.name,"");pt.x=pt.y=pt.z=0;//先赋值
int i=0,count=1,g=1;//i记录字符数组历程,count记录读到第几个数,g是状态参量
while(ch!='\n'&&ch!=EOF)
{
if(ch>='-'&&ch<='z') { st[i]=ch; i++; }
ch=getc(fp);
if(g==1&&(ch<'-'||ch>'z'))
{
g=0;
if(count==1)
{strcpy(pt.name,st);count++;i=0;memset(st, 0, sizeof(st));continue;}
if(count==2)
{pt.x=S2D(st);count++;i=0;memset(st, 0, sizeof(st));continue;}
if(count==3)
{pt.y=S2D(st);count++;i=0;memset(st, 0, sizeof(st));continue;}
if(count==4)
{pt.z=S2D(st);count++;i=0;memset(st, 0, sizeof(st));continue;}
}
else if(!(ch<'-'||ch>'z')) g=1;
}
P[t]=pt;
printf("%d,%s,%lf,%lf,%lf\n",t,P[t].name,P[t].x,P[t].y,P[t].z);
t++;ch=getc(fp);
}
return P;
}
4.要包含的头文件:
#include <cstdio>
#include <cstdlib>
#include <cstring>//把一个字符数组赋给另一个字符数组用到
#include <memory.h>//把字符数组置空用到
#include <cmath>//计算字符数组转double用到
5.实例main函数:
int main()
{
FILE *fp;
fp=fopen("D:\\MY WORK\\C#\\MY APP\\实验数据\\坐标转换\\7_目标坐标.txt","r");
Point *P=Read(fp);
fclose(fp);
system("pause");
}
结果:
用C#读此类型的文件可参考我另一篇博客
最后对两个语言读文件的异同做个总结:
1.C 语言定义一个结构体比 C# 定义一个点类要简单一些,C 语言不需要 C# 的什么 get,set 等之类的方法,想改变结构体中变量的值可以随便改。其实到 C++ 中结构体就相当于类了。
2.C# 中有专门的函数可以直接把字符串变为 double ,C 中没有,并且是以字符数组的形式来存储的,就造成把字符数组置空用到 memory.h 文件下的 memset(st, 0, sizeof(st)); 函数。
3.C# 可以直接读一行:string str = sR.ReadLine(); C这里是一个字符一个字符的读的:ch=getc(fp);
4.策略都是相同的,都是先读一行,在储存到点类型中,接着循环。
5.可能是我最先学的是 C 语言,所以 C 语言读文件看着顺眼,用的也多一些(笑哭)但是 C #在读文件方面确实更简单,就是定义点类的时候很麻烦。