質問するログイン新規登録
C

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

Q&A

解決済

2回答

946閲覧

fscanfでファイルを正しく読み込みたい

omochiiii.exe

総合スコア1

C

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

0グッド

0クリップ

投稿2022/01/31 13:50

編集2022/01/31 13:58

0

0

前提・実現したいこと

fscafを用いて読み込んだデータをprintfで表示したいのですが、
思ったようにデータが取得できません。

該当のソースコード

fassion.h

c

1#ifndef FASSION_H 2#define FASSION_H 3//------------------------------------------------ 4 5//------------------------------------------------ 6// マクロ定義(Macro definition) 7//------------------------------------------------ 8#define D_FASSION_IDSIZE (6) // IDバイト数 9#define D_FASSION_TYPESIZE (5) // 種類バイト数 10#define D_FASSION_COLORSIZE (4) // 色バイト数 11 12//------------------------------------------------ 13// 型定義(Type definition) 14//------------------------------------------------ 15// 服 16typedef struct{ 17 char fassion_id[D_FASSION_IDSIZE]; // ID 18 char type[D_FASSION_TYPESIZE]; // 種類 19 char color[D_FASSION_COLORSIZE]; // 色 20 int pattern; // 柄(0:なし 1:あり) 21}S_FASSION_DATA; 22 23//------------------------------------------------ 24// プロトタイプ宣言(Prototype declaration) 25//------------------------------------------------ 26int memorycatch(void); 27 28//------------------------------------------------ 29#endif 30

main.c

c

1#include <stdio.h> 2#include "fassion.h" 3 4int main(void){ 5 memorycatch(); 6}

fassion.c

c

1#include <stdio.h> 2#include "fassion.h" 3#include <stdlib.h> 4#include <string.h> 5#define _CRT_SECURE_NO_WARNINGS 6 7//------------------------------------- 8//メモリ確保 9//------------------------------------- 10int memorycatch(){ 11 12 FILE * fp = NULL; 13 S_FASSION_DATA * pFdata = NULL; 14 15 // メモリ領域をヒープメモリに確保 16 pFdata = (S_FASSION_DATA *)malloc(sizeof(S_FASSION_DATA)); 17 if(pFdata == NULL){ 18 return -1; 19 } 20 21 // fp = fopen("./fasson/fassion.txt", "r"); 22 fp = fopen("fassion.txt", "r"); 23 24 25 if(fp == NULL){ 26 return -1; 27 } 28 while(fscanf(fp, "%s, %s, %s, %d", 29 pFdata->fassion_id, 30 pFdata->type, 31 pFdata->color, 32 pFdata->pattern) != EOF){ 33 printf("ID:%s タイプ:%s 色:%s 柄:%d\n", 34 pFdata->fassion_id, 35 pFdata->type, 36 pFdata->color, 37 pFdata->pattern); 38 } 39 40 return 0; 41}

fassion.txt

txt

1P00001, skirt, pink, 0 2

printfで表示した結果

理想(正)

ID:P00001 タイプ:skirt 色:pink 柄:0

現在(誤)

ID:P00001, タイプ:, 色:kカ 柄:9836336 ID:skirt, タイプ: 色:kカ 柄:9836336 ID:pink, タイプ: 色:kカ 柄:9836336 ID:0 タイプ: 色:kカ 柄:9836336

試したこと

  • テキストの変更
  • 構造体の文字列(type,color)のサイズ変更

初歩的な質問だとは思いますが、よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

fscanf関数の書式設定が間違っているのが原因です。
"%s, %s..."は、「(カンマではなく)空白文字を発見するまでストリームを読み込みバッファに格納せよ、そして直後のカンマ、0個以上の空白文字を読み飛ばし、その後、空白文字を発見するまでストリームを読み込みバッファに格納さよ、…」という意味に解釈されます。そのため、1つ目の%sで、"P00001,"がバッファに格納されます。その後、カンマを読み飛ばそうとしますが、実際にストリームに残っているのは空白文字ですから、書式文字列と一致しません。そのため、fscanf関数はそこで終了し、読み取ったフィールド数の1を返します。

直し方ですが、"%6[^,]"のように指定すれば、「カンマ以外の文字を最大6文字読み取れ」という意味になり、2つ目以降のフィールドが読めるようになります。
(ただ、バッファの大きさが足りないのでこのままでは動きませんが…)

投稿2022/01/31 14:59

majiponi

総合スコア1722

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

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

omochiiii.exe

2022/02/01 14:59

回答ありがとうございます。返信遅れて申し訳ないです。 丁寧な説明をありがとうございます。 なぜうまく読み取れないのか原因を理解することができました。 ベストアンサーはどちらにもつけたいのですが、 早さおよび指摘数の面からotnさんにさせていただきました。 お二人とも回答ありがとうございました。
guest

0

ベストアンサー

fscanfの引数にはアドレスを渡します。

C

1誤:pFdata->pattern) != EOF){ 2正:&pFdata->pattern) != EOF){

投稿2022/01/31 14:08

otn

総合スコア86389

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

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

omochiiii.exe

2022/01/31 14:26

回答ありがとうございます。 以下のように修正しましたが、やはり間違ったまま表示されます。 配列はそもそもアドレスのため、&はつけないでいいと思ったのですが、 あっていますでしょうか。 ---------------------------------------------------------------- while(fscanf(fp, "%s, %s, %s, %d", pFdata->fassion_id, pFdata->type, pFdata->color, &pFdata->pattern) != EOF){ ----------------------------------------------------------------
otn

2022/01/31 14:43

> 配列はそもそもアドレスのため、 patternは配列じゃないです。 > やはり間違ったまま表示されます。 全く同じ出力結果ということであれば、修正前のプログラムを動かしたのでは?
otn

2022/01/31 14:56 編集

ああ、書式がそもそも間違ってました。 "%[^,], %[^,], %[^,], %d" ですね。 %s は空白文字以外の文字列なので、P00001, にマッチします。「カンマ以外の文字列」にすべき。 fscanfの返り値が4であることを確認しましょう。
omochiiii.exe

2022/02/01 14:55

回答ありがとうございます。返信遅れて申し訳ないです。 >patternは配列じゃないです。 pattern以外(id,typeなどの配列)は&をつけないとだめなのか気になって確認しました。 otnさんの回答+最後に\n↓ fscanf(fp, "%[^,], %[^,], %[^,], %d\n", ~~~) で正常に読み込むことができました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問