3

これは、この質問のフォローアップです。

ポインターを使用して C で構造体をソートする

修正したコードを修正しました。ソートは機能していると思いますが、ポインターを正しく使用していないように感じます。printf ステートメントがコンソールに表示されず、コメントにラベルが付けられています。

私はCが初めてなので、これは明らかかもしれませんが、printステートメントが印刷されないときにデバッグする方法がわかりません。

現在のコンパイラ警告:

Q1.c: In function 'generate':
Q1.c:28: warning: implicit declaration of function 'time'
Q1.c:35: warning: implicit declaration of function 'dupe'
Q1.c: In function 'output':
Q1.c:61: warning: implicit declaration of function 'sort'
Q1.c: At top level:
Q1.c:68: warning: conflicting types for 'sort'
Q1.c:61: warning: previous implicit declaration of 'sort' was here
Q1.c: In function 'sort':
Q1.c:82: warning: implicit declaration of function 'deallocate'
Q1.c: At top level:
Q1.c:90: warning: conflicting types for 'deallocate'
Q1.c:82: warning: previous implicit declaration of 'deallocate' was here

コードは次のとおりです。

#include <stdio.h>
#include<stdlib.h>
#include<math.h>

int SIZE = 10;
static char c[] = "------------------------------\n";

struct student{
    int id;
    int score;
};

struct student* allocate(){
     /*Allocate memory for ten students*/
     struct student *s = malloc(SIZE* sizeof*s);
     /*return the pointer*/
     return s;
}

void generate(struct student* students){
    /*Generate random ID and scores for ten students, ID being between 1 and 10, scores between 0 and 100*/
    srand((unsigned int)time(NULL));
    int id[SIZE];
    int y;

    for (int i = 0; i < SIZE; i++){
        do{
        y = rand() % SIZE + 1;
        } while(dupe(id, i, y));
        id[i] = y;
    }

    for (int j = 0; j < SIZE; j++){
        students[j].id = id[j];
        students[j].score = rand() % 101;
        printf("ID: %d\tScore: %d\n", students[j].id, students[j].score);
    }
}

int dupe(int id[], int SIZE1, int i){
    for (int x = 0; x < SIZE1; x++){
        if(id[x] == i)
            return 1;
    }
    return 0;
}

void output(struct student* students){
     /*Output information about the ten students in the format:
              ID1 Score1
              ID2 score2
              ID3 score3
              ...
              ID10 score10*/
    sort(students);
    printf("post sort students.\n %s", c);
    for(int x = 0; x < SIZE; x++){
        printf("ID: %d\tScore: %d\n", students[x].id, students[x].score); //print stmt not showing
    }
}

void sort(struct student* students){
    struct student *sd = allocate();

    struct student *stud;

    for(int i = 0; i < SIZE; i++){
        stud = &students[i];
        sd[stud->id -1] = *stud;
    }
    printf("sorted SD.\n %s", c);
    for(int x = 0; x < SIZE; x++){
        printf("ID: %d\tScore: %d\n", sd[x].id, sd[x].score); //print stmt not showing
    }
    students = sd;
    deallocate(sd);
}

void summary(struct student* students){
     /*Compute and print the minimum, maximum and average scores of the ten students*/

}

void deallocate(struct student* stud){
     /*Deallocate memory from stud*/
    free(stud);
}

int main(){
    struct student* stud = NULL;
    /*call allocate*/
    stud = allocate();
    /*call generate*/
    generate(stud);
    /*call output*/
    printf("%s", c);
    output(stud);
    /*call summary*/

    /*call deallocate*/
    deallocate(stud);

    return 0;
}
4

2 に答える 2

10

「printfステートメントがコンソールに表示されません」

プログラムがそこまで到達する前にクラッシュしなかったと確信していますか?

studはタイプstudent*&stud持っているので、はタイプを持ってstudent**いますが、それを期待する関数に渡していますstudent*...studではなく、を渡すだけ&studです。コンパイラで警告をオンにすると、そのようなことがわかります。

assert(s != 0);

これは不適切な慣行です。assertメモリ不足などの通常の障害状態ではなく、論理エラーのテストにのみ使用する必要があります。

struct student *s = malloc(size*(sizeof(struct student)));

これは大丈夫ですが、私はお勧めします

struct student* s = malloc(size * sizeof *s);

冗長性が低く、タイプに依存しないためです。

static int size = 10;

Cでは、これは定数ではありません(そして、constキーワードを追加しても定数にはなりません)。ローカル配列のサイズとして使用するため、すべてのCコンパイラで使用できるわけではないVLA(可変長配列)機能を呼び出しています。Cでは、それを行うのがより一般的です

#define SIZE 10

また

enum { SIZE = 10 };

これはあなたに問題を引き起こすでしょう:

ID being between 1 and 10

(「1とサイズ」と表示されている必要があるという事実は別として)。SIZE要素配列を割り当ててから、学生IDをインデックスとして使用しますが、有効なインデックスは0..SIZE-1のみです...SIZEはそうではありません。student->id - 1したがって、でインデックスを作成するか、IDを0インデックスにする必要があります。

    y = rand() % size + 1;
    while(dupe(id, i, y)){
        y = rand() % size + 1;
    }

それは次のように書くことができます

do
{
    y = rand() % size + 1;
} while(dupe(id, i, y));

しかし、私はこれがあなたが望んでいることをしているとは思いません。学生証がインデックスとは異なることを保証していますが、そうする理由はありません。あなたが保証したいのは、2つの学生IDが同じではないということですが、あなたはそれをしていません。1つの可能性は、以前に割り当てられたすべてのIDをスキャンし、すでに割り当てられている場合は別のIDを選択することです。もう1つの方法は、すべてのID 1 .. SIZEを配列に入れてから、ランダムに配列からアイテムを引き出し、配列の一番上の要素をそのスロットに移動し、配列のサイズを1ずつ減らします。アレイを空にして、すべてのIDを割り当てました。

(students + j)->id

Cにはいくつかの同等のルールがあります:*(x + y)=== x[y]、およびx->y=== (*x).y。したがって、(students + j)->id=== (*(students + j)).id=== students[j].id、これはそれを書くための好ましい方法です。

students = &sd;

このステートメントはその後使用されないため何もしません。これstudentsはタイプエラー(&sdタイプstudent**あり)です。これも、警告をオンにするとコンパイラが警告します(-Wall for gcc)。

ここでやろうとしているのは、発信者の生徒を変更することですが、これはそれを行いません。学生のアドレスを渡す必要があります(つまり、struct student** pstudents取得するために逆参照する引数がありますstudents)。または、return新しい配列(使用が完了するまで割り当てを解除しないでください)を渡す必要があります。

この問題のリストは必ずしも網羅的ではありません。

于 2012-10-05T16:52:05.337 に答える
0

ポインターの使用に関して、プログラムで見つけたいくつかのエラーを指摘します。

内部main,

あなたは呼び出す必要がgenerate()あり、output()として、

generate(stud);
output(stud);

ではsort

students = &sd;students = sd;代わりにする必要があります

ではoutput

sort(&students);sort(students);代わりにする必要があります

于 2012-10-05T17:13:13.200 に答える