C言語の構造体とは?

このQ&Aのポイント
  • C言語の構造体は、異なる型のデータをまとめて1つのデータ型として扱うためのものです。構造体を使用することで、複数の変数をひとまとめに管理することができます。
  • 構造体を使用すると、複数の変数をひとまとめに宣言することができます。例えば、個々の学生のデータを管理する場合に、名前や学籍番号、成績などの情報を一括して扱うことができます。
  • また、構造体は関数の引数や返り値としても使用することができます。関数に複数のデータを渡す場合や、複数のデータを返す場合に便利です。
回答を見る
  • ベストアンサー

C言語の構造体

組込み系でマイコンにソフトをプログラミングの仕事をしています。 C言語は初心者です。 http://www9.plala.or.jp/sgwr-t/c/sec15.html のページの冒頭に、 「構造体は幾つかの異なる型のデータをまとめて 1つのデータ型として扱うものなのです。」と書かれています。 1つのデータ型として扱うとどのようなメリットがあるのでしょうか? 例えば、 struct seiseki seito1; のように対象が1つ(seito1)なら int seito1_no; char  seito1_name[20]; double seito1_average; と変数を確保すれば済むのに、 何故、構造体で宣言するのでしょうか? 例えば、 struct seiseki seito2[20]; のように、似たものが複数ある場合は(seito2が20人分なるなら、) 構造体で宣言する意味があるとはなんとなくわかります。 後ページの http://www9.plala.or.jp/sgwr-t/c/sec15-4.html では、関数でのやり取りが書かれています。 関数で引数や返値で扱うときに構造体にしておいた方が良いからでしょうか? 構造体のメリットというのが今一わかりません。 対象が1つでも構造体で書いた方がいろんな意味で良いのでしょうか? 如何せん、初心者なので質問がうまく書けませんがご了承ください。 ※上から目線的な回答はご遠慮願います。

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

  • ベストアンサー
  • jack-a3
  • ベストアンサー率34% (196/572)
回答No.5

No3です。 >仮に関数での引数で使わない場合でも構造体で書いた方が良いということでしょうか? そうですね。ある処理ブロックの中でしか使わない使い捨て的なデータならどうでもいいのですが、プログラムの動作期間中に保持され続けるデータであるとか、動作に影響を与えるようなある程度重要なデータに関しては、そのデータの内容に応じてまとめておいた方がいいです。理由はNo3にも書きましたが、あとから見た人がプログラムの意図を理解しやすくなる可能性があるからです。 ですが、どのデータが重要なデータだと判断するか、またどのデータをまとめて構造体化するか、といった点でプログラム作成者のセンスがモロに出ます。 質問者さんの例で言うと、生徒番号、名前、成績データを構造体として定義していると、あとから見た人は「ああ、生徒ごとの成績情報を管理、処理しようとしてるんだな」と想像がつきますが、ここにプログラム動作に必要だからと言ってプログラムの起動時間を管理する変数とか画面のボタン状態を管理する変数とかを同じ構造体のメンバに追加したらワケ分からなくなります。こういった、どのデータをどうまとめるかも設計力ですね。 もうちょっと言いますと、生徒ごとの成績情報みたいなそのプログラムで扱う大事なデータについては、実領域の確保、解放、内容の初期化、データの追加、更新、削除などの各処理をそれぞれ専用の下請け関数でやらせるようなプログラム構成にするのがセオリーです。そうするとおや関数から下請け関数を呼び出す時に、引数で渡すような形になるはずです。なぜこれがセオリーかは説明するのが大変ですが、「構造化プログラム」を勉強し、また一つのプログラムを複数人で開発する状況になると身についてくるはずです。

EGA4545
質問者

お礼

丁寧な回答ありがとうございます。 ソフトに対する気持ちが少し楽になりました。 構造化プログラム 調べてみます。

その他の回答 (4)

  • catpow
  • ベストアンサー率24% (620/2527)
回答No.4

>>回答者様は、どのようにして理解や習得されたのでしょうか? 教えてください。宜しくお願いします。 私がC言語を学んだ頃は、世の中は「猫も杓子もC言語」って雰囲気がありました。 ですので、書店には、C言語専門の月刊誌が並んでいたり、C言語の専門書も沢山並んでいました。 でも、多くの書籍は入門レベルであり、それらから実務レベルのC言語を学ぶのは困難だったように記憶しています。 とはいえ、C言語の中級以上の書籍が出版されていたのも確かです。 ある書籍では、C言語がどのようにマシン語に翻訳されるかについて、多くのページを使って、丁寧に解説してありました。 別の書籍では、1冊丸ごと「C言語を使って、MS-DOSで動作するC-Shellを作ろう」的な書籍がありました。 それを参考に、別のOSに、その便利なC-Shellを移植する作業をしました。 また、そのOSには、使いやすいデータベースが存在しなかったので、米国からデータベース的に使えるC言語のソースを購入して移植作業をしました。 購入したソースコードは膨大で、それまで見たこともないような命令の使い方がいくつもあり、しかも日本語対応も必要だったため、かなり移植には時間がかかりました。 そのように実務で使うようなC言語で書かれたソフトウエアの移植作業を通じて、C言語の理解をすることができたと思っています。 なお、絶版みたいですが「エキスパートCプログラミング 知られざるCの深層」とか、「BINARY HACKS ハッカー秘伝のテクニック100選」の書籍はC言語を深く理解するのに役にたつと思います。

EGA4545
質問者

お礼

回答ありがとうございます。 絶版ですか、ちょっと調べてみます。

  • jack-a3
  • ベストアンサー率34% (196/572)
回答No.3

プログラムが複雑になってくるとたくさんのデータを扱うことになりますが、いろんなデータの中からどのデータをひとかたまりとして扱おうとしているのかが分かりやすくなります。たとえば質問者さんの例だと生徒番号、名前、平均値をそれぞれ扱っていますが、これらを構造体として定義することで、後からプログラムを見た人が、そのプログラムではどのデータを関連したデータとして扱おうとしているのかの意図を理解しやすくなります。 また、質問者さんが挙げているURLにあるように、こういったデータは関数間の引数として渡すことが多いのですが、関数呼び出し時のパラメタに生徒番号、名前、平均値の3つを渡すより、構造体へのポインタを渡した方が記載が簡単です。 さらにはたとえば5教科の得点すべてを管理するような改造が発生体場合はどうでしょう?もし構造体化していない場合は、3つのパラメタを渡していた関数間の受け渡しの記載をすべて修正する必要がありますが、構造体化していた場合は構造体の定義を修正するだけで関数間のインタフェースの記載は修正しなくてもビルドできます。そして構造体のメンバ変数を追加や変更する場合、それがどの関数に影響するのかを調べることも簡単になります(構造体の定義名で検索すると影響範囲が分かる)。こういった点から保守性も向上します。 なお、C言語では扱うデータをひとかたまりにするのが構造体ですが、C++やJavaなどオブジェクト指向言語は、扱うデータとそのデータを処理する関数をひとかたまりにする、という考え方します(もっといろんな概念を含んでいますが、一番の基本はここ)。 なので、構造体を使いこなすことがオブジェクト指向言語の考え方を知る第一歩である、とも言えます。

EGA4545
質問者

補足

ご回答ありがとうございます。 仮に関数での引数で使わない場合でも構造体で書いた方が良いということでしょうか? ひょっとしたら、後々引数で使うかもしれないので構造体で書いておくということでしょうか? よろしくお願いします。

  • chachaboxx
  • ベストアンサー率23% (412/1777)
回答No.2

用途の参照ページの通りです。宣言が冗長になるのが防げ、引数の記述もシンプルになるので間違いも防げます。何を扱うかが明瞭になるので、見た目がキレイですよね。(笑)

  • catpow
  • ベストアンサー率24% (620/2527)
回答No.1

>>構造体は幾つかの異なる型のデータをまとめて 1つのデータ型として扱うものなのです。 このとおりのメリットです。 例えば、1つのデータとしてAさん1人の情報を確保する場合、住所、氏名、年齢、電話番号、メールアドレス・・・と沢山の情報が必要です。 もし、健康診断の情報まで入れたら、100項目を超えるかもしれません。 これを構造体として1つにまとめておけば、関数とのやりとりが1つの引数で済むため、楽になります。 ただ、このあたりは、入門レベルのC言語では、あまり記述がされてないことも多いので、C言語の初心者にはわかりにくい部分かもしれませんね。

EGA4545
質問者

補足

私は、ソフトのプログラミングは経験がありますがC言語が初心者です。 「学校の勉強で言えば、教科書は理解できますが、その次の応用問題やテストになると点が取れない」そんな局面に立たされています。 「入門レベルでは記述されていない」ということは、 回答者様は、どのようにして理解や習得されたのでしょうか? 教えてください。宜しくお願いします。

関連するQ&A

  • 構造体について

    凄く初歩的な質問で申し訳ありませんが… 入門書の構造体のところで 以下のようなプログラムの例がありました。 #include <stdio.h> struct seiseki { /* 構造体の宣言 */ int no; char name[20]; double average; }; int main(void) { int i; struct seiseki seito1, seito2[20]; /* 構造体変数と構造体配列の宣言 */ >char name[20] というのは、NAMEの領域を20文字 確保すると言うことですよね? >struct seiseki seito1, seito2[20] ここの箇所が分からないのですが seito2[20]の20というのは どうして20なのですか? NAMEだけではないので もっと大きな数字になるような気がするのですが… またseito1の方は どうして数字が何もないんですか? 考え違いをしているところを ご指摘して頂ければ幸いです。

  • C言語 構造体

    以前にも構造体について質問させていただきましたが、より自由度の高い処理が必要となりご質問させていただきます。 よろしくお願いいたします。 以前のものは入力する項目数(列),行数(行)が前提にあるものでした。 テキストファイルを読み込んで、 構造体としてデータを読み込みたいのですが、 今回は項目数が不定のものです。 a.txt ------------------------- あああ,いいい,ううう ------------------------- とあれば あああ いいい ううう とカンマ抜きで得たい。(3項目) 次回読み込んだとき、 a.txt ------------------------- abc,def,g,h,i,jk ------------------------- とあれば、 abc def g h i jk とカンマ抜きで得たい。(6項目) 以前のものは下記のような感じです。 FILE *fp; FILE *file; struct seiseki seito[20]; char buf[1024]; fp = fopen("aaa.txt", "r"); i=0; while( fgets(buf, sizeof(buf), fp) ){ struct seiseki tmp; sscanf(buf,"%d %s %s %d %d %d",&tmp.no,tmp.lname,tmp.fname,&tmp.val[0],&tmp.val[1],&tmp.val[2]); seito[i++] = tmp; } for(i = 0; i < 3; i++) { printf("%d / %s %s / %d / %d / %d / %d\n", seito[i].no,seito[i].lname,seito[i].fname, seito[i].val[0], seito[i].val[1], seito[i].val[2], seito[i].val[0] + seito[i].val[1] + seito[i].val[2]); }

  • 構造体の構造体 引数

    構造体の中の構造体の関数の引き渡し方法がわかりません。 下記ソースで試したのですが、うまくいきませんでした。 助言お願いいたします。 //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言語 list 構造体配列

    どうしてもこの問題がわからないので教えてください!  下記の構造体タグ「seiseki」を使って,表に示すデータをもつ構造体配列「list」を作成する.  関数に構造体配列「list」のアドレスを渡す.  関数で構造体ポインタ「*list」を利用して,一番点 数の高い者(1名限定)を調べ,その名前を表示する. struct seiseki{ char name[30]; int score; name score }; 表 佐藤 80 鈴木 75 田中 95 高橋 90

  • C言語 構造体でつまずいています

    以下、番号と点数を入力して構造体配列に入力し、番号に0が入力されたら、入力処理をやめ、平均点を表示するプログラムです。  今のコードでは、最初から番号に0を入力すると、0除算になりエラーになります。どうすれば良いのでしょうか? #include <stdio.h> #define MAX 50 //配列の要素数を定義 int count=0; //グローバル変数 struct data { //構造体の定義 int num; //メンバの宣言 int ten; }; void nyuryoku(struct data *); //プロトタイプ宣言 float heikin(struct data *); //プロトタイプ宣言 void main() { struct data score[MAX]; //構造体の宣言 printf("**学生番号/点数入力**\n"); printf("\n"); nyuryoku(score); //nyuryoku関数呼び出し printf("\n**以上%d名の平均点:%0.1f点**\n",count,heikin(score)); //heikin関数の戻り値表示 } //nyuryoku関数 //機能:構造体配列にデータを入力する void nyuryoku(struct data *pd) //仮引数pdに構造体ポインタが渡る { int i; for(i=0;i<MAX;i++){ printf("学生番号>>"); scanf("%d",&pd->num); if(pd->num==0){ //学生番号に0を入力するとループを抜ける break; } printf("点  数>>"); scanf("%d",&pd->ten); count++; //人数のカウント pd++; //構造体配列を一つずらす } } //heikin関数 //機能:構造体配列の点数の平均を計算、戻り値として返す float heikin(struct data *pd) //仮引数pdに構造体ポインタが渡る { int i; int sum=0; float ave=0; for(i=0;i<MAX;i++){ if(pd->num==0){ break; } else{ sum+=pd->ten; //点数を加算 pd++; } } ave=(float)sum/count; //平均値を求める return(ave); //平均値を戻り値として返す }

  • C言語について教えてください。

    名前、身長、体重をメンバとする構造体オブジェクトを要素とする配列を宣言・定義する。 (1)名前、身長、体重を構造体オブジェクトのメンバに格納する関数 (2)平均身長を計算する関数 (3)平均体重を計算する関数 をそれぞれ定義し、その関数の機能を確認するプログラムを作成する。 構造体オブジェクトの各メンバは以下の値をもつとする。 Name Height(cm) Weight(kg) Tom 174.2 72.3 Jerry 152.3 49.2 Spike 168.6 84.8 ただし、平均身長と平均体重は呼び出し元の関数(関数main())で表示する。 また(2)(3)については、生徒の人数が変更されても処理できる関数を作成する。 [実行結果の例] 平均身長:165.0cm 平均体重: 68.0kg [ヒント] 構造体の配列でまとめられたデータから平均身長あるいは平均体重を計算する関数 <返却値型><関数名>(構造体の配列の受け渡しに対応した仮引数の宣言、生徒の人数) この問題について教えてください。 下のプログラムは自分でつかりかけたプログラムです。 #include <stdio.h> #include <string.h> struct student { char name[6]; double height; double weight; }; struct student set_student(char *n, double h, double w) { struct student ss; strcpy(&ss.name[0], n); ss.height = h; ss.weight = w; return ss; } int main(void) { struct student seito[3]; seito[0] = set_student("Tom", 174.2, 72.3); seito[1] = set_student("Jerry", 152.3, 49.2); seito[2] = set_student("Spike", 168.6, 84.8); return 0; } (2)(3)計算の計算する関数を定義し、表示させる方法がよく分かりません。具体的に教えてもらえませんか。よろしくお願いします。

  • C言語構造体についてです。

    C言語、π=PI 3.14159265で構造体を用いてmensekiを呼び出して 半径と面積を計算して出力するプログラムです。下の空白を埋めてもらえますか? /* 構造体のプログラム */ #include <stdio.h> #include <math.h> #define PI 3.14159265 struct Data { /* 半径rと面積areaをdoubleで宣言 */ }; void menseki(struct ... 構造体のポインタを引数とする ){ /* 面積を計算する際に構造体のアドレスから計算する */ circle->area=PI* .....; } main(){ struct Data example[2]; //構造体配列 int i; /* 半径rを構造体配列を用いて2例入力する */ /* 2例の各々について mensekiを呼び出して 半径と面積を計算して出力する */ } よろしくお願いします。

  • C言語 構造体配列 list

    プログラミングでこの問題がわからないので教えてください! 下記の構造体タグseisekiを使って,表に示すデータをもつ構造体配列listを作成する. 構造体配列listを利用して,一番点数の高い 者を探し,その名前を表示する. struct seiseki{ char name[30]; int score; name score }; 表 佐藤 80 鈴木 75 田中 95 高橋 90

  • C言語

    よろしくお願いします。  下記の構造体タグ「seiseki」を使って,表に示すデータをもつ構造体配列「list」を作成する.  関数に構造体配列「list」のアドレスを渡す.  関数で構造体ポインタ「*list」を利用して,一番点 数の高い者(1名限定)を調べ,その名前を表示する. struct seiseki{ char name[30]; int score; name score }; 表 佐藤 80 鈴木 75 田中 95 高橋 90

  • C言語の構造体について

    構造体を勉強している所なのですが変数をまとめられるのは分かりましたがどのサイトを見てもいまいち使い所がわかりません。 struct test { int a; int b; int c; }testtest; testtest.a = 0; testtest.b = 1; testtest.c = 2; 例えば上記のような構造体を作成するとします。 私の見たサイトでは構造体で宣言はまとめられても初期化する事はできないと書いてありました。 下記のように変数を普通に宣言&初期化するよりも手間がかかってしまっていると思うのですが私の考えが及ばない何か別の使い方または処理が早くなったりする事があるのでしょうか?。 int a = 0; int b = 1; int c = 2;

専門家に質問してみよう