0

10 から 60,000 の間の候補数を取得し、各候補の名前を取得する関数を作成しようとしました...これは私が書いたものです:

/********** Headers **********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
/********** Consts **********/
const number_candidates;

/********** Functions **********/
void get_candidates(char *arr[256][256])
{
    int counter = 1, i = 0, j =0;
    int temp = 0;

    printf ("Please enter the number of candidates: \n");
    scanf ("%d", &temp);
    while (temp < 10 && temp > 60000)
    {
        printf ("Please enter the number of candidates: \n");
        scanf ("%d", temp);
    }
    const number_candidates = temp;
    while (counter < number_candidates + 1)
    {
        printf ("Please enter the %d name: \n", counter);
        fgets (arr, 256, stdin);
        counter++;
    }
}

int main(int argc, char *argv[])
{
    int i = 0;
    char can_names[256][256];

    get_candidates(&can_names);

    system("PAUSE");
    return 0;
}

配列への名前の取得中にエラーが発生しました...

4

5 に答える 5

2

このような引数の使用は避けてください:char *arr[256][256]...そのポイントは何ですか?関数が何をするかを考える必要があります。候補者の名前をロードしたいですか?したがって、その中に属性を含む構造体候補を定義できますname

typedef struct candidate{
    char name[256];
} Candidate;

別のこと:なぜこの関数に配列のアドレスを渡すのですか?配列にデータを入力するだけで、配列自体を操作することはできません。したがって、配列のアドレスではなく、配列を渡すだけで十分です。

次に、関数のプロトタイプを、void get_candidates(Candidate* candidates)はるかに読みやすいものに変更できます。そして、この関数の使用法がどれほど簡単になるか見てみましょう。

Candidate candidates[256];
get_candidates(candidates);

そして最後に、そのような関数を書く前に、まずもっと簡単なことを試してください(そこで何が起こっているのかを知るために)。次に例を示します。

#include <stdio.h>

typedef struct candidate{
    char name[256];
} Candidate;

void get_candidates(Candidate* candidates){
    scanf("%255s", candidates[4].name);
}

int main(int argc, char *argv[]){
    Candidate candidates[256];
    get_candidates(candidates);
    printf("%s\n", candidates[4].name);
    return 0;
}

を呼び出す前に候補の数がわからない場合はget_candidates、この関数のプロトタイプをに変更して、Candidate* get_candidates()この関数が配列を作成することが明確になるようにすることをお勧めします。

// caller is responsible for calling free on return value
Candidate* get_candidates(){
    Candidate* candidates;
    int count = 50; // here you found out the count
    candidates = malloc(count*sizeof(Candidate));
    fgets(candidates[4].name, 255, stdin);
    return candidates;
}

int main(int argc, char *argv[]){
    Candidate* candidates = get_candidates();
    printf("%s\n", candidates[4].name);
    free(candidates);
    return 0;
}
于 2012-05-09T18:45:19.987 に答える
0

これが役立つかどうかはわかりませんが、以下のコードをご覧ください。つまり、動的に機能します。60,000の候補を想定するのではなく、希望する候補の数にメモリを割り当てました。

/*
 * Write a function, that get a number of candidates betwen 10 to 60,000, and gets a     name for each candidate 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 256

int main(int argc, char*argv[]){

int i,n;
char **s;

printf("Enter the total number of candidates\n");
scanf("%d",&n);

//error condition
if(n<10 || n>60000){        
    printf("Sorry number of candidates should be between 10 to 60,000\n");
    return -1;      
}

//allocate memory
s = malloc(sizeof(char*)*n);

//get the data
for(i=0;i<n;i++){

    s[i] = calloc(MAX,sizeof(char));
    printf("Enter the candidate number %d's name:\n",i+1);
    //fgets(s[i],MAX,stdin);
    scanf("%s",s[i]);

}

//Display the data
printf("\nDetails of all the Candidates\n\n");
for(i=0;i<n;i++){
    printf("Candidate number %d's name:%s\n",i+1,s[i]);
}

//Free the memory
for(i=0;i<n;i++){
    free(s[i]);
}
free(s);

return 0;

}

最初の候補情報をスキップしていたfgetsに問題がありました。助けていただければ幸いです。私は試しflush(stdin)ましたが、問題は解決しませんでした。

于 2012-05-10T09:29:59.903 に答える
0

初めて scanf を呼び出したときと同様に、変数をポインターとして渡す必要があることを示すドキュメントをscanf参照してください。次に、scanf への 2 回目の呼び出しを見てください...

現在、配列の最初の文字列に何度も名前を割り当てているだけです。while ループ、特に 'arr' 変数をどのように渡しているかを見てください。インスピレーションについては、こちらをご覧ください。

すべての名前を出力するには、配列をループする必要があります。文字列のリストを出力する例は、ここここにあります。

于 2012-05-09T18:31:04.353 に答える
0

あなたは電話する必要があります:

counter = 0;
...
fgets (arr[counter], 256, stdin);


ループごとに 1 ステップ歩く必要があります。

于 2012-05-09T18:37:21.487 に答える
0

いくつかの点が間違っています:

まず、60000 個の名前のスペースが必要ですが、256 個しか割り当てられません。

char can_names[256][256];

char can_names[60000][256];

そして...セグメンテーション違反、おそらく。これは、配列がスタック領域を使いすぎているためです。に変更します

static char can_names[60000][256];

したがって、スタックにはありません。


次に、配列のアドレスを取得する必要はありません。既にポインターとして渡されています。関数呼び出しが次のように変わります

get_candidates(can_names);

関数のシグネチャは

void get_candidates(char arr[60000][256])

3 番目に、エントリを 1 つずつ読み取るためのループが必要です。forループの方が読みやすい:

for (counter = 0; counter < number_candidates; counter++)
{
    printf ("Please enter the %d name: \n", counter);
    fgets (arr[counter], 256, stdin);
}

第四に、条件

while (temp < 10 && temp > 60000)

する必要があります

while (temp < 10 || temp > 60000)

(数値が 10 未満で 60000 を超える場合はどうすればよいでしょうか?) これが修正されたらtemp、ループが少なくとも 1 回実行されるため、最初の読み取りを削除できます。ここで数字の代わりに文字を入力すると、プログラムは無限ループに入ります (文字を繰り返し読み取ります)。これを修正することは演習として残されています。


第 5 に、 以外のヘッダーは必要ありませんstdio.h。また、iおよびj変数は使用されません。


編集:scanfエラーを逃しました。 パラメータとしてアドレスscanfを取ります。それも理にかなっています。値を格納する場所が必要であり、現在の値は気にしません。したがって、への呼び出しは次のようになります。scanfscanf

scanf ("%d", &temp);
于 2012-05-09T18:46:38.723 に答える