C言語初心者です。 構造体のバブルソートについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さいとう

C言語初心者です。 構造体のバブルソートについて

#1

投稿記事 by さいとう » 10年前

こんばんわ!
現在、C言語勉強中の者です。

C言語の市販の参考書(明解・C言語入門編)を買いほぼ独学で進めていたのですが、構造体のソートで行き詰ってしまいました。

下記のプログラムを、
「身長順でソートするか名前の昇順でソートするかを選べるようにする」問題です。
int型のソートは理解できたのですが、文字列のソートが上手くいきません。

コード:

 

#include <stdio.h>
#include <string.h>

#define NUMBER  5
#define NAME_LEN 64

typedef struct{
  char  name[NAME_LEN] ;
  int   height ;/*名前*/
  float weight ;/*身長*/
  long  schols ;/*奨学金*/
  } Student ;
  
/*xおよびyが指す学生を交換*/

void swap_Student(Student *x, Student *y)
  {
  Student temp =*x;
  *x = *y ;
  *y = temp ;
  }
  
 void sort_by_height(Student a[], int n)
 {
     int i, j ;
     for(i=0;i<n-1;i++)
     {
       for(j=n-1;j>i;j--)
       if(a[j-1].height > a[j].height)
         swap_Student(&a[j-1],&a[j]) ;
     }
  }
  
int main (void)
{
  int i;
  Student std[]={
  {"Sato",   178, 61.2, 80000},
  {"Sanaka", 175, 62.5, 73000},
  {"Takao",  173, 86.2, 0},
  {"Mike",   165, 72.3, 70000},
  {"Masaaki",179, 77.5, 70000},
  };
  
  for(i=0;i<NUMBER;i++)
   printf("%-8s %6d%6.1f%7ld\n",
      std[i].name, std[i].height,std[i].weight,std[i].schols);
      
      sort_by_height(std,NUMBER) ;
      
      printf("\n身長順にソートしました\n");
      for(i=0;i<NUMBER;i++)
         printf("%-8s %6d%6.1f%7ld\n",
      std[i].name, std[i].height,std[i].weight,std[i].schols);
      
      return 0 ;
      }
それに、選べるようにメニューを追加するには他に関数を作るべきでしょうか?
色々な方のやり方も学びたいので、コメント等で解説して頂けるとありがたいです。

どなたかお願い致します。

box
記事: 2002
登録日時: 15年前

Re: C言語初心者です。 構造体のバブルソートについて

#2

投稿記事 by box » 10年前

コード:

#include <stdio.h>
#include <string.h>

#define NUMBER    (5)
#define NAME_LEN (64)

typedef struct{
    char  name[NAME_LEN];     /* 名前 */
    int   height;             /* 身長 */
    float weight;             /* 体重 */
    long  schols;             /* 奨学金 */
} Student;

/*xおよびyが指す学生を交換*/

void swap_Student(Student *x, Student *y)
{
    Student temp = *x;
    *x = *y;
    *y = temp;
}

void sort_by_height(Student *a)
{
    int i, j;

    for (i = 0; i < NUMBER - 1; i++) {
        for (j = i + 1; j < NUMBER; j++) {
            if (a[i].height > a[j].height) {
                swap_Student(&a[i], &a[j]);
            }
        }
    }
}

void sort_by_name(Student *a)
{
    int i, j;

    for (i = 0; i < NUMBER - 1; i++) {
        for (j = i + 1; j < NUMBER; j++) {
            if (strcmp(a[i].name, a[j].name) > 0) {
                swap_Student(&a[i], &a[j]);
            }
        }
    }
}

void printStudent(Student *a)
{
    int i;

    for (i = 0; i < NUMBER; i++) {
        printf("%-8s %6d%6.1f%7ld\n",
            a[i].name, a[i].height, a[i].weight, a[i].schols);
    }
}

int main(void)
{
    Student std[] = {
        { "Sato",    178, 61.2, 80000 },
        { "Sanaka",  175, 62.5, 73000 },
        { "Takao",   173, 86.2,     0 },
        { "Mike",    165, 72.3, 70000 },
        { "Masaaki", 179, 77.5, 70000 },
    };

    printStudent(std);

    sort_by_height(std);
    printf("\n身長順に並べ替えました\n");
    printStudent(std);

    sort_by_name(std);
    printf("\n名前順に並べ替えました\n");
    printStudent(std);
    return 0;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。 構造体のバブルソートについて

#3

投稿記事 by みけCAT » 10年前

さいとう さんが書きました:int型のソートは理解できたのですが、文字列のソートが上手くいきません。
どのような方法を試したのですか?
さいとう さんが書きました:それに、選べるようにメニューを追加するには他に関数を作るべきでしょうか?
色々な方のやり方も学びたいので、コメント等で解説して頂けるとありがたいです。
メニューの処理がある程度長くなるなら、関数を分けたほうがいいかもしれません。

コード:

#include <stdio.h>
#include <string.h>

#define NUMBER  5
#define NAME_LEN 64

typedef struct{
	char  name[NAME_LEN] ;
	int   height ;/*名前*/
	float weight ;/*身長*/
	long  schols ;/*奨学金*/
} Student ;

/* 学生用の比較関数(x>yなら正の値、x==yなら0、x<yなら負の値を返す) */
typedef int (*compare_func_ptr)(Student* x, Student* y);

/* 学生の名前を比較 */
int compare_height(Student *x, Student *y)
{
	if (x->height > y->height)
		return 1;
	if (x->height < y->height)
		return -1;
	return 0;
}

/* 学生のnameを比較 */
int compare_name(Student *x, Student *y)
{
	return strcmp(x->name, y->name);
}

/*xおよびyが指す学生を交換*/

void swap_Student(Student *x, Student *y)
{
	Student temp =*x;
	*x = *y ;
	*y = temp ;
}

/* 第三引数で比較関数を指定する */
void sort(Student a[], int n, compare_func_ptr compare)
{
	int i, j ;
	for(i=0;i<n-1;i++)
	{
		for(j=n-1;j>i;j--)
			if(compare(&a[j-1], &a[j]) > 0)
				swap_Student(&a[j-1],&a[j]) ;
	}
}

/* メニューを出力し、比較関数を選択させる */
compare_func_ptr select_compare_function(const char** func_name)
{
	/* メニューの候補 */
	static struct{
		const char *name; /* 比較関数の名前 */
		compare_func_ptr func; /* 比較関数 */
	} menu[] = {
		{"身長順", compare_height},
		{"名前順", compare_name},
		{NULL, NULL} /* 終了マーク */
	};
	int count = 0;
	int i;
	int select;
	/* メニューの数を数える */
	while (menu[count].name != NULL) count++;
	do {
		/* メニューを表示 */
		puts("比較関数を選んでください。");
		for (i = 0; i < count; i++)
			printf("%d: %s\n", i, menu[i].name);
		/* プロンプトを表示 */
		printf("> ");
		fflush(stdout);
		/* 入力を読み込み、失敗したら終了 */
		if (scanf("%d", &select) != 1)
			return NULL;
	} while(select < 0 || count <= select); /* 不正な入力なら再入力させる */
	/* 選ばれた比較関数の情報を返す */
	*func_name = menu[select].name;
	return menu[select].func;
}

int main (void)
{
	int i;
	Student std[]={
		{"Sato",   178, 61.2, 80000},
		{"Sanaka", 175, 62.5, 73000},
		{"Takao",  173, 86.2, 0},
		{"Mike",   165, 72.3, 70000},
		{"Masaaki",179, 77.5, 70000},
	};
	compare_func_ptr func;
	const char *func_name = "";

	for(i=0;i<NUMBER;i++)
		printf("%-8s %6d%6.1f%7ld\n",
			std[i].name, std[i].height,std[i].weight,std[i].schols);

	func = select_compare_function(&func_name);
	if (func == NULL)
		return 1;

	sort(std,NUMBER, func) ;

	printf("\n%sにソートしました\n", func_name);
	for(i=0;i<NUMBER;i++)
	printf("%-8s %6d%6.1f%7ld\n",
		std[i].name, std[i].height,std[i].weight,std[i].schols);

	return 0 ;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る