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

構造体(姓、身長、体重、年齢)を作成して身長で昇順ソートする。
教えて下さい。今は下のようになっています。


#include <stdio.h>

typedef struct Student{
char sur[100];
double hei,wei;
int age;
}Student;

int main(void)
{
Student stu[5],tmp;

int i,j;
int n,m;

printf("五人分のデータを入力してください\n");

for(i = 1;i <= 5;i++){
printf("%d人目姓、身長、体重、年齢をスペース区切りで入力後Enter\n",i);
scanf("%s %lf %lf %d",&stu[i].sur,&stu[i].hei,&stu[i].wei,&stu[i].age);
}
printf("ソートのキー (1:身長 , 2:体重) : ");
scanf("%d",&n);
printf("\n\n");

switch(n){
case 1:
for(i = 1;i <= 5;i++){
for(j = i + 1;j <= 5 ;j++){
if(stu[i].hei > stu[j].hei){
tmp = stu[i];
stu[i] = stu[j];
stu[j] = tmp;
}
}
}
for(i =1;i <= 5;i++){
printf("%s %.1lf %.1lf %d\n",stu[i].sur,stu[i].hei,stu[i].wei,stu[i].age);
}


case 2:
for(i = 1;i <= 5;i++){
for(j = i + 1;j <= 5 ;j++){
if(stu[i].wei > stu[j].wei){
tmp = stu[i];
stu[i] = stu[j];
stu[j] = tmp;
}
}
}
for(i =1;i <= 5;i++){
printf("%s %.1lf %.1lf %d\n",stu[i].sur,stu[i].hei,stu[i].wei,stu[i].age);
}


}
return 0;
}

A 回答 (3件)

問題点1:配列の添え字は0から開始します。


従って、stu[5]の配列は、0~4が有効な添え字です。
OKの範囲はstu[0]~stu[4]です。
あなたの場合、i=5でstu[i]を参照するとき、範囲外のアクセスの為、
プログラムが暴走します。
それを踏まえて、
for(i = 1;i <= 5;i++){
printf("%d人目姓、身長、体重、年齢をスペース区切りで入力後Enter\n",i);
scanf("%s %lf %lf %d",&stu[i].sur,&stu[i].hei,&stu[i].wei,&stu[i].age);
}
を修正すると
for (i = 0; i < 5; i++) {
printf("%d人目姓、身長、体重、年齢をスペース区切りで入力後Enter\n",
i+1);
scanf("%s %lf %lf %d", &stu[i].sur, &stu[i].hei, &stu[i].wei,
&stu[i].age);
}
になります。
他も、同様に修正してください。

問題点2:
switch case文で
case1 :の最後にbreak;を入れてください。
そうしないと、case 2:の方も実行してしまいます。

問題点3:
問題点というほどではありませんが、#1の方も言っているように、
ソート結果を印字する処理は、switch caseが終わってからにすると、
1っ箇所で済みます。
    • good
    • 1

例えばこんなカンジ。



/* ここから */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Student {
 char sur[100];
 double hei, wei;
 int age;
} Student;

int cmp_hei(const void *p, const void *q) {
 return ((Student*)p)->hei - ((Student*)q)->hei;
}

int cmp_wei(const void *p, const void *q) {
 return ((Student*)p)->wei - ((Student*)q)->wei;
}

int main(void) {
 Student stu[5];
 char tmp[128];
 int n;

 puts("五人分のデータを入力してください\n");

 for (int i = 0; i < 5; i++) {
  printf("%d人目姓、身長、体重、年齢をスペース区切りで入力後Enter\n", i+1);
  scanf("%127[^\n]%*c", tmp);
  strcpy(stu[i].sur, strtok(tmp, " "));
  stu[i].hei = strtod(strtok(NULL, " "), NULL);
  stu[i].wei = strtod(strtok(NULL, " "), NULL);
  stu[i].age = strtol(strtok(NULL, " "), NULL, 10);
 }
 printf("ソートのキー(1:身長, 2:体重): ");
 scanf("%1[^\n]%*c", tmp);
 n = strtol(tmp, NULL, 10);
 printf("\n\n");

 switch(n) {
 case 1:
  qsort(stu, 5, sizeof(Student), cmp_hei);
  break;
 case 2:
  qsort(stu, 5, sizeof(Student), cmp_wei);
  break;
 }

 for (int i = 0; i < 5; i++) {
  printf("%s %.1lf %.1lf %d\n", stu[i].sur, stu[i].hei, stu[i].wei, stu[i].age);
 }

 return EXIT_SUCCESS;
}

/* ここまで */

昇順・降順のアルゴリズム考えるよりも、C言語の標準ライブラリ(stdlib.h)に入ってるqsort関数を使った方が早い。

qsort:
https://www.cc.kyoto-su.ac.jp/~yamada/ap/qsort.h …
「C言語に関する質問です」の回答画像3
    • good
    • 0

細かくコードを読む気はないですが…



>Student stu[5],tmp;
で、確保した配列で添え字に指定可能に範囲はどこからどこまででしょう?
その上で…
>for(i = 1;i <= 5;i++){
は安全な範囲に入ると思いますか?
さらに…
>for(j = i + 1;j <= 5 ;j++){
でiが5の時にループが回ると思いますか?
# まぁソートが正常に完了しているのならば最後のは不要なのでループ回らなくてもいいのですが。

switch()~case文でbreakしなかったらどうなると思いますか?
# 結果の表示は一緒なのですからswitchから抜けた後の表示でいいんじゃないですかね?
    • good
    • 0

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

このQ&Aを見た人はこんなQ&Aも見ています