C言語の成績表示プログラムでセグメンテーション違反が発生する理由とは?

このQ&Aのポイント
  • C言語初心者の方が作成した成績表示プログラムで、人数分の生徒の出席番号と点数を入力し、ソートして表示するという処理を行っています。
  • しかし、人数分の入力が終わった後にセグメンテーション違反が発生してしまいます。
  • 今回の質問では、なぜセグメンテーション違反が発生するのかと、それを修正するための添削を求めています。
回答を見る
  • ベストアンサー

c言語 成績表示のプログラムです。

c言語初心者です。課題で出た問題で、生徒の人数、その後出席番号と点数を入れ、ソートしてから表示するプログラムなのですが、人数分打ち終わったあとにセグメンテーション違反になります。添削とともになぜそうなるのか教えてもらえると幸いです。 include <stdio.h> #define MAXDATA 10000 main() { int stnum[MAXDATA],point[MAXDATA],mem; int n,j,k,i,tmp,tmps; printf("生徒数を入力してください。"); scanf("%d",&mem); if(mem<=0){ do{ printf("もう一度生徒数を入力してください。"); scanf("%d", &mem); }while(mem<=0); } for(i=0;i<mem;i++){ printf("%d人目の生徒の点数を入力してください。\n",i+1); scanf("%d", &(point[i])); printf("%d人目の出席番号を数字で入力してください。\n",i+1); scanf("%d", &(stnum[i])); } 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;} } tmps=stnum[j]; stnum[j]=stnum[i]; stnum[i]=tmps; for(i=0;i<mem;i++){ printf("%d番の点数は%d点です。", stnum[n],point[n]); } }

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

  • ベストアンサー
  • yelser
  • ベストアンサー率72% (8/11)
回答No.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型の返り値 }

yuu05270409
質問者

お礼

御礼がだいぶ遅れてしまってすいません。本当に助かりました。ありがとうございます!

その他の回答 (5)

  • KEIS050162
  • ベストアンサー率47% (890/1879)
回答No.5

入力した順(ソートなし)、出席番号順、得点順表示のサンプルを作ってみました。 手入力で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 ); }

yuu05270409
質問者

お礼

ありがとうございます。つくっていただいたサンプルと自分のプログラムを見比べて修正点を見つけたいと思います。

  • yelser
  • ベストアンサー率72% (8/11)
回答No.4

#3のものですが、修正後のコードはあくまで「意味のわかる」です。 悪いところは他にもありますが、memにいろんな値を入れて試してみてください。

yuu05270409
質問者

お礼

ご指摘ありがとうございます。これを参考にしながら修正をしていきたいと思います。

  • yelser
  • ベストアンサー率72% (8/11)
回答No.3

なんだか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)
回答No.2

>printf("%d番の点数は%d点です。", stnum[n],point[n]); このnはなんでしょうか。

yuu05270409
質問者

お礼

変数の割り当てを見てみます。アドバイスありがとうございます。

yuu05270409
質問者

補足

打ち間違いです。nではなくiです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

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 がどんな値になるか理解できていますか?

yuu05270409
質問者

お礼

アドバイスありがとうございます。確かに理解が足りないかもしれません。指摘されたところを中心に全体を検討してみます。

関連するQ&A

  • 助けてください! c言語のプログラムです。

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define KAMOKU_SUU 5 #define AVE_INDEX KAMOKU_SUU typedef struct { char name[32]; int scor[KAMOKU_SUU]; int mean; } STUDENT; int round(double d) { if (d < 0) return (int)(d-0.5); else return (int)(d+0.5); } #define ARRAY_OF(a) (sizeof (a) / sizeof (a[0])) int main(int argc,char* argv[]) { int i, j,k, n; int nStudets; double avrg[KAMOKU_SUU + 1]; double stdv[KAMOKU_SUU + 1]; STUDENT *mem; char buff[80]; if (argc < 2) { printf("!パラメータ不足\n"); return 1; } nStudets = atoi(argv[1]); mem = (STUDENT*)malloc(sizeof (STUDENT) * nStudets); if (mem == NULL) { printf("!アロケーション\n"); return 2; } memset(avrg, 0, sizeof (avrg)); memset(stdv, 0, sizeof (stdv)); printf("生徒 %d 名分の成績を入力してください:\n", nStudets); for (k = 0; k < nStudets; k++) { printf("%d 人目の点数と名前 > ", k + 1); gets(buff); strcpy(mem[k].name, strtok(buff," ")); mem[k].mean = 0; for (j = 0; j < KAMOKU_SUU; j++) { int i = mem[k].scor[j] = atoi(strtok(NULL," \n")); mem[k].mean += i; avrg[j] += i; stdv[j] += i * i; } mem[k].mean = round(mem[k].mean * 1.0 / KAMOKU_SUU); } for(j = 0; j < KAMOKU_SUU; j++) { avrg[AVE_INDEX] += avrg[j]; stdv[AVE_INDEX] += stdv[j]; avrg[j] = avrg[j] / nStudets; stdv[j] = sqrt(stdv[j] / nStudets - avrg[j] * avrg[j]); } n = nStudets * KAMOKU_SUU; avrg[AVE_INDEX] = avrg[AVE_INDEX]/ n; stdv[AVE_INDEX] = sqrt(stdv[AVE_INDEX] / n) - (avrg[AVE_INDEX] * avrg[AVE_INDEX]); printf("\n成績表\n"); printf("# NAME"); for (i = 1; i <= KAMOKU_SUU; ++i) printf(" #%d ", i); printf("MEAN\n"); for (k = 0; k< nStudets; k++) { printf("%d %10s",k+1,mem[k].name); for (j = 0; j < KAMOKU_SUU; j++) { printf(" %3d",mem[k].scor[j]); } printf(" %3d\n",mem[AVE_INDEX].mean); } printf("------------------------------------\n"); printf(" %10s","average"); for(j = 0; j < ARRAY_OF (avrg);j++) { printf(" %3.0f",avrg[j]); } printf("\n"); printf(" %10s","st.dev."); for ( j = 0; j < ARRAY_OF (stdv); j++) { printf(" %3.0f",stdv[j]); } printf("\n"); printf("正常終了\n"); return 0; }  実行してもできません。原因が全く分かりません。 お願いします。 修正してくださるとありがたいです。

  • C言語 エラー表示 break の位置が誤っている(関数 main ) 

    #include<stdio.h> int main(void){ int n,i,j,k; char c='*'; printf("正の整数:"); scanf("%d",&n); if(n>0){ for(i=1;i<=n;i++){ printf("%d",i); for(j=1;j<=n+1-i;j++){ if(j==1){ if(i-1>0){ for(k=i-1;k>0;k--){ printf(" "); } } } printf("%c",c); } printf("\n"); } } break; return 0; } これをコンパイルすると「break の位置が誤っている(関数 main )」と表示されるのですが何でですか? 困ってます↓

  • c言語のプログラムで行列の積を計算する

    指定された行・列数(それぞれ10以下とする)の行列 X, Y の積 Z = X × Y を求めるプログラムを作成せよ.行列の要素はすべて整数とする. このプログラムで行と列の成分を入力するときに、1列になってしまうのですがどうしたらちゃんと入力できますか? int main(void) { double A[10][10]; double B[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } }

  • c言語のプログラミングについて聞きたいのですが

    自分は課題で「10人分の名前と点数を入力して降順に並び替える」というプログラムを作ろうとしているのですが、なかなかうまくいきません。一応↓の形までできたのですがなぜか数字が変になります。 どうしてか教えていただけないでしょうか。 #include<stdio.h> int main(void) {     int i,j;     int tensu[10][3];     char namae[10][6]; for(i=0;i<10;i++){ printf("名前の入力>>"); scanf("%s",&namae[i]); printf("点数の入力>>"); scanf("%d",tensu[i]); } printf("名前   点数\n"); for(j=0;j<10;j++) { printf("%s ",&namae[j]); printf("%10d\n",tensu[j]); } return 0; } それとポインタ?みたいなのもよく理解できず、点数で降順にしたあとに点数を使って名前を並び替えるのかなと思うのですがそれもよくわかりません。 どなたか教えてください

  • C言語プログラムについての質問です。下のプログラムがなぜ降順で出力され

    C言語プログラムについての質問です。下のプログラムがなぜ降順で出力されるのか分かりません。何回も確認したのですが、不等号の向きが昇順になっているのに、どうして降順になるのかが理解できません。 ご教授お願いします。   #include <stdio.h>   #define MAX 10000   int main (int argc, const char * argv[]) { int N,data[MAX],d[MAX],j,k,w,x,a; x=0; a=1; do{printf("学生番号を入力してください\n");    scanf("%d",&N);   if(N!=0){printf("得点を入力してください\n"); scanf("%d",&data[N]);}x++;} while(N!=0);   for(j=0; j<x;j++){ d[j]=data[j];} for(j=0; j<x;j++)      {for(k=0;k<x-j-1;k++){   if(d[k]>d[k+1]){ w=d[k]; d[k]=d[k+1]; d[k+1]=w;}}} printf("昇順での整列結果\n"); for(j=x-1;j>0;j--){ printf("%d位 %d点\n",a,d[j]);a++;} return 0; }

  • C言語 プログラミング 行列演算

    下記のプログラムのおかしい点と解決法を教えてください。 コンパイルは通りますがうまく動きません。。 #include<stdio.h> #define MAX 500 int main(void){ int matrA[MAX][MAX],matrB[MAX][MAX],matrC[MAX][MAX],l,m,n,i,j,k; printf("lとmを入力してください:"); scanf("%d",&l); scanf("%d",&m); printf("行列Aを入力してください"); for(i=0;i<l;i++){ printf(">"); for(j=0;l<m;j++){ scanf("%d",&matrA[i][j]); } printf("\n"); } printf("nを入力してください(m = %d):",m); scanf("%d",&n); printf("行列Bを入力してください"); for(i=0;i<m;i++){ printf(">"); for(j=0;j<n;j++){ scanf("%d",&matrB[i][j]); } printf("\n"); } printf("C=\n"); for(i=0;i<l;i++){ for(j=0;j<n;j++){ for(k=0;k<m;k++){ matrC[i][j]+=matrA[i][k]*matrB[k][j]; } printf("%d",matrC[i][j]); } printf("\n"); } }

  • C言語で多項式の割り算のプログラム

    C言語で多項式の割り算のプログラムを作っているんですができません 以下プログラム #include <stdio.h> int main(void) { int m,m2,i,i2,j,k; int a[1000],b[1000],c[1000],d[1000]; puts("何次の多項式ですか?"); printf("1つめ:"); scanf("%d",&m); printf("2つめ:"); scanf("%d",&m2); puts("1つめの多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%d",&a[i]); } puts("2つめの多項式の係数を入力してください。"); for(i=m2;i>=0;i--){ scanf("%d",&b[i]); } k=m-m2; c[k]=a[m]/b[m2]; printf("商の次数は%dです。\n",k); j=m2-1; for(k=m-m2;k>=0;k--){ for(i=m-1;i>=0;i--){ d[i]=a[i]-c[k]*b[j]; a[i]=d[i]; c[k-1]=a[i]/b[m2]; j=j-1; } printf("%d ",c[k]); } return(0); } 原因は  for(k=m-m2;k>=0;k--){ for(i=m-1;i>=0;i--){ d[i]=a[i]-c[k]*b[j]; a[i]=d[i]; c[k-1]=a[i]/b[m2]; j=j-1; } printf("%d ",c[k]); } で、iのfor文が終わった後kのfor文が更新され、またiのfor文が始まったときにa[i]が最初に入力された値に変わってしまうからだと思うんですが直せません 誰か教えてくださいm(_ _)m

  • プログラムについて(C言語)

    #include<stdio.h> int main() { int i,n,total; for(;;){ /* 無限ループ*/ printf("整数n?"); /* nの値の表示 */ scanf("%d",&n); /* ifとbreakを使った終了判定 */ if(n<0)break; total=1; for(i=1;i<=n;i++){ printf("i=%d ",i); total*=i; /* total←total*i(階乗の計算) */ } printf("total=%d\n",total); /* totalの値(結果)の表示 */ } printf("Thanks\n"); /* 終了メッセージの表示 */ return(0); } これは階乗を求めるプログラムなのですが、i++ではなくi--をつかって求める場合 どのように変更すればよいでしょうか? for(i=1;i<=n;i++){ あたりをいろいろ弄ってみたのですが、求めてる結果は得られませんでした

  • C言語でのプログラム

    全対最短経路(フロイドのアルゴリズム)のプログラムを作成したんですが、以下のようなメッセージが出てしまい、どこが悪いのかさっぱりわかりません。どなたかご教授願えないでしょうか? <プログラム> #include<stdio.h> #define NC 999 /* It should be large enough. */ #define N 5 void floyd(int, int [][], int [][], int [][]); int W[N][N] = { { 0, 1, NC, 1, 5 }, { 9, 0, 3, 2, NC }, { NC, NC, 0, 4, NC }, { NC, NC, 2, 0, 3 }, { 3, NC, NC, NC, 0 }, }; int P[N][N]; int D[N][N]; main() { floyd(N, W, D, P); } void floyd(int n, int W[][], int D[][], int P[][]) { int i, j, k; for(i=0;i<n;i++){ for(j=0;j<n;j++){ P[i][j] = 0; } } for(i=0;i<n;i++){ for(j=0;j<n;j++){ D[i][j] = W[i][j]; } } for(k=0;k<n;k++){ for(i=0;i<n;j++){ for(j=0;j<n;j++){ if(D[i][k]+D[k][j]<D[i][j]){ P[i][j] = k; D[i][j] = D[i][k] + D[k][j]; } } } } printf("?nall pairs of the shortest pathes:?n"); for(i=0;i<n;i++){ for(j=0;j<n;j++){ printf("%3d ", D[i][j]); } printf("?n"); } printf("?n"); } <エラーメッセージ> In function `floyd': :30: error: invalid use of array with unspecified bounds :36: error: invalid use of array with unspecified bounds :43: error: invalid use of array with unspecified bounds :44: error: invalid use of array with unspecified bounds :45: error: invalid use of array with unspecified bounds :54: error: invalid use of array with unspecified bounds

  • c言語で行列の積の値を求める

    行列の成分を入力した後に、 入力された行列は X = 1 2 3 4 5 6 7 8 9 10 11 12 Y = 1 5 2 6 3 7 4 8 のように表示して、(上の数字は適当です。) 行列 X と行列 Y の積を求めて結果を表示するプログラムが作りたいのですが、上手く表示できなくて困っています。 #include <stdio.h> int main(void) { double A[10][10]; double B[10][10]; double C[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } } この後にどうすればいいのか教えてください。 よろしくお願いします。

専門家に質問してみよう