3

これは構造体です:

typedef struct _friend {
        char *firstname;
        char *lastname;
        char birthdate[9];
} friend;

ユーザーに文字列を入力させ、それを(または)friendとして構造体に配置する方法について混乱しています。また、ユーザーが を使用するときに 256 文字を超える文字を入力するとどうなりますか? これは私がこれまでに持っているものです...firstnamelastnamefgets

friend *f = (friend *)malloc(sizeof(friend));  //initialize f pointer to friend
char *str;

fgets(str,256,stdin);
f->firstname = (char*)malloc(sizeof(char)*(strlen(str)+1));
strcpy(f->firstname,str);
4

3 に答える 3

2

この問題に対する万能の解決策はありません。特定のエンジニアは、さまざまな基準に基づいて、同じ問題に対していくつかの解決策の1つを使用する可能性があります。

  • 解決策はばかげた単純なものである必要がありますか?
  • 幅広い入力長に柔軟に適応する必要がありますか?
  • コードは、十分なメモリが利用可能であることがわかっている限られた範囲の環境でのみ実行されますか?
  • 継続的なメンテナンスのように、他の誰かがソリューションを理解する必要がありますか?

既知の適切なメモリ環境での簡単な解決策として、次のようにします。

char  buf [1000];  // for English names, this should be big enough
friend f;  // not a pointer, but a full struct
if (!fgets (buf, sizeof buf, stdin))
{
      perror ("error reading from stdin");
      return;
}
f.firstname = strdup (buf);  // allocates the right size of memory and copies

...
// when finished with the structure, deallocate the dynamic strings:
free (f.firstname);

これにより、ポインタの操作がほぼ完全に回避されることに注意してください。(strdup()それを実行しているだけで、基本的な操作をきちんとカプセル化します。)これは、堅牢でトラブルの少ないコードの機能です。

于 2012-10-14T01:08:05.493 に答える
2

stdinはバッファリングされた入力であるため、fgetc改行または EOF に到達するまで入力を 1 文字ずつ読み取るために使用できます。おそらく、あなたはこのようなものを探しています:

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

struct friend {
        char    *firstname;
        char    *lastname;
        char     birthdate[9];
};

static char *read_line(FILE *f)
{
    char    *r = NULL;
    char    *p = r;
    char    *e = p;
    int  c;

    while ((c = fgetc(f)) != EOF) {
        if (p >= e) {
            size_t   l = e > r ? (size_t)(e - r) : 32u;
            char    *x = realloc(r, l);
            if (!x) {
                free(r);
                r = NULL;
                goto out;
            }
            p = x + (p - r);
            e = x + l;
            r = x;
        }
        if (c != '\n') {
            *p++ = (char)c;
        } else {
            *p++ = '\0';
            goto out;
        }
    }
    if (ferror(f) != 0) {
        free(r);
        r = NULL;
    }
out:
    return r;
}

int main(void)
{
    struct friend f;

    memset(&f, 0, sizeof(struct friend));

    printf("Please enter your first name: ");
    fflush(stdout);
    f.firstname = read_line(stdin);
    if (!f.firstname)
        goto on_error;
    printf("Please enter your last name: ");
    fflush(stdout);
    f.lastname = read_line(stdin);
    if (!f.lastname)
        goto on_error;

    printf("You first name is: %s\n", f.firstname);
    printf("Your last name is: %s\n", f.lastname);

    free(f.firstname);
    free(f.lastname);
    return EXIT_SUCCESS;

on_error:
    perror("read_line");
    free(f.firstname);
    free(f.lastname);
    return EXIT_FAILURE;
}
于 2012-10-14T01:00:49.677 に答える
1

しないでください。

ユーザー入力用に別のバッファーを用意します。次に、ユーザーがこのバッファにデータを入力した後、それを解析し、それが正常かどうか (たとえば、空の文字列ではないかどうか、数字やその他の奇妙な文字が含まれていないかどうか) を判断し、余分な空白などを取り除きます。データが受け入れられるかどうかを確認し、実際の長さを判断して、コピー先として適切な量のメモリを割り当てます。

ユーザー入力を別のバッファに入れる場合は、 を使用しないでくださいfgets()fgetc()必要に応じてバッファのサイズを増やすことができるように、代わりにループで使用します。たとえば、32 バイトの小さなバッファーから始めて、バッファーrealloc()がいっぱいになるたびにバッファーのサイズを 2 倍にします ( を使用)。

于 2012-10-14T00:52:15.360 に答える