逗号分隔的值--CSV

来源:互联网 发布:有点牛网络公司 知乎 编辑:程序博客网 时间:2024/05/30 20:08

// 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;

}

 

 

原创粉丝点击