• ベストアンサー

整数型配列と2次元文字型配列の入れ替え方

以下のプログラムを実行結果のように作りたいのですがexchange_numberの中身の書き方(配列の入れ替え方)が分らないので教えて下さい。 #include<stdio.h> #define M 10 #define N 5 void sort_score(int score_cpy[M]); int linear_search(int score_cpy[M],int key); void exchange_number(int order[M],char number[M][N]); int no; int main(void) { int i,number[M][N],score[M],score_cpy[M],order[M]; printf("人数を入力して下さい:"); scanf("%d",no); ("学生番号と平均点を入力して下さい。"); for(i=0;i<M;i++){ printf("学生番号:"); scanf("%s",&number[i][N]); printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<=M;i++) score_cpy[i]=score[i]; sort_score(score_cpy); for(i=0;i<M;i++){ order[i]=linear_search(score_cpy,score[i]); } exchange_number(order,number); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++) printf("学生番号 :%s %d点\n",number[i],score_cpy[i]); return 0; } void sort_score(int score_cpy[M]) { int i,j,score; for(j=0;j<no-1;j++){ for(i=no-1;i>0;i--){ if(score_cpy[i-1]<score_cpy[i]){ score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int score_cpy[M],int key) { int i; for(i=0;i<no;i++){ if(score_cpy[i]==key){ return i; } } return -1; } void exchange_number(int order[M],char number[M][N]) {?} ちなみに実行結果は以下の通りです。 人数を入力して下さい:10 学生番号と平均点を入力して下さい。 学生番号:y3051 得点:85 学生番号:y3052 得点:65 学生番号:y3053 得点:75 学生番号:y3054 得点:63 学生番号:y3055 得点:95 学生番号:y3056 得点:68 学生番号:y3057 得点:80 学生番号:y3058 得点:90 学生番号:y3059 得点:83 学生番号:y3060 得点:70 得点の高い順に並び替えて表示します 学生番号:y3055 95 点 学生番号:y3058 90 点 学生番号:y3051 85 点 学生番号:y3059 83 点 学生番号:y3057 80 点 学生番号:y3053 75 点 学生番号:y3060 70 点 学生番号:y3056 68 点 学生番号:y3052 65 点 学生番号:y3054 63 点 プログラム中で間違えがありましたら指摘して頂けると幸いです。それで良いお待ちしております。

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

  • ベストアンサー
回答No.5

 いやいや、ひねくれた例題ですね。間違い箇所が多く見られ、実際にまだコンパイルはされていないようですよね。レポートは明日までとのことですので参考に...。  ここでの一番の問題は、なぜ「void exchange_number(int order[M],char number[M][N]);」関数を作らなければいけないかの疑問です。結果は、ソート降順に行われることから、次の for() ループでは  order[i]=linear_search(score_cpy,score[i]); の学生番号順にソート順番が何番であるかを求めるのではなく、  order[i]=linear_search(score,score_cpy[i]); のソート結果に対して何番の学生番号が該当するのかのプログラム内容とならなければなりません。事例ではわざとかく乱させて、ご要望の関数を作らないとさも答えが出ないような内容になっています。例題は考えられています。  回答は、平均点が重なってもきちんと表示されるように「 signed char flag[M];」を追加してみました。したがって、要望の関数は不要です。とりあえず、動くかどうか試してみてください。 #include<stdio.h> #define M 10 #define N 8 // 余裕を持たせましょう。 void sort_score(int score_cpy[]); int linear_search(int key, int score[], signed char flag[]); int no; int main(void) { int i,score[M],score_cpy[M],order[M]; char number[M][N]; signed char flag[M]; printf("人数を入力して下さい:"); scanf("%d",&no); ("学生番号と平均点を入力して下さい。"); for(i=0;i<no;i++) { printf("学生番号:"); scanf("%s",number[i]); printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<no;i++) { score_cpy[i]=score[i]; flag[i] = 0; } sort_score(score_cpy); for(i=0;i<no;i++) order[i]=linear_search(score_cpy[i], score, flag); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++) printf("学生番号 :%s %d点\n", number[order[i]],score_cpy[i]); return 0; } void sort_score(int score_cpy[]) { int i,j,score; for(j=0;j<no-1;j++) { for(i=no-1;i>j;i--) { if(score_cpy[i-1]<score_cpy[i]) { score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int key,int score[], signed char flag[]) { int i; for(i=0;i<no;i++) { if(key == score[i] && flag[i] == 0) { flag[i] = -1; // 重複を回避する break; } } return i; }

その他の回答 (4)

回答No.4

またまたすみません。実行結果を見ると学生番号にはyという文字が入っているので文字列ですね。ということはnumberは文字型配列にしないといけませんね。Mが学生数で、Nは学生番号の最大数だったのでしょうか? プログラムだけ見て実行結果に注意をしていませんでした。ごめんなさい。 でも、前回のサンプルプログラムが参考になると思います。これを参考に自分で少し考えてみることをお勧めします。

freezeb
質問者

補足

こちらの説明不足で何度もお答えさせてしまい申し訳ありません。 この回答の通り、numberは学生を表す文字型配列でMが学生数、Nが学生番号の最大数です。この場合で考えると、文字型なので1文字ずつ入れ替えるように作るんですかね?明日までに、レポートとして提出しなければならないので、出来れば前回のサンプルプログラムを書きなおして欲しいのですが・・・宜しくお願い致します。

回答No.3

すみません。Mは使用しないといっておいて、サンプルにはMを残してしまいました。このままでも動くと思いますが、MはNにするつもりでした。

回答No.2

このプログラムに関して3点ほど質問があります。 質問1 なぜ学生番号を%Sで読み込む必要があるのか? 質問2 なぜnumber配列は2次元である必要があるのか? 質問3 define定義されているMとNはどんな意味を持つのか? で、次のように勝手に解釈して作ったプログラムを以下に示します。 いろいろ突っ込みが入るかもしれませんが参考にして下さい。 解釈1 学生番号は%dで読み込む 解釈2 numberは1次元配列にする 解釈3 Mは使用しない。Nは学生の最大人数 <プログラム> オリジナルから修正を加えた部分はコメントを入れておきました。 #include<stdio.h> #define M 10 #define N 5 void sort_score(int score_cpy[M]); int linear_search(int score_cpy[M],int key); void exchange_number(int order[M],int number[M]); //numberはint型です。 int no; int main(void) { int i,number[M],score[M],score_cpy[M],order[M];//numberを2次元配列にするのはなぜ? printf("人数を入力して下さい:"); scanf("%d",&no);//&がない printf("学生番号と平均点を入力して下さい。");//printfがない for(i=0;i<no;i++){ //no回くりかえせばいい printf("学生番号:"); scanf("%d",&number[i]);//%dでよいのでは?Nしか確保していないのにNにいれてはダメ //そもそも2次元配列にする意味が解らない printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<=M;i++) score_cpy[i]=score[i]; sort_score(score_cpy); for(i=0;i<M;i++){ order[i]=linear_search(score_cpy,score[i]); } exchange_number(order,number); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++) printf("学生番号 :%d %d点\n",number[i],score_cpy[i]);//numberはintなので%sでなく%d return 0; } void sort_score(int score_cpy[M]) { int i,j,score; for(j=0;j<no-1;j++){ for(i=no-1;i>0;i--){ if(score_cpy[i-1]<score_cpy[i]){ score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int score_cpy[M],int key) { int i; for(i=0;i<no;i++){ if(score_cpy[i]==key){ return i; } } return -1; } void exchange_number(int order[M],int number[M]){ int i; int tmp[M]; //numberを全てコピーして for(i=0;i<M;i++){ if(order[i]==-1) break; tmp[i]=number[i]; } //該当箇所にセット for(i=0;i<M;i++){ if(order[i]==-1) break; number[order[i]]=tmp[i]; } }

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

学生番号と試験点数をメンバーに持つ構造体の配列を定義します。 読み込んだデータを前項の配列に格納します。 配列の要素(試験点数)どうしを比較し、点数の降順になるよう、 必要に応じて配列の要素(学生番号と試験点数)を入れ替えます。

freezeb
質問者

補足

申し訳ないのですが、C言語については初心者並みですので、exchange_numberの中身を書いて頂けるとうれいしいのですが・・・お願い致します。

関連するQ&A

  • 学生番号が正常に出力されていません

    この質問と同じ質問が他に1つありますが、何分急いでいますのでご了承下さい。以下のプログラムで実行結果が、入力された得点に対応する学生番号を得点の高い順に並び替えて出力したいのです。得点の方は正常に出力されているのですが学生番号がおかしな出力になっています。しかし、どこをどう直せば良いか分かりません。なので分かりやすく説明お願い致します。 #include<stdio.h> #define M 10 #define N 5 void sort_score(int score_cpy[M]); int linear_search(int score_cpy[M],int key); void exchange_number(int order[M],char number[M][N]); int no; int main(void) { int i,score[M],score_cpy[M],order[M]; char number[M][N]; printf("人数を入力して下さい:"); scanf("%d",&no); ("学生番号と平均点を入力して下さい。"); for(i=0;i<no;i++){ printf("学生番号:"); scanf("%s",&number[i][N]); printf("得点:"); scanf("%d",&score[i]); } for(i=0;i<=M;i++){ score_cpy[i]=score[i]; } sort_score(score_cpy); for(i=0;i<M;i++){ order[i]=linear_search(score_cpy,score[i]); } exchange_number(order,number); printf("\n\n得点の高い順に並び替えて表示します\n\n"); for(i=0;i<no;i++){ printf("学生番号 :%s %d点\n",number[i],score_cpy[i]); } return 0; } void sort_score(int score_cpy[M]) { int i,j,score; for(j=0;j<no-1;j++){ for(i=no-1;i>0;i--){ if(score_cpy[i-1]<score_cpy[i]){ score=score_cpy[i-1]; score_cpy[i-1]=score_cpy[i]; score_cpy[i]=score; } } } } int linear_search(int score_cpy[M],int key) { int i; for(i=0;i<no;i++){ if(score_cpy[i]==key){ return i; } } return -1; } void exchange_number(int order[M],char number[M][N]) { int i,temp[M]; for(i=0;i<M;i++){ if(order[i]==-1)break; temp[i]=number[i][N]; } for(i=0;i<M;i++){ if(order[i]==-1)break; number[order[i]][N]=temp[i]; } } 人数を入力して下さい:10 学生番号:y3051 得点:85 学生番号:y3052 得点:65 学生番号:y3053 得点:75 学生番号:y3054 得点:63 学生番号:y3055 得点:95 学生番号:y3056 得点:68 学生番号:y3057 得点:80 学生番号:y3058 得点:90 学生番号:y3059 得点:83 学生番号:y3060 得点:70 得点の高い順に並び替えて表示します 学生番号 : 95点 学生番号 :y3051y3052y3053y3054y3055y3056y3057y3058y3059y3060 90点 学生番号 :y3052y3053y3054y3055y3056y3057y3058y3059y3060 85点 学生番号 :y3053y3054y3055y3056y3057y3058y3059y3060 83点 学生番号 :y3054y3055y3056y3057y3058y3059y3060 80点 学生番号 :y3055y3056y3057y3058y3059y3060 75点 学生番号 :y3056y3057y3058y3059y3060 70点 学生番号 :y3057y3058y3059y3060 68点 学生番号 :y3058y3059y3060 65点 学生番号 :y3059y3060 63点

  • 一次元配列についてです

    配列matを以下の様に宣言し、連続した3つの数の和を順に書き出すプログラムを作成しています。が、条件式とprintfの出力の仕方が全く解りません。この二つが解る方、教えて頂けませんか。 #include <stdio.h> int main(void) { int i,mat[10]={5,3,8,2,7,1,10,4,9,6}; for(i=0;i<10;i++) { } printf("\n"); return(0); }

  • 2次元配列

    大学の課題なのですが 10×10の2次元配列に、平面のビットパターンが入っているとする(0と1の整数が入っているとする)。左右反転して出力しなさい。 という問題で、自分は以下のプログラムを作ったのですが、うまくうごいてくれません。だれか間違いを指摘していただけないでしょうか。 よろしくお願いします。 #include<stdio.h> int main(void) { int i,j; int data[10][10]={0,1}; for(i=0;i<10;i++){ for(j=0;j<10;j++){ printf("%3d",data[10-i][10-j]); } printf("\n"); } return(0); }

  • 2次元配列の基礎について

    とある問題で 下に示す行列x,yの積を求めるプログラムを作成せよ。 x=[123][456] y=[15] [53][81] 問題の意味が自分にはよくわからないのですが この場合 123*15;123*53;123*81 456*15;456*53;456*81 の解答を表示させればいいのでしょうか? 自分でやったら以下のようになりましたが、これだと456*53と123*15と0しか表示されません。どこをどう直せば宜しいでしょうか? ご教授お願いしますm(__)m #include <stdio.h> int main(void){ int ma[3][1] ={{123},{456}}; int mb[3][1] ={{15},{53},{81}}; int mc[3][1] ={0}; int i; int j; for(i=0;i <= 3;i++){ for(j=0;j <= 1;j++){ mc[i][j] =ma[i][j] * mb[i][j]; } } for(i=0;i <= 3;i++){ for(j=0;j <= 1;j++){ printf("%3d",mc[i][j]); putchar('\n'); } } return 0; }

  • ポインタ配列

    "one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列の文字列を、ASCIIコード順に並べ変えようと思ったのですが、 もうどこが間違っているかさえわからないぐらいになってしまいました。 まだまだはじめたばかりなもので、わからないことだらけなんで、 できるだけわかりやすい説明おねがいします。 関数の引数に問題があるのじゃないかと思ったのですが、 何かいいアドバイスありましたら、お願いします。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; /* ポインタのポインタの定義 */ char **pp=x; char k[100]; char *p=k; int i,t,a,b,c,d; a=0; /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++) { for(t=1;t<10;t++) { a=strmp(*(pp+i),*(pp+t)); if(a<0) { cpy(p,*(pp+i) ); cpy(*(pp+i),*(pp+t) ); cpy(*(pp+t),p); } } } for(i=0;i<10;i++) { printf("%s ,",x[i]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; for(i=0;*(x+i)==*(y+i);i++) { if( *(x+i)=='\0') { return 0; } } return *(x+i)-*(y+i); } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { int i; for(i=0;*(b+i)!='\0';i++) { *(a+i)=*(b+i); } *(a+i)='\0'; }

  • 二次元配列についての質問です。

    1~9の数字を9,8,7,6,5,4,3,2,1と出力するようなプログラムを作成しているのですが、解りません。一応ある程度(以下のプログラム)出来たのですが、何処をどう直せばいいか解りません。何処を直せばいいか教えて下さい。 #include<stdio.h> int main(void){ int i,mt[3][3]= {{1,2,3}, {4,5,6}, {7,8,9}}; for(i=0;i<3;i++){ printf("%3d",mt[i][i]); } printf("\n"); return(0); }

  • C++ の多次元配列なんですが

    int i,j; int (*p)[2][3]; int *x; int a[2][3] = {{1,2,3},{4,5,6}}; p = &a; x = &a[0][0]; for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", (*p)[i][j]); } } printf (" | "); for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", *(x + ( i * 3 + j )) ); } } printf (" | "); for ( i = 0; i < 6; i++ ) { printf (" %d", *(x + i) ); } これで大丈夫でしょか?

  • ダブルポインタで2次元配列を作成

    2次元配列を作り、そのアドレスなどを表示させましたが どうもおかしいです。 3行5列の配列で、3本のポインタ配列がありますが、 その配列のアドレスがかぶっているのです。 まずはコンパイルしてみてください。 #include<stdio.h> main() { int i; int k; int y=1; int **p; p=(int **)malloc(sizeof(int *)*3); for(i=0;i<=2;i++) { *(p+i)=(int *)malloc(sizeof(int)*5); } for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ p[i][k]=(i+k)*y; } y=y*10; } for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ printf("%4d",*(*(p+i)+k)); } printf("\n"); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",p+i); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",&p+i); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",*(p+i)); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p+2)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p+2)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p+2)+i); } printf("\n"); for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ printf("%p\n",&*(*(p+i)+k)); }} free(p); return 0; } どこがかぶっているかと申しますと、 for(i=0;i<=4;i++) { printf("%p\n",&*(p)+i); } と for(i=0;i<=4;i++) { printf("%p\n",&*(p+1)+i); } と for(i=0;i<=4;i++) { printf("%p\n",&*(p+2)+i); } です。 これが同じアドレスになるはずは論理的にありえないことです。 VC++2008無料バージョンです。 よろしくお願いいたします。

  • 初心者向け配列の処理、本に載っているコードの意味が少しわかりません。

    入門者向けの本に載っていたコードなんですが、1行だけ どういった処理を行っているのか理解できないところがありました。 よろしくお願いします。 /* 5人の学生の点数を読み込んで60点以上の学生の一覧を表示 */ #include <stdio.h> #define NUMBER 5 /* 人数 */ int main(void) {    int i;    int snum = 0; /* 合格者の人数 */    int tensu[NUMBER]; /* NUMBER人の学生の点数 */    int succs[NUMBER]; /* 合格者リスト(合格者の添字を格納) */    puts("点数を入力してください。");    for (i = 0; i < NUMBER; i++) {       printf("%2d番:", i + 1);       scanf("%d", &tensu[i]);       if (tensu[i] >= 60)          succs[snum++] = i; /*ここがどういった処理になっているのかわからないです。 */    }    puts(" 合格者一覧 ");    puts("------------");    for (i = 0; i < snum; i++)       printf("%2d番(%3d点)\n", succs[i] + 1, tensu[succs[i]]);    return (0); }

  • c言語のmalloc関数と2次元配列について

    ・mallocとreallocのAPPを作成しています、下記は単純化しました。 「質問-1」 ・while(1){...以下を無効にした場合、正常に終了します。 ・有効にして、最初に999を入力した場合、エラー表示されます。 ・この理由が分かりません。 「質問-2」 ・有効にして、初期数値(例えば11)を入力の場合、正常表示されます ・続けて数値(例えば15)を入力した場合、エラー表示されます。 ・この理由が分かりません。 ***************************************************************  #include <stdio.h>  #include <stdlib.h>  void MylnOut(void);  int **map;  int X=10,Y=10,i,j; //************************************************************** // MAIN //************************************************************** int main() {  char str[64]={""};  char *s="変更数値を入力(999で終了).... "; /* 2次元配列確保と初期表示 */  map=(int **)malloc(sizeof(int *)*X);  for(i=0;i<X;i++)   map[i]=(int *)malloc(sizeof(int)*Y);  MylnOut(); /* 変更数値入力 */ // while(1){ //  printf(s); //  gets(str); //  X=atoi(str); //  if(X==999) break; /* 領域変更と表示 */ //  map=(int **)realloc(map,sizeof(int *)*X); //  for(i=0;i<X;i++) //   map[i]=(int *)realloc(map[i],sizeof(Y)); //  MylnOut(); // } /* 領域開放 */   for(i=0;i<X;i++) free(map[i]);   free(map);   return 0; } //************************************************************** // 入力・表示 //************************************************************** void MylnOut(void) {  for(j=0;j<Y;j++)   for(i=0;i<X;i++) map[i][j]=55;   for(j=0;j<Y;j++){    for(i=0;i<X;i++) printf("%3d",map[i][j]);    printf("\n");   } }

専門家に質問してみよう