想实现csv文件里指定列的删除和位置互换。用c#实现。求code
手段方法太多,但是我不打算介绍那些古早的玩意
2022年了,新程序员应该具有更开放的思路和眼光,如果不拘泥net的传统手段,我们会发现更多的已经是其他语言的普适手段(传统net们太独,非ms不用,并不利于综合开发团队,这也是人家排斥net的原因,人家用的你不用,你用的人家没办法上手,所以自己把自己孤立了)
比如基于dataframe观点的东西:
Pandas:https://github.com/SciSharp/Pandas.NET
Deedle:Deedle:https://fslab.org/Deedle/
这些是第3方的,官方也给了一个东西不过暂时没有人家强悍( 相关资料Microsoft.Data.Analysis https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.data.analysis.dataframe?view=ml-dotnet-preview
代码我不给了,dataframe的手段基本是一样的,Pandas的资料成千上万,找个Pandas的资料自己对照着用就好(这样搞一遍,至少你再跟python的人沟通,大家就可以在一个频道上了)
仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <locale.h>
#include <windows.h>
#define MAXF 256 //每行最多列数
#define MAXC 2048 //每列最多字符数+1
#define MAXW 16000 //每行最多字符数
static int maxw[MAXF];//扫描一遍得出的每列最大宽度
int maxf[MAXF];//扫描一遍得出的每列属性:-1字符串(左对齐)|0纯数字(右对齐)|>0带小数点数字的最多小数位数(按小数点对齐)
double fsum[MAXF];
double val;
static char fout[MAXF];
int fgrp;
char d[MAXF][MAXC];
char e[MAXF][MAXC];
char ln[MAXW];
static int s,i,j,n,L,k,cn,pc,w,rn,nn,cl,lcl,r,wed,dt,f,o1,fc;
char c,*p,*pp;
FILE *fi,*fo;
char delims[256];
int delimsL;
char ag;
char t;
int agdelims2gap(int col,char c) {
if (col==-1) return ',';
if ('a'==ag) {
if (strchr(delims,c)) return 1;
else return 0;
} else {//'g'==ag
if (col>=delimsL) col=delimsL-1;//后面各列使用指定列间隔字符列表中最后的那个字符
if (c==0) return delims[col];//c为0时返回col列后面在指定列间隔字符列表中对应的间隔字符
if (delims[col]==c) return 1;
else return 0;
}
}
char *strlrtrim_c2c(char *s) {//将s两头的' '或'\t'去掉,并将其中的delims字符','或指定列间隔字符集合中的字符替换为';'
char *s1;
while (1) {
if (*s==' '||*s=='\t') s++;
else break;//
}
s1=s;
while (1) {
if (*s==0) break;//
if ('a'==ag) {
if (strchr(delims,*s)) {*s=';';rn++;} //指定列间隔字符集合时,将集合中的字符替换为';'
} else {//'g'==ag
if (','==*s) {*s=';';rn++;} //指定列间隔字符列表时,仅将','替换为';'
}
s++;
}
while (1) {
if (s1==s) break;
s--;
if (!(*s==' '||*s=='\t')) {
*(s+1)=0;
break;//
}
}
return s1;
}
int strflg(char *ss) {//-1字符串(左对齐)|0纯数字(右对齐)|>0带小数点数字的最多小数位数(按小数点对齐)
int isd;
isd=-1;
if (*ss=='-') ss++;//负数
while (1) {
if (*ss==0) break;//
if (*ss=='.') {
isd=1;
} else if ('0'<=*ss && *ss<='9') {
if (isd<1) isd=0;
else isd++;
} else if (('e'==*ss || 'E'==*ss) && (('0'<=ss[1] && ss[1]<='9') || '-'==ss[1] || '+'==ss[1])) {
if (isd<1) isd=0;
else isd++;
ss++;
} else {
isd=-1;
break;
}
ss++;
}
return isd;
}
void outf(int cc,char o[MAXF][MAXC]) {//-1字符串(左对齐)|0纯数字(右对齐)|>0带小数点数字的最多小数位数(按小数点对齐)
if (o1) {
o1=0;
p=strlrtrim_c2c(o[cc]);
if (-1==maxf[cc])
fprintf(fo,"%-*s",maxw[cc],p);
else if (0==maxf[cc])
fprintf(fo,"%*s",maxw[cc],p);
else {
if (0==L) {
if (-1==strflg(p))
fprintf(fo,"%-*s",maxw[cc]+maxf[cc],p);
else
fprintf(fo,"%*s%s%*s",maxw[cc]-(strchr(p,'.')?strchr(p,'.')-p:strlen(p)),"",p,maxf[cc]-strflg(p),"");
} else {
fprintf(fo,"%*s%s%*s",maxw[cc]-(strchr(p,'.')?strchr(p,'.')-p:strlen(p)),"",p,maxf[cc]-strflg(p),"");
}
}
} else {
c=',';
if ('g'==ag) c=agdelims2gap(cc-1,0);
p=strlrtrim_c2c(o[cc]);
if (-1==maxf[cc])
fprintf(fo,"%c%-*s",c,maxw[cc],p);
else if (0==maxf[cc])
fprintf(fo,"%c%*s",c,maxw[cc],p);
else {
if (0==L) {
if (-1==strflg(p))
fprintf(fo,"%c%-*s",c,maxw[cc]+maxf[cc],p);
else
fprintf(fo,"%c%*s%s%*s",c,maxw[cc]-(strchr(p,'.')?strchr(p,'.')-p:strlen(p)),"",p,maxf[cc]-strflg(p),"");
} else {
fprintf(fo,"%c%*s%s%*s",c,maxw[cc]-(strchr(p,'.')?strchr(p,'.')-p:strlen(p)),"",p,maxf[cc]-strflg(p),"");
}
}
}
}
int main(int argc,char **argv) {
setlocale(LC_ALL,"chs");
if (argc>=2 && 0==strcmp(argv[1],"/?")) goto USAGE;
strcpy(delims,",");
if (argc>=2) {
t=0;
ag=argv[1][0];
if ('t'!=ag && 'a'!=ag && 'g'!=ag) goto USAGE;
if ('t'==ag) {
t='t';
ag=argv[1][1];
if ('a'!=ag && 'g'!=ag) goto USAGE;
strcpy(delims,argv[1]+2);
} else {
strcpy(delims,argv[1]+1);
}
if (0==delims[0]) strcpy(delims,",");
}
delimsL=strlen(delims);
fi=fopen("in.csv","r");
if (NULL==fi) {
fprintf(stderr,"无法打开文件in.csv!\n");
USAGE:
fprintf(stderr,"用法:%s [[t]a|[t]g[delims] [1,3-5,1,100-99] [4,1-3]]\n将in.csv中各列两端的空白去掉,双引号中的','或指定列间隔字符替换为';'[且[t列出各列序号和标题|a指定列间隔字符集合各列对齐|g指定列间隔字符列表各列对齐] [输出第1,3-5,1,100-99列] [异或按第4列分组后对1-3列组内求和]]\n",argv[0]);
return 1;
}
fgrp=-2;
for (i=0;i<MAXF;i++) maxf[i]=-1;
fo=fopen("out.csv","w");
if (NULL==fo) {
fclose(fi);
fprintf(stderr,"无法创建文件out.csv!\n");
return 1;
}
pc=0;
AGAIN:
rn=0;
rewind(fi);
L=0;
while (1) {
if (NULL==fgets(ln,MAXW,fi)) break;//
if ('\n'!=ln[strlen(ln)-1]) {
fprintf(stderr,"in.csv中第%d行太长(>%d个字符)!",L+1,MAXW);
fclose(fo);
fclose(fi);
return 1;
}
ln[strlen(ln)-1]=0;
s=0;
i=0;
n=0;
p=ln;
while (1) {
c=ln[i];
switch (s) {
case 0://开始
if (c==0) goto SHOW;
if (c=='\"') {
s=1;
p=ln+i;
} else if (agdelims2gap(n,c)) {
k=__min((ln+i)-p,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
if (n>=MAXF) {
fprintf(stderr,"警告:in.csv中第%d行多于%d的字段被忽略。\n",L+1,MAXF);
goto SHOW;
}
p=ln+i+1;
s=3;
} else if (c==' ' || c=='\t') {
p=ln+i+1;
} else {
s=2;
p=ln+i;
}
break;
case 1://双引号中
if (c==0) {
fprintf(stderr,"in.csv中第%d行第%d个字符处格式错误!期望双引号。\n",L+1,i);
fclose(fo);
fclose(fi);
return 1;
}
if (c=='\"' && (agdelims2gap(n,ln[i+1]) || ln[i+1]==0 || ln[i+1]==' ' || ln[i+1]=='\t')) {
k=__min((ln+i)-p+1,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
if (n>=MAXF) {
fprintf(stderr,"警告:in.csv中第%d行多于%d的字段被忽略。\n",L+1,MAXF);
goto SHOW;
}
if (ln[i+1]==0) goto SHOW;
if (agdelims2gap(n,ln[i+1])) {
i++;
p=ln+i+1;
s=3;
} else {//' '或'\t'
s=4;
}
} else if (c=='\"' && ln[i+1]=='\"') {//连续两个双引号代表一个双引号
i++;
}
break;
case 2://非双引号中
if (c==0) {
k=__min((ln+i)-p,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
goto SHOW;
}
if (c=='\"') {
fprintf(stderr,"in.csv中第%d行第%d个字符处格式错误!此处不应出现双引号。\n",L+1,i);
fclose(fo);
fclose(fi);
return 1;
}
if (agdelims2gap(n,c)) {
k=__min((ln+i)-p,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
if (n>=MAXF) {
fprintf(stderr,"警告:in.csv中第%d行多于%d的字段被忽略。\n",L+1,MAXF);
goto SHOW;
}
p=ln+i+1;
s=3;
}
break;
case 3://逗号后
if (c==0) {
k=__min((ln+i)-p,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
goto SHOW;
}
if (c=='\"') {
s=1;
p=ln+i;
} else if (agdelims2gap(n,c)) {
k=__min((ln+i)-p,MAXC-1);strncpy(d[n],p,k);d[n][k]=0;
n++;
if (n>=MAXF) {
fprintf(stderr,"警告:in.csv中第%d行多于%d的字段被忽略。\n",L+1,MAXF);
goto SHOW;
}
p=ln+i+1;
} else {
s=2;
p=ln+i;
}
break;
case 4://双引号后连续的' '或'\t'
if (c==0) goto SHOW;
if (agdelims2gap(n,c)) {
p=ln+i+1;
s=0;
} else if (c!=' ' && c!='\t') {
fprintf(stderr,"in.csv中第%d行第%d个字符处格式错误!期望逗号。\n",L+1,i);
fclose(fo);
fclose(fi);
return 1;
}
break;
}
i++;
}
SHOW:
if (0==L) cn=n;
else if (cn!=n) if (!kbhit()) {fprintf(stderr,"警告:in.csv中第%d行数据列数%d不等于第1行数据列数%d!\n",L+1,n,cn);Sleep(500);}
// printf("第%d行%d列:",L+1,n);
if (argc==4 && pc && fgrp==-2) {
fgrp=-1;
for (i=0;i<MAXF;i++) fsum[i]=0.0;
s=0;
o1=1;
fc=0;
pp=argv[3];//4,1-3
wed=0;
while (1) {
r=sscanf(pp,"%d%n",&cl,&nn);
if (1==r) {
if (1<=cl) {
if (!fc) {
fc=1;
fgrp=cl-1;
} else {
if (cl<=n) fout[cl-1]=1;
lcl=cl;
s=1;
}
} else if (cl<=-1 && 1==s) {
cl=-cl;
if (lcl<cl) {
for (i=lcl+1;i<=cl;i++) {
if (i<=n) fout[i-1]=1;
}
} else if (lcl>cl) {
for (i=lcl-1;i>=cl;i--) {
if (i<=n) fout[i-1]=1;
}
}
s=0;
} else {
if (!wed) {
fprintf(stderr,"警告:指定分组求和的某些列不存在!\n");
wed=1;
}
}
pp+=nn;
} else if (0==r) {
s=0;pp++;
} else break;//
}
}
if (argc==3 && pc && fgrp==-2) {
s=0;
o1=1;
pp=argv[2];//1,3-5,1,100-99
wed=0;
while (1) {
r=sscanf(pp,"%d%n",&cl,&nn);
if (1==r) {
if (1<=cl) {
if (cl<=n) outf(cl-1,d);
lcl=cl;
s=1;
} else if (cl<=-1 && 1==s) {
cl=-cl;
if (lcl<cl) {
for (i=lcl+1;i<=cl;i++) {
if (i<=n) outf(i-1,d);
}
} else if (lcl>cl) {
for (i=lcl-1;i>=cl;i--) {
if (i<=n) outf(i-1,d);
}
}
s=0;
} else {
if (!wed) {
fprintf(stderr,"警告:指定输出的某些列不存在!\n");
wed=1;
}
}
pp+=nn;
} else if (0==r) {
s=0;pp++;
} else break;//
}
fprintf(fo,"\n");
L++;
continue;
}
if (argc>=2) {
if (0==pc) {//第1遍仅获取各列格式和最大宽度
for (i=0;i<n;i++) {
p=strlrtrim_c2c(d[i]);
f=strflg(p);
if (L<=1) {
if (f>maxf[i]) maxf[i]=f;
} else {
if (-1==f) maxf[i]=-1;
else if (maxf[i]>=0 && f>maxf[i]) maxf[i]=f;
}
if (f>0 && L>0) {//检测是否带小数点数字忽略第一行标题行
w=strchr(p,'.')?strchr(p,'.')-p:strlen(p);if (w>maxw[i]) maxw[i]=w;
} else {
w=strlen(p);if (w>maxw[i]) maxw[i]=w;
}
}
} else {
if (fgrp>=0) {
if (L==0) {
o1=1;
for (i=0;i<n;i++) {
if (i==fgrp || fout[i]) outf(i,d);
}
fprintf(fo,"\n");
} else {
f=0;if (L>=2 && strcmp(e[fgrp],d[fgrp])) f=1;
if (f==0) {
for (i=0;i<n;i++) {
if (fout[i]) {
p=strlrtrim_c2c(d[i]);
val=0.0;
sscanf(p,"%lf",&val);
fsum[i]+=val;
}
}
} else {//f==1
o1=1;
for (i=0;i<n;i++) {
if (i==fgrp) {
outf(i,e);
} else if (fout[i]) {
sprintf(e[i],"%.15lg",fsum[i]);
outf(i,e);
fsum[i]=0.0;
p=strlrtrim_c2c(d[i]);
val=0.0;
sscanf(p,"%lf",&val);
fsum[i]+=val;
}
}
fprintf(fo,"\n");
}
}
} else {
o1=1;
for (i=0;i<n;i++) outf(i,d);
fprintf(fo,"\n");
}
}
} else {//argc<2
for (i=0;i<n;i++) {
p=strlrtrim_c2c(d[i]);
if (i>0) fprintf(fo,",");
fprintf(fo,"%s",p);
}
fprintf(fo,"\n");
}
L++;
if (t=='t') {
if (L==1) memcpy((void *)e,(void *)d,MAXF*MAXC);
} else memcpy((void *)e,(void *)d,MAXF*MAXC);
}
pc++;
if (argc>=2 && 1==pc && t==0) goto AGAIN;//再一次从头读取每行
if (argc>=2 && 1==pc && t=='t' && fgrp==-2) {
printf("in.csv中共%d行×%d列:\n",L,n);
printf("No Width Type Title\n");
for (i=0;i<n;i++) {
printf("%-3d %5d %-7s %s\n",i+1,maxw[i],(maxf[i]==-1)?"String":((maxf[i]==0)?"Integer":"Float"),strlrtrim_c2c(e[i]));
}
while (kbhit()) getch();
return 0;
}
if (fgrp>=0) {
o1=1;
for (i=0;i<n;i++) {
if (i==fgrp) {
outf(i,e);
} else if (fout[i]) {
sprintf(e[i],"%.15lg",fsum[i]);
outf(i,e);
}
}
fprintf(fo,"\n");
}
fclose(fo);
fclose(fi);
if (rn>0) {
if (argc>=4)
printf("in.csv中共%d行×%d列(双引号中的%d个','或指定列间隔字符替换为';'\n且对%s列组内求和)已导出到文件out.csv中。\n",L,n,rn,argv[3]);
else if (argc>=3)
printf("in.csv中共%d行×%d列(双引号中的%d个','或指定列间隔字符替换为';'\n且各列对齐输出第%s列)已导出到文件out.csv中。\n",L,n,rn,argv[2]);
else if (argc>=2)
printf("in.csv中共%d行×%d列(双引号中的%d个','或指定列间隔字符替换为';'\n且各列对齐)已导出到文件out.csv中。\n",L,n,rn);
else
printf("in.csv中共%d行×%d列(双引号中的%d个','或指定列间隔字符替换为';')已导出到文件out.csv中。\n",L,n,rn);
} else {
if (argc>=4)
printf("in.csv中共%d行×%d列(对%s列组内求和)已导出到文件out.csv中。\n",L,n,argv[3]);
else if (argc>=3)
printf("in.csv中共%d行×%d列(各列对齐输出第%s列)已导出到文件out.csv中。\n",L,n,argv[2]);
else if (argc>=2)
printf("in.csv中共%d行×%d列(各列对齐)已导出到文件out.csv中。\n",L,n);
else
printf("in.csv中共%d行×%d列已导出到文件out.csv中。\n",L,n);
}
while (kbhit()) getch();
return 0;
}
//c:\test>type in.csv
//fl,number;float-str,n,c
//12.3,2;12.3-a4,5,6
//45.0,123;12345.0-a4,,
//1.23,;1.234-abcd,,c
//
//c:\test>csv
//in.csv中共4行×4列已导出到文件out.csv中。
//
//c:\test>type out.csv
//fl,number;float-str,n,c
//12.3,2;12.3-a4,5,6
//45.0,123;12345.0-a4,,
//1.23,;1.234-abcd,,c
//
//c:\test>csv a
//in.csv中共4行×4列(各列对齐)已导出到文件out.csv中。
//
//c:\test>type out.csv
//fl ,number;float-str,n,c
//12.3 ,2;12.3-a4 ,5,6
//45.0 ,123;12345.0-a4 , ,
// 1.23,;1.234-abcd , ,c
//
//c:\test>csv a,;-
//in.csv中共4行×6列(各列对齐)已导出到文件out.csv中。
//
//c:\test>type out.csv
//fl ,number,float ,str ,n,c
//12.3 ,2 , 12.3 ,a4 ,5,6
//45.0 ,123 ,12345.0 ,a4 , ,
// 1.23, , 1.234,abcd, ,c
//
//c:\test>csv ta,;-
//in.csv中共4行×6列:
//No Width Type Title
//1 2 Float fl
//2 6 String number
//3 5 Float float
//4 4 String str
//5 1 String n
//6 1 String c
//
//c:\test>type out.csv
//
//c:\test>csv g,;-,
//in.csv中共4行×6列(各列对齐)已导出到文件out.csv中。
//
//c:\test>type out.csv
//fl ,number;float -str ,n,c
//12.3 ,2 ; 12.3 -a4 ,5,6
//45.0 ,123 ;12345.0 -a4 , ,
// 1.23, ; 1.234-abcd, ,c
//
//c:\test>csv a,;- 4,3-1
//in.csv中共4行×6列(各列对齐输出第4,3-1列)已导出到文件out.csv中。
//
//c:\test>type out.csv
//str ,float ,number,fl
//a4 , 12.3 ,2 ,12.3
//a4 ,12345.0 ,123 ,45.0
//abcd, 1.234, , 1.23
//
//c:\test>csv a,;- 1 4,1-3
//in.csv中共4行×6列(对4,1-3列组内求和)已导出到文件out.csv中。
//
//c:\test>type out.csv
//fl ,number,float ,str
//57.3 ,125 ,12357.3 ,a4
// 1.23,0 , 1.234,abcd
//
//c:\test>csv /?
//用法:csv [[t]a|[t]g[delims] [1,3-5,1,100-99] [4,1-3]]
//将in.csv中各列两端的空白去掉,双引号中的','或指定列间隔字符替换为';'[且[t列出各列序号和标题|a指定列间隔字符集合各列对齐|
//g指定列间隔字符列表各列对齐] [输出第1,3-5,1,100-99列] [异或按第4列分组后对1-3列组内求和]]
//
//c:\test>del in.csv
//
//c:\test>csv
//无法打开文件in.csv!
//用法:csv [[t]a|[t]g[delims] [1,3-5,1,100-99] [4,1-3]]
//将in.csv中各列两端的空白去掉,双引号中的','或指定列间隔字符替换为';'[且[t列出各列序号和标题|a指定列间隔字符集合各列对齐|
//g指定列间隔字符列表各列对齐] [输出第1,3-5,1,100-99列] [异或按第4列分组后对1-3列组内求和]]
//