ページ 11

構造体にデータを入力してバブルソートで並び変えて出力する方法

Posted: 2013年5月20日(月) 20:10
by ケイ
C言語を勉強して1年ちょっとになるのですが、どうもポインタの使い方が
苦手です。成績データを、番号・名前・点数と構造体に入力して、0を選ぶと番号の小さい順に
1を選ぶと点数の低い順にバブルソートし出力するプログラムなのですが、セグメンテーション違反になってしまいます。
おそらく、関数へのポインタ参照の仕方がめちゃくちゃなのだと思いますが、関数へ入る為の条件を格納するscanfの辺りで
エラーがでています。そのため、デバックの意味でprintfを挟んでみました。それぞれ"test1" "test2" "test3"を表示するか試してみたのですが
test1すらはいらずにセグメンテーション違反になってしまいます。

また、名前空間は可変長のためメモリアロケートしています。
プログラムがあまり大きくないと判断したため、構造体データが2件以上の時の、メモリ解放(free)はまだ書いていません。

ポインタの使い方や参照の仕方等、不適切なところがあったら教えてください。
学校の課題で期限は明日までです(-_-;)

環境はLinux のCent OS で
コンパイラは確かgcc です。

お願いします!

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HMAX 20
#define BMAX 30
#define TRUE  1
#define FALSE 0


typedef struct seiseki{
        char number[4];
        char *name;
        int  score;
}SEISEKI;

void sortcheck(SEISEKI *p,int i);
int numbersort(SEISEKI *p,int i);
int scoresort(SEISEKI *p,int i);
void printData(SEISEKI *p,int i);

int main(void){

        SEISEKI a[HMAX];
	SEISEKI *p;
        char bufmax[BMAX];
	int j;
        int i=0;
        int k=0;
        int sum;
        double ave;


        printf("番号を入力してください >");
        scanf("%s",&a[i].number);

        sum = 0;
        while(i<HMAX && a[i].number[0] != '$'){
                printf("\n");
                printf("名前を入力してください >");
                scanf("%s",bufmax);

                a[i].name =(char *)malloc(strlen(bufmax)+1);
                if(a[i].name == NULL){
                        printf("error");
                        exit(1);
                }
                strcpy(a[i].name,bufmax);

                printf("\n");
                printf("点数を入力してください >");
                scanf("%d",&a[i].score);
                printf("\n");

                sum += a[i].score;
                i++;

                printf("番号を入力してください  >");
                scanf("%s",&a[i].number);
        }

	if(i==1){
		ave = 0;
                ave = (double)sum / i;
                printf("\n番号 名前 点数\n");
                for(k=0;k<i;k++){
                        printf("%s  %s  %d\n",a[k].number,a[k].name,a[k].score);
		}   
		 printf("平均点は%.2lfです\n",ave);
                for(j=0;j<i;j++){
                	free(a[j].name);
                }
	}
        else if(i>=2){
		sortcheck(a,i);
		printData(a,i);
	}
	else{
                printf("データ未入力です\n");
	}
}

void sortcheck(SEISEKI *p ,int i){

	int k;
	int flg1,flg2;
	int input;

	flg1 = TRUE;
	flg2 = TRUE;

	printf("\n");
	printf("表示順をきめてください\n");
	printf("番号の低い順に表示する場合は0を\n");
	printf("点数の低い順に表示する場合は1を入力してください >");

	scanf("%d",&input);
	
	for(k = i;k > 1 && flg1 == TRUE && flg2 == TRUE; k--){
                if(input == 0){
		printf("test1");
		numbersort(p,k);
		}
	        else if(input == 1){
		flg2 = scoresort(p,k);
		}
		else{
		printf("入力値が正しくありません\n");
		exit(1);
		}
	}
}

int numbersort(SEISEKI *p ,int i){

	int k;
	int n;
	int temp;
	int flg1 = FALSE;

	printf("test2");
	for(k = 0; k < i; k++,p++){
		if(n=strcmp(p->number,(p+1)->number) > 0){
			temp = *p->number;
			*p->number = *(p+1)->number;
			*(p+1)->number = temp;
			flg1 = TRUE;
		}
	}
	return flg1;
}

int scoresort(SEISEKI *p , int i){

	int k;
	int n;
	int temp;
	int flg2 = FALSE;

	for(k = 0; k < i; k++,p++){
		if(p->score > (p+1)->score){
			temp = p->score;
			p->score = (p+1)->score;
			(p+1)->score = temp;
			flg2 = TRUE;
		}
	}

	return flg2;
}

void printData(SEISEKI *p,int i){

	int k;

	for(k=0;k < i; k++,p++){
	printf("test3");
	}
}

Re: 構造体にデータを入力してバブルソートで並び変えて出力する方法

Posted: 2013年5月20日(月) 21:06
by みけCAT

コード:

scanf("%s",&a[i].number);
この部分(2箇所)のscanfの使い方が間違っています。

コード:

scanf("%s",a[i].number);
としてください。

Re: 構造体にデータを入力してバブルソートで並び変えて出力する方法

Posted: 2013年5月21日(火) 01:16
by かずま
バブルソートでは隣同士を比較しますが、
比較の回数は、データの個数より 1つ少ないはずです。

Re: 構造体にデータを入力してバブルソートで並び変えて出力する方法

Posted: 2013年5月21日(火) 08:58
by non
構造体全部を交換しなくて良いのかな?