2

私は C が初めてで、Scheme のインタープリターの作成に取り組んでいます。構造体を通過する適切な printList メソッドを取得しようとしています。

プログラムは次のような入力を受け取ります。

(a (bc))

内部的には次のように表します。

[""][ ][ ]-->  [""][ ][/]
     |              |              
   ["A"][/][/]     [""][ ][ ]-->  [""][ ][/]     
                        |              |                 
                      ["B"][/][/]    ["C"][/][/]

今のところ、プログラムに入力を取り込ませ、適切なセル構造を内部で作成し、セル構造を出力して、それによって取得したいだけです。

(a (bc))

最後に。

ここに私の構造体があります:

typedef struct conscell *List;

struct conscell {
char symbol;
struct conscell *first;
struct conscell *rest;

};


void printList(char token[20]){
    List current = S_Expression(token, 0);

     printf("(");

printf("First Value? %c \n", current->first->symbol);
printf("Second value? %c \n", current->rest->first->first->symbol);
printf("Third value? %c \n", current->rest->first->rest->first->symbol);


printf(")");

}

メイン メソッドでは、最初のトークンを取得して呼び出します。

printList(トークン);

サブリストの値を再度テストしましたが、機能していると思います。ただし、構造全体をトラバースする方法が必要になります。私のprintListコードをもう一度見てください。(a (bc)) リストの値を手動で取得するには、印刷呼び出しを入力する必要があります。したがって、次の出力が得られます。

最初の値?a

最初の値?b

最初の値?c

それは私が望むものですが、構造がどれほど複雑であっても、ループを使用してそれを実行するメソッドが必要であり、適切な場所にブラケットを追加する必要があるため、最終的には次のようになります。

(a (bc))

これは入力と同じです。

誰でもこれで私を助けてもらえますか?

4

2 に答える 2

2

元のプログラムのデータ型は少し奇妙です。バラバラなデータセットを記述できるようにしたい場合、おそらくユニオンが必要です。現時点では、コンス セルのデータ型は 1 つしかないため、以下を区別するのが難しくなっています。

(a b c)

(a (b c))

現在使用しているトリックは、シンボリック データを、セルの左右のポインターが両方とも NULL であるデータとして扱うことですが、それでは表現できなくなります。

(())

これは、コンテンツが両方とも NULL であるコンス セルがある場合に発生することとまったく同じです。

互いに素なデータ セットを表現する方法の 1 つは、次のように、タグ付きの素なユニオンを使用することです。

enum SexpType {SYMBOL, CONS, NIL};

struct Sexp {
  enum SexpType type;
  union {
    char symbol;
    struct Cons *cons;
  };
};

struct Cons {
  struct Sexp *first;
  struct Sexp *rest;
};

Sexp は、SYMBOL、 a CONS、またはのいずれかNILです。そのタイプに応じて、構造体のユニオン部分を異なる方法で扱います。

これらの種類の構造を簡単に構築できるように、いくつかのヘルパーを含めることができます。

struct Sexp* newCons(struct Sexp* first, struct Sexp* rest) {
  struct Sexp* pair = malloc(sizeof(struct Sexp));
  pair->type = CONS;
  pair->cons = malloc(sizeof(struct Cons));
  pair->cons->first = first;
  pair->cons->rest = rest;
  return pair;
}

struct Sexp* newSymbol(char c) {
  struct Sexp* ch = malloc(sizeof(struct Sexp));
  ch->type = SYMBOL;
  ch->symbol = c;
  return ch;
}

適切なデータ表現printListが得られると、 type タグに基づいてディスパッチする再帰関数になります。

void printSexp(struct Sexp* sexp) {
  switch (sexp->type) {
  case SYMBOL: 
    /* FIXME */
    break;
  case CONS:
    /* FIXME */
    break;
  case NIL:
    /* FIXME */
    break;
  }
}

それぞれのケースはかなり単純です。CONSケースに何かをさせるために、次のようなことを試みるかもしれません:

printf("(");
printSexp(sexp->cons->first);
printf(" . ");
printSexp(sexp->cons->rest);
printf(")");

ここで、ペアのコンポーネントでプリンターを再帰的に呼び出します。ただし、これはすべてを不適切な構造として扱うため、これは私たちが望んでいるものではないかもしれません。

于 2012-10-22T17:35:17.623 に答える
1

List の型は struct conscell のポインターであるため、createList 関数の malloc() が sizeof(struct conscell) である必要があります。

List node = malloc(sizeof(struct conscell));

構造体へのポインターはわずか 8 バイトですが、構造体自体のサイズは 17 です (デフォルトのパディングでは実際には 24 バイトです)。

http://en.wikipedia.org/wiki/Data_structure_alignment

于 2012-10-22T02:58:36.480 に答える