// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__040A9D5A_3A66_49CD_81D7_BB7E62C98798__INCLUDED_)
#define AFX_STDAFX_H__040A9D5A_3A66_49CD_81D7_BB7E62C98798__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
char *csvgetline(FILE *fin);
char *csvfield(int n);
int csvnfield(void);
enum{ NOMEM=-2};
static char *line =NULL;
static char *sline=NULL;
static int maxline=0;
static char **field =NULL;
static int maxfield=0;
static int nfield=0;
static char fieldsep[]=",";
// TODO: reference additional headers your program requires here
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__040A9D5A_3A66_49CD_81D7_BB7E62C98798__INCLUDED_)
// interface.cpp : Defines the entry point for the console application.
//
// try.cpp : Defines the entry point for the console application.
//
#include"StdAfx.h"
static void reset(void) //重置所有变量
{
free(line);
free(sline);
line=NULL;
sline=NULL;
field=NULL;
maxline=maxfield=nfield=0;
}
static int endofline(FILE *fin,int c) //处理输入行的各种可能出现的状况
{
int eol;
eol=(c=='/r'||c=='/n');
if(c=='/r')
{
c=getc(fin);
if(c!='/n'&&c!=EOF)
ungetc(c,fin);//用于向输入流写回指定字符,c不是结束符,将c重新写入输入流
}
return eol;
}
static char *advquoted(char *p)//处理不规范的输入,若两个分隔符“,”之间出现了“"”,那么将把这个引号当做该域中的数据;"...."中的“,”不作为分隔符
{
int i,j;
for(i=j=0;p[j]!='/0';i++,j++)
{
if(p[j]=='"'&&p[++j]!='"')
{
int k=strcspn(p+j,fieldsep);//以str1为参照,比较字符串str2中的字符是否与str中某个字符相等(也就是检索str2中的字符是否在str1中存在),如果第一次发现相等,则停止并返回在str1中这个匹配相等的字符的索引值,失败则返回str1的长度
memmove(p+i,p+j,k);
i+=k;
j+=k;
break;
}
p[i]=p[j];
}
p[i]='/0';
return p+j;
}
static int split(void)//切分输入行,划分数据域,划分后保存在field中,但只返回nfield的值
{
char *p,**newf;
char *sepp;
int sepc;
nfield=0;
if(line[0]=='/0')
return 0;
strcpy(sline,line);
p=sline;
do{
if(nfield>=maxfield)//扩大field空间
{
maxfield*=2;
newf=(char**)realloc(field,maxfield*sizeof(field[0]));
if(newf==NULL)
return NOMEM;
field=newf;
}
if(*p=='"')
sepp=advquoted(++p);//若出现“"”,则需要处理数据的格式,要只保留引号内的数据
else
sepp=p+strcspn(p,fieldsep);//无引号,直接划分
sepc=sepp[0];//此时sepc为逗号或者"/0"
sepp[0]='/0';
field[nfield++]=p;//增加数据域
p=sepp+1;//指针继续向后
}while(sepc==',');
return nfield;
}
char *csvgetline(FILE *fin)//读入所有数据,直接存入line中,在进行数据域的划分
{
void reset(void);
int i,c;
char *newl,*news;
if(line==NULL)
{
maxline=maxfield=1;
line=(char*)malloc(maxline);
sline=(char*)malloc(maxline);
field=(char **)malloc(maxfield*sizeof(field[0]));
if(line==NULL||sline==NULL||field==NULL){
reset();
return NULL;
}
}
for(i=0;(c=getc(fin))!=EOF&&!endofline(fin,c);i++)
{
if(i>=maxline-1){
maxline*=2;
newl=(char *)realloc(line,maxline);
news=(char *)realloc(sline,maxline);
if(newl==NULL||news==NULL){
reset();
return NULL;
}
line=newl;
sline=news;
}
line[i]=c;
}
line[i]='/0';
if(split()==NOMEM){
reset();
return NULL;
}
return(c==EOF&&i==0)? NULL:line;
}
char *csvfield(int n)
{
if(n<0||n>=nfield)
return NULL;
return field[n];
}
int csvnfield(void)
{
return nfield;
}
int main(void)
{
int i;
char *line;
FILE *fp;
fp=fopen("data.txt","r");
while((line=csvgetline(fp))!=NULL)
{
printf("line='%s'/n",line);
for(i=0;i<csvnfield();i++)
printf("field[%d]='%s'/n",i,csvfield(i));
}
return 0;
}