• ベストアンサー

csvファイルからの読み込みがスムーズにできません

fscanfでCSVファイルから文字列を取り込み、カンマ区切りで4つの変数に文字列を代入しようと考えているのですが、出力されたcsvファイルが変わった区切りかたをしているのでうまく変数に代入できずに困っております。 例えば、出力されたcsvファイルは以下のようになっております "ABC CO.,I","4540",""STAR"","2010/03/31" 希望としては aにABC CO.,I bに4540 cにSTAR dに2010/03/31 をそれぞれ代入したいのですが aに入る文字列にはCO.,Iというようにカンマが既にありますので カンマ区切りで読み込むとめちゃくちゃになってしまいます ですので基準をダブルクオーテーションに置き、"と"の間の文字列を代入というような形が取れれば良いのですが、このような方法での文字列取得は可能でしょうか? c言語の勉強を始めて間もない為、低レベルな質問、表現であることをお許し下さい。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

"の回数を判定する変数を用意すれば、ご要望を満たせると思います。 //"を数える変数 int count=0; //csvの内容が入った文字列とする char str[]; //strのインデックス数(≒csvファイルの文字数) int length; char a[256],b[256],c[256],d[256]; //jはabcd配列のインデックスに使う int i,j; for(i=0; i<length; i++){ //"をカウント if(str[i] == '"'){ count++; continue; } //"が偶数の時 if(!(count % 2)) j=0; //"が1~2の間はaに代入 else if(count == 1){ a[j] = str[i]; j++; } //"が3~4の間はbに代入 else if(count == 3){ b[j] = str[i]; j++; } //以下略... } ただ、この方法だと「文字列内に"がある場合」には上手くいきません。 csvには規定があるので、下記リンク20行ほどを読まれると良いです。 http://dobon.net/vb/dotnet/file/readcsvfile.html C#であれば、これをコピペするだけで解決なんですけどね。 せめてC++であれば、上記相当のプログラムは書けると思いますが……。

master817199
質問者

お礼

素晴らしいです! よくそんなアイディアが浮かびますね!! sankaku197様は幅広い経験をお持ちなのですね 初心者の私は雷に打たれたような感じです(笑) 本当にありがとうございました。

その他の回答 (1)

回答No.1

このカテゴリでCSVについて何度も出ているため、一応汎用化を目指して組んでみたプログラムを晒します。 昔の事なので、どこまでデバッグ出来ていたのか覚えていません。 --------------------------------- #include <stdio.h> #include <string.h> #include <stdlib.h> #define STRING_MAX 2048 #define FIELD_MAX 256 #define RECORD_MAX 16384 #define STRING_BUF 16384 typedef struct scsvrec{  char chr[FIELD_MAX][STRING_MAX]; }SCSVREC; typedef struct scsvdat{  long record_cnt;  SCSVREC *dat[RECORD_MAX]; }SCSVDAT; bool csvFileRead(char *filename ,SCSVDAT *csvDat); SCSVREC* csvResolution(char *buf); bool isKanji(unsigned char c); int main() {  bool bRet;  SCSVDAT *cdat;  char filename[1024] = "sample.csv";  cdat = (SCSVDAT*)malloc(sizeof(SCSVDAT));  bRet = csvFileRead(filename, cdat);  return(0); } bool csvFileRead(char *filename ,SCSVDAT *csvDat) {  FILE *fp;  SCSVREC *onerec;  bool ret = false;  char buf[STRING_BUF];  memset(csvDat ,0 ,sizeof(SCSVDAT));  fp = fopen(filename,"r");  if(fp == NULL){   printf("ファイルが開けませんでした。\n");   return(false);  }  while(fgets(buf,sizeof(buf),fp) != NULL){   if (buf[strlen(buf)-1] == '\n'){    buf[strlen(buf)-1] = '\0';   }   onerec = csvResolution(buf);   csvDat->dat[csvDat->record_cnt] = onerec;   (csvDat->record_cnt)++;  }  fclose(fp);  return (true); } SCSVREC* csvResolution(char *buf) {  int bcnt, rcnt, mcnt;  bool dblfld;  SCSVREC *onedat;  onedat = (SCSVREC*)malloc(sizeof(SCSVREC));  memset(onedat ,0 ,sizeof(SCSVREC));  bcnt = rcnt = mcnt= 0;  dblfld = false;  for(;;bcnt++) {   if (buf[bcnt] == '\0') break;   if (mcnt == 0 && buf[bcnt] == '\"') {    dblfld = true;    continue;   }   if (isKanji((unsigned char)buf[bcnt])) {    onedat->chr[rcnt][mcnt] = buf[bcnt];    mcnt++;    bcnt++;    onedat->chr[rcnt][mcnt] = buf[bcnt];    mcnt++;    continue;   }   if (dblfld == false && buf[bcnt] == ',') {    rcnt++;    mcnt = 0;    continue;   }   if (dblfld == true && buf[bcnt] == ',') {    onedat->chr[rcnt][mcnt] = buf[bcnt];    mcnt++;    continue;   }   if (dblfld == true && buf[bcnt] == '\"' && buf[bcnt+1] == '\"') {    onedat->chr[rcnt][mcnt] = '\"';    mcnt++;    bcnt++;    continue;   }   if (dblfld == true && buf[bcnt] == '\"' && (buf[bcnt+1] == ',' || buf[bcnt+1] == '\0')) {    rcnt++;    mcnt = 0;    bcnt++;    dblfld = false;    continue;   }   onedat->chr[rcnt][mcnt] = buf[bcnt];   mcnt++;  }  return onedat; } bool isKanji(unsigned char c) {  bool ret = false;  if ((0x81 <= c && c <= 0x9f) || (0xE0 <= c && c <= 0xEF)) {   ret = true;  }  return (ret); }

master817199
質問者

お礼

私への質問の回答の為にここまで参考になる情報を提供してくださいまして 心から感謝しております。 是非活用させていただきます 本当にありがとうございます。

関連するQ&A

専門家に質問してみよう