アプリ版:「スタンプのみでお礼する」機能のリリースについて

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]);
}
}

A 回答 (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型の返り値
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/12/03 11:55

入力した順(ソートなし)、出席番号順、得点順表示のサンプルを作ってみました。


手入力で10000件というのも大変なので、最大は100にしました。

ソートはもっと良い方法はいくらでもありますが、取りあえず、これでも出来ます。



#include <stdio.h>
#define MAXDATA 100

int main(void) {
intstnum[MAXDATA],point[MAXDATA],mem;
inti,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 );
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/07/31 10:50

#3のものですが、修正後のコードはあくまで「意味のわかる」です。


悪いところは他にもありますが、memにいろんな値を入れて試してみてください。
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/07/31 10:46

なんだか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;
}
    • good
    • 0

>printf("%d番の点数は%d点です。

", stnum[n],point[n]);

このnはなんでしょうか。

この回答への補足

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

補足日時:2013/07/28 01:00
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/07/28 01:46

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 がどんな値になるか理解できていますか?
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/07/28 01:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!