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++であれば、上記相当のプログラムは書けると思いますが……。
素晴らしいです!
よくそんなアイディアが浮かびますね!!
sankaku197様は幅広い経験をお持ちなのですね
初心者の私は雷に打たれたような感じです(笑)
本当にありがとうございました。
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);
}
私への質問の回答の為にここまで参考になる情報を提供してくださいまして
心から感謝しております。
是非活用させていただきます
本当にありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Access(アクセス) CSVファイルの「0落ち」にVBA 6 2023/02/02 15:27
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- Visual Basic(VBA) 【VBA】特定の文字で改行(次の行)に行きたい。 3 2022/04/11 17:20
- Visual Basic(VBA) VBAで出力したCSVファイルの先頭にカンマを挿入したい 5 2022/10/14 12:20
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- Excel(エクセル) PowerQueryに詳しい方教えてください(Office365) 1 2022/07/24 21:11
- Excel(エクセル) CSVファイルがカンマ区切りにならない。対処法を教えていただきたいです。 仕事でSMS一斉送信ができ 2 2022/07/01 21:24
- その他(プログラミング・Web制作) データ解析ソフトRでのファイル入力read.csvがエラーになります 7 2022/03/27 22:11
- Visual Basic(VBA) 集めたシートのシート名を変更したい。 下記のコードでサブフォルダにあるファイルのSheet3を集めて 6 2022/08/23 10:38
- C言語・C++・C# 至急お願いします。C言語で.imgのファイルを読み込んで1バイトづつ出力するプログラムを作りたいので 3 2023/01/16 22:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
csvファイルからの読み込みがス...
-
半角カナ→16進
-
C言語の質問です
-
カラー画像からグレースケール...
-
switch文で文字を比較すること...
-
文字列の比較について
-
3桁区切(コンマ)記号をつけ...
-
charでの計算?
-
C言語で文字列操作を忘れてしま...
-
干支のプログラム
-
fgetsなどのときのstdinのバッ...
-
char型からのバイト数取得
-
c言語についての質問です。
-
int main()の・・・
-
charからLPTSTRへの変換方法
-
[C++]ファイル出力について
-
c言語の文字列の逆順のプログラ...
-
CStringをwchar_tに変換したい
-
C++の関数テンプレートで分から...
-
文字列について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語のfor文です。 繰り返しの...
-
テキストデータをそのままバイ...
-
charでの計算?
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
atoi( ) の反対をやりたい
-
2曲同時再生するにはどうした...
-
C言語の入力した文字を反転させ...
-
配列をnビットシフトする
-
3桁区切(コンマ)記号をつけ...
-
int main()の・・・
-
型変換
-
CStringをwchar_tに変換したい
-
'const char *' 型は 'char *' ...
-
間接操作のレベルとは
-
double型の値をchar配列に変換...
-
絶対パスからのファイル名の切...
-
switch文で文字を比較すること...
-
c++ 文字列を入力して、一文字...
おすすめ情報