質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

4555閲覧

C言語 CSVファイル各項目を構造体へ格納する処理

watan

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/08/10 00:48

C言語でfscanf関数を使用してCSVファイルを読み込みCSVファイルの各項目を構造体へ格納する処理がうまくいきません。

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct{ char sStr0[9]; char sStr1[3]; char sStr2[4]; char sStr3[4]; char sStr4[3]; }stTest ; void main(){ stTest kTest[3] ; int iLp; char fname[] = ".\test.csv" ; FILE *fp ; fp = fopen( fname, "r" ) ; if( fp == NULL ){ printf( "File Open Error \n"); return ; } memset(&kTest, 0x00, sizeof(kTest)); for( iLp = 0; iLp < 3 ; iLp ++ ){ //カンマ区切りのデータを構造体に格納する。 fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%[^,]", kTest[iLp].sStr0, kTest[iLp].sStr1, kTest[iLp].sStr2, kTest[iLp].sStr3, kTest[iLp].sStr4 ); fgetc(fp) ; printf( "sStr0[%s] sStr1[%s] sStr2[%s] sStr3[%s] sStr4[%s]\n", kTest[iLp].sStr0, kTest[iLp].sStr1, kTest[iLp].sStr2, kTest[iLp].sStr3, kTest[iLp].sStr4 ); } return ; }

tesy.csv

20170901,6J ,AAA,XXX,51 20170901,6J ,BBB,YYY,53 20170901,6J ,CCC,ZZZ,55

上記プログラムを実行すると下記のような結果となります。

sStr0[20170901] €sStr1[6J AAA] sStr2[AAA] sStr3[XXX] sStr4[51] sStr0[20170901] €sStr1[6J BBB] sStr2[BBB] sStr3[YYY] sStr4[53] sStr0[20170901] €sStr1[6J CCC] sStr2[CCC] sStr3[ZZZ] sStr4[55]

sStr1には[6J]が入るようにしたいのですが、どのようにすれば正しく読み込めますでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

こんにちは。

gccとclangならば次の書式指定で読めましたけど、狙い撃ちしているので危険なコードです。

C

1fscanf( fp, "%[^,],%[^,\x20] ,%[^,],%[^,],%s", 2 kTest[iLp].sStr0, kTest[iLp].sStr1, kTest[iLp].sStr2, kTest[iLp].sStr3, kTest[iLp].sStr4 );

fscanfの細かい振る舞いを把握しておかないとちゃんと作るのは現実的ではありません。ここは比較的細かい説明があるようです。熟読して、実際に走らせてみて振る舞いを確認することで可能になるだろうと思います。

しかし、今どき、設計が古すぎて問題点が盛りだくさんの「C言語の標準ライブラリ」に熟練する意味がどの程度あるのか疑問です。fgetsで読んでstrtokで分解した方がメリットは多そうです。

投稿2018/08/10 01:35

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/10 01:54

回答ありがとうございました。具体的な解説助かりました。 ご提案の通りfgetsで読み込んだものを分解する方法で試してみようと思います。
guest

0

データとscan書式があってないので、sStr1格納時にsStr2の領域までオーバーフローしています。

データに合わせると、"%[^,],%[^, ] ,%[^,],%[^,],%[^,]"ですね。
長さ指定も加えると、"%8[^,],%2[^, ] ,%3[^,],%3[^,],%2[^,]"

各項目が固定長なら、fscanfじゃなくて、文字位置で切り出して、コピーすればいいかと。

投稿2018/08/10 01:17

otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/10 01:56

回答ありがとうございました。 書式指定の方法の具体例まで提示していただきまして勉強となりました。
guest

0

sStr1のサイズが足りてないです。
NULL文字も考慮して4バイト必要です。

投稿2018/08/10 01:15

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/10 01:57

回答ありがとうございました。ご指摘いただき助かりました。
guest

0

fscanfで分けるのはちと難しいかと。

fgetsで1行づつ読み込んで、コンマで分離していくようにしたほうがいいかと思います


fscanfで分けるのは難しい、んじゃなくて危険。使ってはいけません。
実は、提示の結果はあなたの思うようになった結果でもあったりするんですが。

投稿2018/08/10 00:52

編集2018/08/10 01:02
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/10 01:58

回答ありがとうございました。 fscanfは危険ということで調べてみました。 ご提案いただきました通り、1行読み込んだものを分解する方法で試してみようと思います。
guest

0

もともと2項めが「6J 」と3文字なので、構造体側では sStr[4] 必要なのに sStr[3] ですから、文字列終端を示す \0 が消えて、次の項目と繋がってしまっています。

fscanf を使うのは避けるべきですが、合わせて構造の定義を変更する必要があります。

投稿2018/08/10 01:07

編集2018/08/10 01:08
tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問