ページ 1 / 1
構造体
Posted: 2007年5月20日(日) 21:06
by ☆
またまたやってきました。
構造体ついての質問です。。
「学生の名前と国語、英語、数学の3科目の点数、合計点を保存するためのデータ構造を設計しなさい型名は StdData とすること。また、キーボードから人数と、人数分のそれらのデータを StdData 型の配列に格納し、配列の要素のデータを順に出力するプログラムを作成しなさい。」
こんな問題です。
こんな実行結果になります。
「
The number of students: 7
1: kim 82 57 74
2: otsuki 78 92 65
3: atsumi 88 64 83
4: hachisu 63 74 69
5: miyazawa 76 57 79
6: yokomori 95 89 81
7: nakamiti 73 64 92
name | jpn eng math| sum
kim | 82 57 74 | 213
otsuki | 78 92 65 | 235
atsumi | 88 64 83 | 235
hachisu | 63 74 69 | 206
miyazawa | 76 57 79 | 212
yokomori | 95 89 81 | 265
nakamiti | 73 64 92 | 229 」
Re:構造体
Posted: 2007年5月20日(日) 21:10
by ☆
私の作ったプログラムです。
まだ、合計がでてなかっtりと未完成なのですが・・・・・
#include <stdio.h>
struct stddata{
char student_name[100]; /*生徒の名前*/
int jpn; /*国語の点数*/
int eng; /*英語の点数*/
int math; /*数学の点数*/
};
void getdata(struct stddata *sp,char *name,int jpn,int eng,int math);
void printdata( struct stddata *sp );
int main( void ){
struct stddata student[20];
int i,n,jpn,eng,math;
char name[100];
printf( "The number of students:" );
scanf("%d",&n);
for(i=0;i<n;i++){
printf("%d:",i);
scanf("%s %d %d %d",name,&jpn,&eng,&math);
getdata(&name,jpn,eng,math); /* データ表示 */
}
for(i=0;i<n;i++){
printdata(&student);
}
return 0;
}
void getdata(struct stddata *sp,char *name,int jpn,int eng,int math){
strcpy(sp->student_name,name);
sp->jpn=jpn;
sp->eng=eng;
sp->math=math;
}
void printdata( struct stddata *sp ){
printf( "name | jpn eng math\n" );
printf( "%s %5d %4d %5d \n", sp->student_name,sp->jpn,sp->eng,sp->math);
}
ここで、getdataの引数の事でコンパイル時にエラーが出てしまいました。
どう違うんでしょうか??
御指導お願いします。
Re:構造体
Posted: 2007年5月20日(日) 21:20
by 管理人
まず、そのエラーについてだけ答えます。
コンパイルすると、エラーメッセージがでますよね?
そのエラーメッセージをみてもらったらわかりますけど、
1>.\○○.cpp(25) : error C2660: 'getdata' : 関数に 4 個の引数を指定できません。
こんなエラーがでるはずです。
ここで、4つの引数が指定できないのならこの関数の仕様はどうなっているのかなと思ってみます。
プロトタイプ宣言は
void getdata(struct stddata *sp,char *name,int jpn,int eng,int math);
こうなっています。
全部で5つ引数があるはずの関数に4つの引数を持たせて呼んでいるのでだめですよと言われているのです。
Re:構造体
Posted: 2007年5月20日(日) 21:24
by ☆
あ!!!はい。そうですね。
そのとおりです。
同じ関数を表してるのに引数のかずが5と4であってないですねぇ。
Re:構造体
Posted: 2007年5月20日(日) 21:36
by 管理人
どの辺までお答えいたしましょう??
もう出来そうですか?
また、
/* データ表示 */
と注釈してあるとことは表示するためのしょりではないですよね。
あと、構造体データを渡してやらなければなりませんね。
後nameに&がついているのはおかしいです。
配列nameを
「name」と書くと何を意味しますか?
Re:構造体
Posted: 2007年5月20日(日) 21:48
by 管理人
ちょっと以下の問題をやってみてください。
名前を入力させ、その情報を格納する関数を作ってみてください。
#include <stdio.h>
/*ここに名前を入力・格納する関数を書く*/
void main(){
char name[100];
/* ここで関数を呼ぶ */
printf("%s",name);
}
Re:構造体
Posted: 2007年5月20日(日) 21:56
by 管理人
ちょっと出かける用事があるので、先に答え書いておきますね。
#include <stdio.h>
void getname(char name[100]){
scanf("%s",name);
return ;
}
void main(){
char name[100];
getname(name);
printf("%s",name);
}
そして、配列の特定の要素をポインタを使って操作するには
#include <stdio.h>
void input(char *n){
*n='6';
return ;
}
void main(){
char name[100]="12345";
input(&name[2]);
printf("%s",name);
}
このようにします。
プログラムの意味がわかりますか?
お書きになったプログラムを急いで書き直してみました。
#include <stdio.h>
#include <string.h>
struct stddata{
char student_name[100]; /*生徒の名前*/
int jpn; /*国語の点数*/
int eng; /*英語の点数*/
int math; /*数学の点数*/
};
void getdata(struct stddata *sp,char *name,int jpn,int eng,int math);
void printdata( struct stddata sp );
int main( void ){
struct stddata student[20];
int i,n,jpn,eng,math;
char name[100];
printf( "The number of students:" );
scanf("%d",&n);
for(i=0;i<n;i++){
printf("%d:",i);
scanf("%s %d %d %d",name,&jpn,&eng,&math);
getdata(&student,name,jpn,eng,math); /* データ表示 */
}
printf( "\nname | jpn | eng | math\n" );
for(i=0;i<n;i++){
printdata(student);
}
return 0;
}
void getdata(struct stddata *sp,char *name,int jpn,int eng,int math){
strcpy(sp->student_name,name);
sp->jpn=jpn;
sp->eng=eng;
sp->math=math;
}
void printdata( struct stddata sp ){
printf( "%-10s | %3d | %3d | %3d\n", sp.student_name,sp.jpn,sp.eng,sp.math);
}
急いだので間違いがどこかにあるかもしれませんが、一応実行結果はうまくいきます。
試してみてください。
Re:構造体
Posted: 2007年5月21日(月) 11:42
by ☆
おはようございます★
寝ちゃいました。。。すみません。。
私まだ、管理人サンの書いていただいたやつみてないです!!!
もうちょっと待ってもらえますか???今、もうすぐでできそうなんですよ^^(笑)
勝手な勘違いかもしれないけど・・・・(笑)
また書き込みするので、その時、チェックしていただけますか??
Re:構造体
Posted: 2007年5月21日(月) 12:45
by 管理人
いえいえ、全然かまいませんよ、
しかし21:30に・・、寝るの早いですね^^;
後、答えを見ずに完成できたらそれに越した事はありません、頑張ってください☆
Re:構造体
Posted: 2007年5月21日(月) 17:54
by ☆
バイトでかなり疲れて・・・・(笑)
今日1ゲンからだったしぃ。。。
おそくなりました★
こんなのを作りました。実行はできたんですが、内容的にどうでしょうか??
チェックお願いします。
#include <stdio.h>
typedef struct{
char name[100];
int jpn;
int eng;
int math;
}StdData;
int getdata(StdData student_1[/url]);
void printdata(int n,StdData student_2[/url]);
int main(void){
StdData list[100];
int tensu;
tensu=getdata(list);
printdata(tensu,list);
return 0;
}
int getdata(StdData student_1[/url]){
int num,count;
printf("The number of students: ");
scanf("%d",&num);
for(count=0;count<num;count++){
printf("%d: ",count+1);
scanf("%s %d %d %d",student_1[count].name,&student_1[count].jpn,&student_1[count].eng,&student_1[count].math);
}
return num;
}
void printdata(int n,StdData student_2[/url]){
int kazoeru,sum;
printf(" name | jpn eng math|sum\n");
for(kazoeru=0;kazoeru<n;kazoeru++){
sum=student_2[kazoer[/url].jpn+student_2[kazoer[/url].eng+student_2[kazoer[/url].math;
printf("%10s | %3d %3d %3d |
%d\n",student_2[kazoer[/url].name,student_2[kazoer[/url].jpn,student_2[kazoer[/url].eng,student_2[kazoer[/url].math,sum);
}
}
見にくくて、ごめんんさぁーい。。お願いします。
Re:構造体
Posted: 2007年5月21日(月) 18:42
by 管理人
バイトお疲れ様です。
私も、新しいバイクを買う前は、毎日夜明けまでバイトをしていたので、よくわかります(_ _)
プログラムコードを拝見しましたけど、よいと思いますよ、特に間違っている箇所は無いと思います。
若干細かいところをいうと・・・。
①
見にくい^^;
>見にくくて、ごめんんさぁーい。。
そういえば初めて投稿してもらった時から微妙に字下げがおかしかったですよね^^;
Linux使ってるんでしたっけ?ってことはエディタはEmacsですか?
Emacsならそれぞれの行でTabキー押せば自動調整してくれるはずなんですけどねぇ><
例えばここ
int kazoeru,sum;
printf(" name | jpn eng math|sum\n");
for(kazoeru=0;kazoeru<n;kazoeru++){
sum=student_2[kazoer[/url].jpn+student_2[kazoer[/url].eng+student_2[kazoer[/url].math;
printf("%10s | %3d %3d %3d |
空白が
2
4
4
4
5
になってます。
4
4
4
8
8
の方が綺麗に見えると思います。
②
後、関数はなるべく最後にはreturn文を書きましょう。
int関数ならreturn 0;(あるいは他の数値)と、void関数なら最後にreturn ;と。
③
もっとも深刻なのが、エラー処理をしていない点。
例えばscanfで4つのデータをとってきていますが、スペースを空け忘れたり、4つ以外のデータが入力されたり、数値部分に文字が入力されてもそのままになっていますので、
バッファのデータが狂うかもしれません。
http://www.pc.uec.ac.jp/sp/hshrkw/edu/p ... e1-22.html
このへんscanfを使う危険性が書かれています。
getchar関数で1文字ずつ判定していけばエラー処理も綺麗に行えるでしょう。
しかし全体的に大きな間違いは無いと思います。
確かまだプログラムを始めて1年もたってないんでしたよね。
頑張っていらっしゃいますね、これからも頑張ってください☆
Re:構造体
Posted: 2007年5月21日(月) 18:52
by ☆
見にくいって言われちゃった(笑)
ですよねぇー!!!アタシ頑張りましたもん。。。
昨日とは見違えましたよね!!!
なるほど、return省略しない方がいいんですねぇー。
なんか学校だと先生が強制てきにしろ!!とか言うんですよ。。。
それで、するべきところとかがごっちゃになってしまって。。。
あと1つ質問なんですが、
これを今度、合計点の高い順にソートした結果を 出力するように修正する場合って。。。
どうすればいいんでしょうか?バブルソートを考えてるんですが・・・
void bubbleSort(int student_2[/url],int num){
int i,j;
for(i=num-1;i>=0;i--){
for(j=0;j<i;j++){
if(student_2[j].>student_2[j+1]){
swap(student_2[j].sum);
なんかこんなん形は作ったんですが・・・よくわからなくて・・・
Re:構造体
Posted: 2007年5月21日(月) 18:54
by Justy
>関数はなるべく最後にはreturn文を書きましょう
>void関数なら最後にreturn ;と
え? 今はそうなんですか?
好みもありますので何ともいえませんが、戻り値がないなら returnが無い方が
自然かな~と思ってました。
>エラー処理
エラー処理に関してはもういくつか。
StdDataの配列は 100個用意していますが、"The number of students"の入力で 101以上の
値が入力されたらヤバそうです。
又、ここの入力で数字が入力されるとは限らないので、その対処が必要ですね。
Re:構造体
Posted: 2007年5月21日(月) 19:02
by 管理人
あら・・voidの時はreturn文は書かない方がいいんでしょうか?
私が愛用していた入門書には全てreturnを書いた方がいいと書いてあったので、
ずっとそうしてきましたが、そうではなかったのですか。
ずっと今までそうしてきたので、関数の終わりに何もないと違和感を感じるようになりました^^;
プログラムのコードは短いに越した事は無いので、書かなくていいものは書かない方がいいかもしれないですね。
また、Justyさんのおっしゃる方法が一般的なのでしょうから、一般的な方法に合わせる方が可読性もあがると思いますし、
そちらに合わせた方がいいと思います。
すみませんでした(_ _|||)
Re:構造体
Posted: 2007年5月21日(月) 19:07
by Justy
あ、いや謝られれる必要は全然ないです。
こちらこそ変なところに突っ込んでしまって申し訳ないです。
最近の教科書とか授業は returnを推奨しているのかな、と思っただけなんで・・・。
>voidの時はreturn文は書かない方がいいんでしょうか?
基本的にはどっちでもいいんじゃないでしょうか。
あってもなくても問題ないですし。
>Justyさんのおっしゃる方法が一般的なのでしょうから
いやいや、そんなことありませんって(w
時々ものすごい勢いで偏ってるときがありますから。
Re:構造体
Posted: 2007年5月21日(月) 19:08
by 管理人
>これを今度、合計点の高い順にソートした結果を 出力するように修正する場合って。。。
>どうすればいいんでしょうか?
それには合計点を格納するための変数を構造体にもう一つ追加する必要がありますが、それはコードを拝見する限りは既に用意されているようですね。
バブルソートは簡単ですし、ウェブにサンプルが沢山ありますので、
それを見ながら実装してみてはいかがでしょうか。
http://www.ics.kagoshima-u.ac.jp/~fuchi ... -sort.html
http://www1.cts.ne.jp/~clab/hsample/Sort/Sort1.html
Re:構造体
Posted: 2007年5月21日(月) 19:12
by ☆
わかりました。ありがとうございます☆
できるだけ早く見違えてきますからーー!!!(笑)
Re:構造体
Posted: 2007年5月21日(月) 19:18
by 管理人
いやいや、私なんぞがJusty様のような神の領域にいらっしゃる人物に意見出来ない事はご存知の通りで(w
しかし、return文を書かない方が一般的だと聞いてなんとなくすっきりしました。
コードを短く書きたいのに余計なものを書く事に抵抗を感じていましたので。
>☆さん
もしバブルソートが出来たら他にある様々なソートを勉強してみるのもいいかもしれませんね。
私のHPにクイックソート解説アプリがありますので、もしよければクイックソートもこの際勉強してみてください。
Re:構造体
Posted: 2007年5月21日(月) 19:24
by 管理人
そういえばもう一つ。
メイン関数はintとvoidをよく見かけますが、
私の入門書には必ずint mainからはじまり、return 0で終われと書かれていました。
メイン関数にvoidを使うべきではないのでしょうか?
他のプログラムからこのプログラムを呼ぶ機会のないような状況ではどちらも関係無いように思うのですが。
Re:構造体
Posted: 2007年5月21日(月) 19:38
by ☆
管理人サンのHPのクイックソートは、以前とても念入りに勉強させていただきましたよ^^
大変分かりやすかったです☆
Re:構造体
Posted: 2007年5月21日(月) 20:24
by Justy
>return文を書かない方が一般的だと聞いてなんとなくすっきりしました
あー、一般的とまでは断定できません。
自分の周りではあまりいない、というだけで。
ひょっとしたら時流は returnを使う方に流れているのかもしれませんよ。
他の人の意見を聞いてみたいところです。
>メイン関数にvoidを使うべきではないのでしょうか?
結論から言えば、YESです。
このあたりはちょっとだけ複雑です。
Cの場合 main関数の型に関しては必ず以下の4つでなければなりません。
1 intを戻り値にして引数なし。
int main(void)
2 intを戻り値にして、2つに引数を持つ
int main(int, char *[/url])
3 1や 2と等価な方法
int main(int, char **)
typedef int int_t;
int_t main(int, char *[/url])
とか
4 1~3以外の処理系定義
なので、原則的には intが戻り値ではあるものの、4を適用した処理系では
voidなのかもしれませんし、極端な話 floatかもしれません。
ちなみに C++ではまたちょっと違いますが、intを戻り値とすることが基本となっています。
戻り値をホスト環境(OS)がどう見ているかにもよります。
ひょっとしたら 0以外を返したら、OSをシャットダウンしてしまう環境があるかもしれません。
そんなとき、戻り値を void型にしてしまって不定な値をホスト側が戻り値として
解釈されてしまったら・・・・。
まぁ、そんなわけで、原則である intを戻り値にしておけばほとんどの環境で
大丈夫だろうというわけです。
ただ、現実的には巷のメジャーな環境では 戻り値が voidであっても
何事もなかったかのように動いてはいるので、実装的には問題ないとは言えなくもないですが、
教える側としてはかなり難アリなのではないでしょうか。
Re:構造体
Posted: 2007年5月21日(月) 22:07
by 管理人
なるほど、今回も人のトピで私が勉強させてもらってしまいました。
ありがとうございますm(_ _)m
今まで引っかかっていた部分がはっきりしたので、すっきり出来ました。
誰かに返り値について答える機会があれば上記の事をふまえて発言したいと思います。
Re:構造体
Posted: 2007年5月22日(火) 00:09
by ☆
すごいハイテクな話になっていて・・・おじゃまかもしれませんが・・・
一応、念のために・・・御世話になったので御報告だけでも・・・聞いてください!!!
バブルソート使って、高い順に出力できました!!!!!!!
ホントに感動しました^^;
ホントにありがとうございました!!!!
Re:構造体
Posted: 2007年5月22日(火) 00:18
by 管理人
ただ引数と返り値は何にするかというだけの話ですので全くハイテクでもなんでもないんでお気になさらず^^;
バブルソート完成したのですね、よかったです☆
私は別に何もしていないので、☆さんの力ですよ♪
また何か躓いたら遠慮なくトピお立て下さいませm(_ _)m