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

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

ただいまの
回答率

88.64%

構造体のポインタ配列によるエラーから抜け出せない

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 916

urazome

score 26

標準入力からファイル名を入力して、そのファイルのデータを読み込み、ポインタ配列にデータを格納します。その後、別のファイルに先ほど格納したデータを書き込み、出力できれば成功です。
ファイルのデータはポインタ配列に格納し、且つ、利用する分だけ動的にメモリを確保することが条件です。

次の4行が読み込むデータです。
JZK-30 Jizake_tsumeawase 4500 
BSP-15 Body_soap_set 3000 
BT-200 Bath_towel_set 2500 
TEA-20 Koutya_tsumeawase 5000

そして以下のコードを作成したのですが、
"request for member '(構造体のメンバ)' in something not a structure or union"というエラーが表示されます。
(エラーが起きたところにエラーを書きました。)
しかし、何が足りないのかわかりません。。。ご教授頂けると助かります!

#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 4

struct gift{
  char code;
  char name;
  int price; 
};

int main(void)
{
  int num,i,k;
  char ref[256];
  int fprice[MAX][256]; //一時保管場所
  char fname[MAX][256], fcode[MAX][256];  //一時保管場所

  FILE *fp;
  FILE *file;

  printf("データ数を入力してください:");
  scanf("%d",&num);
  printf("ファイル名を指定して下さい:");
  scanf("%s",ref);


  struct gift *gifts[num];

  for(i=0;i<MAX;i++){

    fp=fopen(ref,"r");
    if(fp==NULL){
      printf("%s ファイルが開けません\n",ref);
      exit(1);
    }

    fscanf(fp,"%s %s %d",fcode[i],fname[i],fprice[i]);  //一時保管場所に保管

    k=0;
    while(fprice[i][k]){
      k++;
  }

//ここから動的メモリ確保をします
    (gifts+i)->code=(char*)malloc(sizeof(char)*strlen(fcode[i]));  //エラーrequest ~ 'code' in ~
    (gifts+i)->name=(char*)malloc(sizeof(char)*strlen(fname[i]));   //エラーrequest ~ 'name' in ~
    (gifts+i)->price=(int*)malloc(sizeof(int) * k+1);               //エラーrequest ~ 'price' in ~

//コピー
    srcpy((gifts+i)->code,fcode[i]);    //エラーrequest ~'code' in ~
    srcpy((gifts+i)->name,fname[i]);    //エラーrequest ~'name' in ~
    srcpy((gifts+i)->price,fprice[i]);  //エラーrequest ~'price' in ~

    fclose(fp);

    file=fopen("present.txt","w");
    fprintf(file,"%s\n%s\n%d\n",(gifts+i)->code,(gifts+i)->name,(gifts+i)->price);  
 //エラーrequest ~'code' in ~  //エラーrequest ~'name' in ~  //エラーrequest ~'price' in ~

    fclose(file);

    free((gifts+i)->code);  //エラーrequest ~'code' in ~
    free((gifts+i)->name);  //エラーrequest ~'name' in ~
    free((gifts+i)->price);  //エラーrequest ~'price' in ~
  }


  puts("表示形式変換後ファイルに出力しました。");

  return 0;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

...なんかダメダメやね。
そのものヅバリを呈示するから よーく読んで理解して。
すべての処理をmain一本に詰め込むのは悪い癖だ。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

struct gift {
  char* code;
  char* name;
  int   price; 
};

// 与えられたcode/name/priceを基にgiftを生成する
struct gift* gift_create(const char* code, const char* name, int price) {
  struct gift* result = (struct gift*)malloc(sizeof(struct gift));
  assert( result != NULL );
  result->code = strdup(code); assert(result->code != NULL);
  result->name = strdup(name); assert(result->name != NULL);
  result->price = price;
  return result;
}

// giftを廃棄する
void gift_destroy(struct gift* pgift) {
  assert(pgift != NULL);
  free(pgift->code);
  free(pgift->name);
  free(pgift);
}

// ファイルから読みこまれた一行(line)を基にgiftを構築する
struct gift* gift_build(char* line) {
  char* code;
  char* name;
  int   price;
  char* ctx;
  assert(line != NULL);
  code = strtok_s(line, " ", &ctx);
  name = strtok_s(NULL, " ", &ctx);
  price = atoi(strtok_s(NULL," ", &ctx));
  return gift_create(code, name, price);
}

/*
 *  main
 */

#define MAX 4

int main() {

  struct gift* gifts[MAX];
  int num;

  { // ファイルを呼んでgiftsを構築する。データ数(最大MAX個)をnumに求める
    FILE *fp;
    char line[256];

    printf("ファイル名を指定して下さい:");
    scanf("%s",line);

    fp = fopen(line, "r");
    if(fp==NULL){
      printf("%s ファイルが開けません\n",line);
      exit(1);
    }

    num = 0;
    while ( fgets(line, 256, fp) ) {
      gifts[num++] = gift_build(line);
      if ( num == MAX ) break;
    }
    fclose(fp);
  }

  { // giftsを出力。ファイルに書き出したいなら好きにしろ
    int i;
    for ( i = 0; i < num; ++i ) {
      printf("code[%s] name[%s] price[%d]\n", gifts[i]->code, gifts[i]->name, gifts[i]->price);
    }
  }

  { // あとしまつ
    int i;
    for ( i = 0; i < num; ++i ) {
      gift_destroy(gifts[i]);
    }
  }

  return 0;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/14 23:17

    お忙しいところ、わざわざコードを見直していただきありがとうございます。大変勉強になりました!

    キャンセル

+1

    (gifts+i)->code=(char*)malloc(sizeof(char)*strlen(fcode[i]));  //エラーrequest ~ 'code' in ~

gift の中身が存在しません。
(gifts+i)ってなにを指してるのか考えてみればどうでしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/14 23:19

    はい!ありがとうございます!

    キャンセル

+1

(gifts+i)->code  宣言を見ると、struct gift *gifts[num] なんで、struct giftへのポインタ配列。実体が無いので、まずは、その実体の確保から。

で、code=(char*)malloc() この部分も、左側が char に対し、右側が、(char *) なので不一致。 こちらは、struct gistの宣言の見直しが必要かと思います。

VS2019でコンパイルしたら、他にも色々と警告されましたが、まずはこの辺でしょうか。 (警告の一部は、コンパイラオプションの問題ですが)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/14 23:18

    恐縮です。助言ありがとうございます!

    キャンセル

0

結局、以下のコードで通してもらえました。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX 256

 struct gift{
  char code[MAX];
  char name[MAX];
  int price; 
};

int main(void)
{
  int num,i,len;
  char ref[256];//="gifts.dat";
  int fprice;
  char fname[256], fcode[256];

  FILE *fp;
  FILE *file;




  printf("データ数を入力してください:");
  scanf("%d",&num);
  printf("ファイル名を指定して下さい:");
  scanf("%s",ref);


  struct gift *gifts=(struct gift*)malloc(num * sizeof(struct gift));

    fp=fopen(ref,"r");
    if(fp==NULL){
      printf("%s ファイルが開けません\n",ref);
      exit(1);
    }

  for(i=0;i<num;i++){

    fscanf(fp,"%s %s %d",fcode,fname,&fprice);
    //fscanf(fp,"%s ",gifts->code);

    //printf("%s %s %d\n",fcode,fname,fprice);
    //printf("%s\n", fcode);

    strcpy((gifts+i)->code,fcode);
    strcpy((gifts+i)->name,fname);
    (gifts+i)->price=fprice;

    //printf("%s \n",(gifts+i)->code);
    //++gifts;
  }
  fclose(fp);

  file=fopen("present.txt","w");
  for(i=0;i<num;i++){
    fprintf(file,"code:%s\nname:%s\nprice:%d\n\n",(gifts+i)->code,(gifts+i)->name,(gifts+i)->price);
    //printf("%s\n",gifts->code);

    //++gifts;
    //free((gifts+i)->code);
    //free((gifts+i)->name);
    // free((gifts+i)->price);
  }
  fclose(file);

  free(gifts);
  puts("表示形式変換後ファイルに出力しました。");


  return 0;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る