26

リンク リストの概念ではなく、構造体自体の文字列フィールドが原因で、C で単一リンク リストに基づいてデータベースを作成するのに問題があります。

これは C での割り当てであり、私が知る限り (私は初心者です)、C は「文字列」をデータ型として認識しません。

これは私の構造体コードがどのように見えるかです:

typedef struct 
{
  int number;
  string name;
  string address;
  string birthdate;
  char gender;
} patient;

typedef struct llist
{
  patient num;
  struct llist *next;
} list;

次のように、構造体で使用できるように、文字列自体の構造体を作成することを考えていました。

typedef struct string 
{ 
  char *text;
} *string;

次にmalloc()、文字列型 (char の配列) の新しいデータを作成する必要があるときに、それぞれを作成します。

typedef struct string
{
  char *text;
} *string;

int main()
{
    int length = 50;
    string s = (string) malloc(sizeof string);
    s->text = (char *) malloc(len * sizeof char);
    strcpy(s->text, patient.name->text);
}

誰かがこれを理解するのを手伝ってくれますか?
ありがとうございました。

4

5 に答える 5

58

文字列とメモリ割り当てについて:

C の文字列は単なる一連のchars であるため、文字列データ型を使用する場合はどこでもchar *または配列を使用できます。char

typedef struct     {
  int number;
  char *name;
  char *address;
  char *birthdate;
  char gender;
} patient;

次に、構造体自体と各文字列にメモリを割り当てる必要があります。

patient *createPatient(int number, char *name, 
  char *addr, char *bd, char sex) {

  // Allocate memory for the pointers themselves and other elements
  // in the struct.
  patient *p = malloc(sizeof(struct patient));

  p->number = number; // Scalars (int, char, etc) can simply be copied

  // Must allocate memory for contents of pointers.  Here, strdup()
  // creates a new copy of name.  Another option:
  // p->name = malloc(strlen(name)+1);
  // strcpy(p->name, name);
  p->name = strdup(name);
  p->address = strdup(addr);
  p->birthdate = strdup(bd);
  p->gender = sex;
  return p;
}

数秒しか必要ない場合は、patient実際に必要以上のメモリを割り当てることを犠牲にして、メモリ管理を回避できます。

typedef struct     {
  int number;
  char name[50];       // Declaring an array will allocate the specified
  char address[200];   // amount of memory when the struct is created,
  char birthdate[50];  // but pre-determines the max length and may
  char gender;         // allocate more than you need.
} patient;

リンクされたリスト:

一般に、リンクされたリストの目的は、順序付けられた要素のコレクションにすばやくアクセスできることを証明することです。に (おそらく患者番号が含まれている)llistという要素が含まれている場合、実際の s 自体を保持するための追加のデータ構造が必要になり、毎回患者番号を検索する必要があります。numpatient

代わりに、宣言すると

typedef struct llist
{
  patient *p;
  struct llist *next;
} list;

次に、各要素にはpatient構造体への直接ポインターが含まれ、次のようにデータにアクセスできます。

patient *getPatient(list *patients, int num) {
  list *l = patients;
  while (l != NULL) {
    if (l->p->num == num) {
      return l->p;
    }
    l = l->next;
  }
  return NULL;
}
于 2012-04-15T13:02:50.050 に答える
1

typedef を使用したい場合は Richard が必要ですが、何も得られずにポインタであることを見失うため、この例ではおそらく特に良い考えではないことをお勧めします。

カウントされた文字列または追加機能を備えたものとして扱っていた場合は、異なる場合がありますが、この場合は、「標準」の C 文字列実装が「char *」であることに慣れることをお勧めします。 ..

于 2012-04-15T13:07:54.103 に答える
0

さらに単純なものを使用することもできますtypedef

typedef char *string;

次に、mallocは通常のmallocのようになります。

string s = malloc(maxStringLength);
于 2012-04-15T12:58:09.130 に答える
0

これは動作しません:

string s = (string)malloc(sizeof string); 

stringポインターを参照する場合、構造体自体のサイズが必要です。

string s = malloc(sizeof (*string)); 

void*キャストがないことにも注意してください((の戻り値の型)からの変換mallocは暗黙的に実行されます)。

また、あなたmainの には、グローバルに宣言された がありますがpatient、それは初期化されていません。試す:

 patient.number = 3;     
 patient.name = "John";     
 patient.address = "Baker street";     
 patient.birthdate = "4/15/2012";     
 patient.gender = 'M';     

そのメンバーのいずれかに読み取りアクセスする前に

また、境界チェックがないため、strcpy本質的に安全ではありません ('\0'ソースが長すぎる場合は、最初に遭遇するまでコピーし、割り当てられたメモリを超えて書き込みます)。strncpy代わりに、少なくともコピーされる最大文字数を指定できる場合に使用してください。ドキュメントを読んで、正しい値を渡すようにしてください。オフバイワン エラーを起こしやすいです。

于 2012-04-15T12:53:38.177 に答える