- ベストアンサー
C言語の成績表示プログラムでセグメンテーション違反が発生する理由とは?
- C言語初心者の方が作成した成績表示プログラムで、人数分の生徒の出席番号と点数を入力し、ソートして表示するという処理を行っています。
- しかし、人数分の入力が終わった後にセグメンテーション違反が発生してしまいます。
- 今回の質問では、なぜセグメンテーション違反が発生するのかと、それを修正するための添削を求めています。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
#3です。#5さんのコードでも解決しないとのことなのであなたのコードにprintfを少々つけたコードを載せますので実行してください。 手入力が面倒なので使っていたNOINPUTFLAGを放置してます。"#define NOINPUTFLAG 1"にすれば適当に値をぶち込みます。 #if~#endifの部分はNOINPUTFLAGが0の時コンパイル時にあなたのコードと全く同じになるので変化はありません。 今後も何かエラーが出る場合はprintfなどで自分が何をしているのか確認してください。 ///////////////////////////////////////////// #include <stdio.h> #define MAXDATA 10000 #define NOINPUTFLAG 0 //main()の型はintなのでそう宣言する int main() { int stnum[MAXDATA],point[MAXDATA],mem; int n,j,k,i,tmp,tmps; printf("生徒数に1または10000を超える値を入れるとエラーになります\nもちろん数字以外の値もダメです\n"); //バッファオーバーフローですので場合によっては検知できません、1の方はjの初期化に注目 printf("生徒数を入力してください。"); scanf("%d",&mem); if(mem<=0){ do{ printf("もう一度生徒数を入力してください。"); scanf("%d", &mem); }while(mem<=0); } for(i=0;i<mem;i++){ //NOINPUTFLAGが0のとき何も変化はありません #if NOINPUTFLAG point[i]=i; stnum[i]=i; #else printf("%d人目の生徒の点数を入力してください。\n",i+1); scanf("%d", &(point[i])); printf("%d人目の出席番号を数字で入力してください。\n",i+1); scanf("%d", &(stnum[i])); #endif } //NOINPUTFLAGが0のとき何も変化はありません #if NOINPUTFLAG printf("入力は省略しました\n"); #endif for(i=0;i<mem-1;i++){ j=i; } printf("この時点でi=%d, j=%d, k=undefined。でもまだ配列にアクセスなし\n",i,j); for(k=i+1;k<mem;k++){ if(point[j]>point[k]){j=k;} } printf("i+1(=%d)とmem(=%d)の大小を比べるとバブルソートを意図したと思われる処理は・・・ できたとしてもpoint[%d]は値が与えられてたっけ?\n",i+1,mem,i+1); tmp=point[j]; point[j]=point[i]; point[i]=tmp; printf("point[%d]とpoint[%d]を入れ替えました\n",i,j); for(k=i+1;k<mem;k++){ if(stnum[j]>stnum[i]){j=k;} } printf("同じく。\ni+1(=%d)とmem(=%d)の大小を比べるとバブルソートを意図したと思われる処理は・・・\n",i+1,mem); tmps=stnum[j]; stnum[j]=stnum[i]; stnum[i]=tmps; printf("stnum[%d]とstnum[%d]を入れ替えました\n",i,j); for(i=0;i<mem;i++){ printf("%d番の点数は%d点です。", stnum[i],point[i]);//改変:nはiだとのことだったので } return 0;//int型の返り値 }
その他の回答 (5)
- KEIS050162
- ベストアンサー率47% (890/1879)
入力した順(ソートなし)、出席番号順、得点順表示のサンプルを作ってみました。 手入力で10000件というのも大変なので、最大は100にしました。 ソートはもっと良い方法はいくらでもありますが、取りあえず、これでも出来ます。 #include <stdio.h> #define MAXDATA 100 int main(void) { int stnum[MAXDATA], point[MAXDATA], mem; int i,j,tmp,tmps; printf("生徒数を入力してください。"); scanf("%d",&mem); while (mem<=0){ printf("もう一度生徒数を入力してください。"); scanf("%d", &mem); } for (i=0; i<mem; i++ ) { printf("%d人目の出席番号を数字で入力してください。\n",i+1); scanf("%d", &(stnum[i])); printf("%d人目の生徒の点数を入力してください。\n",i+1); scanf("%d", &(point[i])); } // Input Order printf( "Input Oder \n" ); for ( i = 0 ; i < mem ; i++ ) { printf( "出席番号 %3d : 得点 %3d\n", stnum[ i ],point[ i ] ); } // Studend Number Order for ( i = 0 ; i < mem ; i++ ) { tmp = point[i]; tmps = stnum[i]; for ( j = i; j < mem ; j++ ) { if (stnum[j] < tmps ) { point[ i ] = point[ j ]; stnum[ i ] = stnum[ j ]; point[ j ] = tmp; stnum[ j] = tmps; tmp = point[ i ]; tmps = stnum[ i ]; } } } printf( "Student Number Order \n" ); for ( i = 0 ; i < mem ; i++ ) { printf( "出席番号 %3d : 得点 %3d\n", stnum[ i ],point[ i ] ); } // Score Order for ( i = 0 ; i < mem ; i++ ) { tmp = point[i]; tmps = stnum[i]; for ( j = i; j < mem ; j++ ) { if (point[j] > tmp ) { point[ i ] = point[ j ]; stnum[ i ] = stnum[ j ]; point[ j ] = tmp; stnum[ j] = tmps; tmp = point[ i ]; tmps = stnum[ i ]; } } } printf( "Score Order \n" ); for ( i = 0 ; i < mem ; i++ ) { printf( "出席番号 %3d : 得点 %3d\n", stnum[ i ],point[ i ] ); } return( 0 ); }
お礼
ありがとうございます。つくっていただいたサンプルと自分のプログラムを見比べて修正点を見つけたいと思います。
- yelser
- ベストアンサー率72% (8/11)
#3のものですが、修正後のコードはあくまで「意味のわかる」です。 悪いところは他にもありますが、memにいろんな値を入れて試してみてください。
お礼
ご指摘ありがとうございます。これを参考にしながら修正をしていきたいと思います。
- yelser
- ベストアンサー率72% (8/11)
なんだかfor文をわかっていない気が ・・・と言うか何がしたいのかを理解してない気が。 一応出席番号と点数は関連があるという前提のもと、意味のわかるソースにしました。 気持ち悪いのでiや\nも一部修正してます。 これが意図したものかは知りません。 インデントをつけるために全角の半角が入ってるのでそのままコピペではできません。 //////////////以下ソース////////////////// #define _CRT_SECURE_NO_WARNINGS //一部コンパイラで必要 #include <stdio.h> #define MAXDATA 10000 int main(){ int stnum[MAXDATA],point[MAXDATA],mem; int j,tmp,tmps; printf("生徒数を入力してください。\n"); scanf("%d",&mem); while(mem<=0){ printf("もう一度生徒数を入力してください。\n"); scanf("%d", &mem); } for(int i=0;i<mem;i++){ printf("%d人目の生徒の点数を入力してください。\n",i+1); scanf("%d", &(point[i])); printf("%d人目の出席番号を数字で入力してください。\n",i+1); scanf("%d", &(stnum[i])); } for(int i=0;i<mem-1;i++){ j=i;printf("j=i;を実行しました!\n"); for(int k=i+1;k<mem;k++){ if(point[i]>point[k]){ j=k;printf("j=k;を実行しました!\n"); tmp=point[k]; point[k]=point[i]; point[i]=tmp; tmps=stnum[k]; stnum[k]=stnum[i]; stnum[i]=tmps; } } } for(int i=0;i<mem;i++){ printf("%d番の点数は%d点です。", stnum[i],point[i]); } printf("出席番号は関係なかったです!\n"); return 0; }
- honor
- ベストアンサー率35% (25/71)
>printf("%d番の点数は%d点です。", stnum[n],point[n]); このnはなんでしょうか。
お礼
変数の割り当てを見てみます。アドバイスありがとうございます。
補足
打ち間違いです。nではなくiです。
- Tacosan
- ベストアンサー率23% (3656/15482)
for(i=0;i<mem-1;i++){ j=i; } for(k=i+1;k<mem;k++){ if(point[j]>point[k]){j=k;} } tmp=point[j]; point[j]=point[i]; point[i]=tmp; for(k=i+1;k<mem;k++){ if(stnum[j]>stnum[i]){j=k;} } のあたりで何をしたいのかさっぱりわからない. 例えば for(i=0;i<mem-1;i++){ j=i; } の結果 i や j がどんな値になるか理解できていますか?
お礼
アドバイスありがとうございます。確かに理解が足りないかもしれません。指摘されたところを中心に全体を検討してみます。
お礼
御礼がだいぶ遅れてしまってすいません。本当に助かりました。ありがとうございます!