在C中编写打印方法

时间:2012-10-22 02:03:04

标签: c pointers scheme interpreter

我是C的新手,正在为Scheme制作翻译。我试图获得一个合适的printList方法来遍历结构。

该程序接受如下输入:

  

(a(b c))

并在内部将其表示为:

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

现在,我只是希望程序接受输入,在内部制作适当的单元格结构并打印出单元格结构,从而获得

  

(a(b c))

最后。

这是我的结构:

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(")");

}

在main方法中,我得到第一个令牌并调用:

  

的printList(令牌);

我再次为子列表测试了值,我认为它正在运行。但是,我需要一种方法来遍历整个结构。请再次查看我的printList代码。打印调用是我必须键入的,手动获取(a(b c))列表值。所以我得到了这个输出:

  

第一个值?一个

     

第一个值? B'/ P>      

第一个值? ç

这就是我想要的,但是我想要一个使用循环的方法,无论结构有多复杂,还要在适当的地方添加括号,所以最后,我应该得到:

  

(a(b c))

与输入相同。

有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

原始程序的数据类型有点奇怪;您希望能够描述一组不相交的数据,在这种情况下,联合可能就是您想要的。目前,您只有一个cons单元格的数据类型,这使得很难区分:

(a b c)

(a (b c))

您现在使用的技巧是将符号数据视为单元格的左右指针均为NULL,但这使得无法表示:

(())

正是当你有一个内容为NULL的cons单元时会发生什么。

您可能表示不相交的数据集的一种方法是使用标记的不相交联合,如下所示:

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可以是SYMBOLCONSNIL。根据其类型,我们将以不同的方式处理结构的并集部分。

我们可能会包含一些帮助程序,以便更容易构建这些结构:

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将是一个递归函数,它根据类型标记进行调度:

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(")");

我们以递归方式调用打印机上的组件。但是,这可能不是我们想要的,因为它将所有内容视为不正确的结构,并且您可能希望为常规列表做更好的事情。

答案 1 :(得分:1)

List的类型是struct conscell的指针,因此createList函数中的malloc()应该是sizeof(struct conscell):

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

指向结构的指针只有8个字节,而结构本身的大小为17(默认填充实际为24byte):

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