• ベストアンサー

構造体とポインタについて教えてください。

#include <stdio.h> typedef struct ningen { char *name; char *sex; int age; } NINGEN; NINGEN data = {"牧村 五郎",NULL,30}; char mf[2][3] = {"男","女"}; void main(void) { data.sex=mf[0]; printf("%s (%s) %d歳\n", data.name, data.sex, data.age); } このプログラムで実行結果は 牧村 五郎 (男) 30歳 となるのですが、最初の typedef struct ningen { char *name; char *sex; int age; } NINGEN; のところで、nameとsexはアドレスで宣言しているので printf("%s (%s) %d歳\n", data.naem, data.sex, data.age);でのdata.naem, data.sexでの対象もアドレスを示していると思うのですが、 結果は値を表示しているのはなぜでしょうか?

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

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

printfの%sが「渡された引数を文字列へのアドレスと思い、そのアドレスにある文字列を出力しろ」と言う意味だからです。 なので、渡す引数がアドレスなのは当然ですし、値(文字列)を表示するのも当然です。 以下の例は、すべて「文字」と言う文字列を出力します。 ------------------------ printf("%s\n","文字"); ------------------------ char *p; p = "文字"; printf("%s\n",p); ------------------------ struct { char *p; } t; t.p = "文字"; printf("%s\n",t.p); ------------------------ このように、リテラル文字列であれ、構造体であれ、ポインタであれ、結果は同じです。

yuyakiyo
質問者

お礼

たいへん分かりやすい解説でした。 %sにそのような意味があったんですね。 理解できました。 ありがとうございました。

その他の回答 (3)

回答No.4

こういう話かな? それは、C言語には、2次元配列というものが存在しないからです。 char mf[2][3]; は、char の2次元配列ではなくて、 char [3]個の1次元配列が、2 個からなる配列です。 なので、mf[0]は、「配列 mf[0] の先頭アドレス」なので、char * に正しく代入できます。 その実体は、 char [3] です。

yuyakiyo
質問者

お礼

char mf[2][3];における mf[0]はアドレスを指しているのですね。 質問の内容はここでは、なかったのですが この部分も理解できていなくて困っていたので助かりました。 ありがとうございました。

  • bulgaris
  • ベストアンサー率50% (8/16)
回答No.2

>このプログラムで実行結果は >牧村 五郎 (男) 30歳 と説明しているのにdata.name, data.sexの結果が 値を表示しているとは、どういうことでしょうか? 先の実行結果は、あなたが作成したプログラムの実行結果ですか? そうでないならば、実際の実行結果を示してくれませんか?

yuyakiyo
質問者

補足

解答ありがとうございます。 参考書に書いてあったプログラムなのですが、 ポインタなのになぜ値を示しているのかが疑問だったのです。分かりにくくてすいません。

  • valvelde
  • ベストアンサー率35% (46/129)
回答No.1

printf関数でアドレスの先頭から'\0'間での文字を表示するようになっているので正しく表示される。

関連するQ&A

  • 構造体のポインタ

    なぜかprevのほうが表示されません。 問題としては関数を作成し gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END と表示させるのが目的です gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] ここまではうまく表示できているのですが・・・ #include <stdio.h> void printoufuku(struct kara *p); struct kara { char name[16]; int age; struct kara *next; struct kara *prev; }; int main() { struct kara a, x, f, m, c, *start; strcpy(a.name, "gyuri"); a.age = 23; strcpy(x.name, "sunyon"); x.age = 23; strcpy(f.name, "nicole"); f.age = 20; strcpy(m.name, "hara"); m.age = 20; strcpy(c.name, "jiyon"); c.age = 17; a.next = &x; x.next = &f; f.next = &m; m.next = &c; c.next = NULL; /********************* 5 lines */ c.prev = &m; m.prev = &f; f.prev = &x; x.prev = &a; a.prev = NULL; /*********************/ start = &a; printoufuku(start); return 0; } void printoufuku(struct kara *p) { for(p->next; p != NULL;p = p->next){ printf("%s[%d] ->",p->name,p->age); } for(p->prev; p != NULL; p = p->prev){ printf("%s[%d] ->",p->name,p->age); } }

  • 構造体について

    5件のデータをRECORDに追加したいのですが、 RECORD inputdata(void)の宣言文エラーなどのコンパイルエラー。それと、inputdataを用いてどうやって5件のデータを入れたらいいかがわかりません。教えてください。 #define SIZE 5 #include <stdio.h> typedef struct{ int yy; int mm; int dd; }YMD; typedef struct{ char name[20]; YMD birthday; int age; }RECORD; RECORD inputdata(void); void main(void) { int i; for(i = 0;i < SIZE;i++){ inputdata(); } RECORD inputdata(void) { RECORD person; printf("名前>"); scanf("%s", person.name); printf("誕生日入力\n"); printf("年>"); scanf("%d", person.birthday.yy); printf("月>"); scanf("%d", person.birthday.mm); printf("日>"); scanf("%d", person.birthday.dd); return person; }

  • 構造体の構造体 引数

    構造体の中の構造体の関数の引き渡し方法がわかりません。 下記ソースで試したのですが、うまくいきませんでした。 助言お願いいたします。 //repo.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define NUM 20 #define MAX 15 struct seiseki{ float shu[3]; }; struct seito{ char name[NUM]; int age; struct seiseki kekka; }; void input(struct seito *p); void s_input(struct seiseki *p); void ss_input(struct seiseki *data); int main(){ int i; struct seito data[2]; for(i=0;i<2;i++){ printf("------------------------------\n"); printf("%d人目",i+1); input(&data[i]); } printf("%f\n",data[0].kekka.shu[0]); printf("%f\n",data[0].kekka.shu[1]); printf("%f\n",data[0].kekka.shu[2]); //data[1]に格納できない。 printf("%f\n",data[1].kekka.shu[0]); printf("%f\n",data[1].kekka.shu[1]); printf("%f\n",data[1].kekka.shu[2]); return 0; } void input(struct seito *p){ printf("名前->"); scanf("%s",p->name); printf("年齢->"); scanf("%d",p->age); s_input(&(p->kekka)); } void s_input(struct seiseki *data){ printf("国語->"); ss_input(data); printf("算数->"); ss_input(data); printf("英語->"); ss_input(data); } //下記関数で成績をchar型で受け取り、数値化したい。 void ss_input(struct seiseki *data){ char p[100]; int i=0; static int o=0; scanf("%s",p); while( p[i] != '\0'){ if(isdigit(p[i])==0){ printf("再入力してください"); scanf("%s",p); } i++; } data->shu[o]=atof(p); printf("%f\n",data->shu[o]); o++; }

  • C言語について

    いつもお世話になっています。 以下のソースを分割コンパルをしたいのですが・・・コンパイルがとおりません。 環境としては、Visual Studio 2005 です。 ヘッダファイルは、 /* People.h */ #include <stdio.h> #include <string.h> typedef struct { char name[256]; int age; int sex; } People; /* 個人データを入力する */ extern void InputPeople(People *data); /* 個人データを表示する */ extern void ShowPeople(People data); で、 /* People.c */ #include "People.h" void InputPeople(People *data) { /* 中身は同じなので省略 */ printf("名前:"); scanf("%s",data->name); printf("年齢:"); scanf("%d",&data->age); printf("性別(1-男性、2-女性):"); scanf("%d",&data->sex); printf("\n"); } void ShowPeople(People data) { /* 中身は同じなので省略 */ char sex[16]; printf("名前:%s\n",data.name); printf("年齢:%d\n",data.age); if (data.sex == 1) { strcpy(sex,"男性"); } else { strcpy(sex,"女性"); } printf("性別:%s\n",sex); printf("\n"); } どこがおかしいのでしょうか?? あと、コマンドのところでは、 C:\ > ←のあとは、普通にcl People.cとすればいいのでしょうか?

  • リストの削除について(構造体)

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #include<stdio.h> #include<malloc.h> #include<string.h> struct list{ char name[20]; int age; struct list *next; }; void main(void) { struct list *head, *p, *n, *old; char key[20]; /*ダミーノード作成*/ head = (struct list*)malloc(sizeof(struct list)); old = head; while(p = (struct list*)malloc(sizeof(struct list)), printf("name age入力\n"), scanf("%s %d", p -> name, &p -> age) != EOF){ old -> next = p; old = p; } free(p); old -> next = NULL; p = head -> next; printf("変更前リスト\n"); while(p != NULL){ printf("name:%s age:%d\n",p -> name, p -> age); p = p -> next; } printf("削除key入力(name)\n"); gets(key); n = head; while(n != NULL){ old = n; n = n -> next; //printf("n -> name %s\n", n -> name); if(strcmp(n -> name, key) == 0){ printf("%s削除\n", key); //printf("n -> name %s old -> name %s\n", n -> name, old -> name); old -> next = n -> next; } } p = head -> next; printf("変更後リスト\n"); while(p != NULL){ printf("name:%s age:%d\n", p -> name, p -> age); p = p -> next; } }

  • ファイル読込時に構造体の文字列ポインタに割当てたいと

    ファイル読込時に構造体の文字列ポインタに割当てたいと思っています。 (new 演算子を使用します。) 文字列の長さが不定です。 どうすれば、文字列の長さを知ることができますか? 以下のようなところまでは作れましたが、 困っています。 void loaddata()のfscanf関数の部分です。 ほかにも関数の void outputdata() void deletedata() がありますが、長いので省略しました。 ********************************************************** #include<stdio.h> #include<string.h> class data { public: struct basic { char *name; int age; struct basic *next; }; private: struct basic *base; struct basic *base_top; int cnt; public: data::data() { cnt=0; } void inputdata(char *name,int age) { if(cnt==0) { base=new basic; base_top=base; base->age=age; int len=strlen(name); base->name=new char[len+1]; strcpy(base->name,name); cnt++; } else { base->next=new basic; base=base->next; base->age=age; int len=strlen(name); base->name=new char[len+1]; strcpy(base->name,name); cnt++; } } void savedata() { base=base_top; FILE *fp; fp=fopen("dat.txt","w"); for(int i=0;i<cnt;i++) { fprintf(fp,"%s\t%d\n",base->name,base->age); base=base->next; } fclose(fp); } void loaddata() { if(cnt!=0){deletedata();} cnt=0; FILE *fp; fp=fopen("dat.txt","r"); while(1) { fscanf(fp,"%s\t%d\n",base->name,base->age); } } };

  • ポインタ型配列のポインタを構造体のポインタ変数に格納する方法教えて!

    問題の箇所を試行錯誤しても「移植性のないポインタ変換(関数 main )」と表示されます。 どうすればエラーが出ないでしょうか? 返答のほどよろしくお願いいたします。 #include<stdio.h> char *name[] = {"AAA", "BBB", "CCC"}; struct namelist{ char *name; struct namelist *next; }*head; void main(void) { printf("name = %s\n", name[1]); head -> name = *name[1];←問題の箇所 printf("head -> name = %s\n", head -> name); }

  • structでvoid*型を利用して中身を動的に変化させる

    構造体の中にvoid*型のポインタを作り、そこの中身を替えることでデータを変えたいと思っています。 例 struct DATA{ void* p; } struct PROF_1{ char* name; int age; } struct PROF_2{ char* name; int age; int level; } void main(){ struct DATA data; struct PROF_1 p1={"HATOYAMA", 60}; struct PROF_2 p2={"OBAMA", 60, 1}; data.p = p1; printf("Name[%s] Age[%d]\n", (PROF_1)(data.p)->name, (PROF_1)(data.p)->age); data.p = p2; printf"Name[%s] Age[%d] Lv[%d]\n", (PROF_2)(data.p)->name, (PROF_2)(data.p)->age, (PROF_2)(data.p)->level); } このような感じで構造体の中にあるvoid*型のポインタの参照する場所を変えるだけで構造体の中身を変化させることが出来ないでしょうか?

  • 構造体配列

    いつもお世話になっています。 今日構造体配列を勉強した際に下の演習をしていたのですが、いまいち基礎的な関数や配列のことやコマンドライン引数のことが理解できていません。一応自分なりにプログラムを書いてみたのですが、エラーがでます。 どなたかアドバイス・ご指摘・解説・例などをおねがいいたします。 問題はコマンドライン引数で人数を指定し,人数分のデータを標準入力(キーボード)から構造体配列に入力し,標準出力(ディスプレイ)に出力するプログラムです。 #include<stdio.h> typedef struct{ char name[100]; int age; double height; double weight; } PERSONAL_DATA1; typedef struct{ int person[10]; }PERSONAL_DATA2; PERSONAL_DATA1 input_personal_data(int num); void output_personal_data(PERSONAL_DATA2 person[10],int num); int main(int argc, char *argv[]){ PERSONAL_DATA1 x; int num,i; char person[10]; if(argc != 2){ printf("Usage ./test number"); return 0; } num=atoi(argv[1]); for(i=0;i<10&&i<num;i++){ person[i]=input_personal_data(); output_personal_data(person,num); return 0; } } PERSONAL_DATA input_personal_data(void){ PERSONAL_DATA1 x; printf("name>"); scanf("%c" ,&x.name); printf("age>"); scanf("%d" ,&x.age); printf("height>"); scanf("%lf" ,&x.height); printf("weight>"); scanf("%lf" ,&x.weight); return x; } void output_personal_data(PERSONAL_DATA2 person[10],int num){ PERSONAL_DATA1 x; printf("name>>%s\n" ,x.name); printf("age>>%d\n" ,x.age); printf("height>>%lf[cm]\n" ,x.height); printf("weight>>%lf[kg]\n" ,x.weight); } またコマンドライン引数で指定したデータファイルAから入力した個人データ集合を構造体配列に取り込み,標準出力(ディスプレイ)と同じくコマンドライン引数で指定したデータファイルBへファイル出力に出力するプログラムというおまけの問題もあります。 こちらの問題のヒントもいただけませんか?

  • 構造体宣言したポインタ変数に値を代入するには?

    strcpy(p -> key ,name);と打ってp -> key に入力した名前を格納したいのですがうまくいきません。 ほかにもp -> key = nameなども試してみましたがコンパイルエラーが出現してダメでした。 うまく格納できるやり方があれば教えてください。よろしくお願いします。 #include<stdio.h> #include<string.h> #define WORD_LENGTH 50 /* 文字列の最大長 */ typedef struct cell{ char key[WORD_LENGTH]; struct cell *next; /* 次のセルへのポインタ */ } CELL; void main(void) { char name[WORD_LENGTH]; CELL *p; printf("名前入力\n"); scanf("%s\n", name); strcpy(p -> key ,name); printf("%s\n", p -> key); }