2012-02-13 50 views
2

我是编程新手,想学习链表。我决定通过编写一个简单的程序来实验链表,该程序将从文件中读取,每次只读一个字符,并将每个字符插入链表中。然后我打印出链表。很简单,对吧?好吧,如果这是你第一次,也许不会。我在网上教程哦,如此小心,但我的输出不是它应该是。 (程序编译并运行时没有错误或警告,我正在使用代码块。)我没有获取任何字符,而是得到两个数字,就这些了。c中的链表,意想不到的结果

这里是我写的代码:

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

typedef struct Tokens_read_in{ 
    char character; 
    int number; 
    char whichOne[5]; 
    struct Tokens_read_in* next; 
}Tokens; 

int main() 
{ 

    //declare variables 
    char c; 

    //create a struct for the array that will hold the tokens 
    Tokens* token_array; 
    token_array = malloc(sizeof(Tokens)); 
    token_array->next = NULL; 

    //open the input file 
    FILE *ifp; //input file pointer 
    char *filename = "input.txt"; 
    ifp = fopen(filename, "r"); 

    if(!ifp){ 
     printf("Error in opening '%s' for reading!", filename); 
     exit(0); 
    } 

    while(!feof(ifp)){ 

     //prepare to read in file one character at a time 
     c = getc(ifp); 

     //create a struct for the current token that is read in 
     Tokens* current_token = token_array; 

     //let the current_token point to the beginning of token_array 
     current_token = token_array; 

     //let the current_token point to the LAST of token_array 
     while(current_token->next != NULL){ 
      current_token = current_token->next; 
     } 

     //create a node at the end of token_array 
     current_token->next = malloc(sizeof(Tokens)); 

     //move the current_token to the last (new) of token_array 
     current_token = current_token->next; 
     if(current_token == NULL){ 
      printf("Out of memory"); 
      exit(0); 
     } 

     //plug character into current_token 
     current_token->next = NULL; 
     //letter 
     if(isalpha(c)){ 
      printf("%c", c); 
      current_token->character = c; 
      strcpy(current_token->whichOne, "char"); 
     } 
     //number 
     else if(isdigit(c)) 
     { 
      printf("%d", (int)c); 
      current_token->number = (int)c; 
      strcpy(current_token->whichOne, "num"); 
     } 
     //space 
     //this does not need to go into the token array 
     else if (c == ' '){ 
      printf(" "); 
     } 
     //newline 
     //this does not need to go into the token array 
     else if (c == '\n'){ 
      printf("\n"); 
     } 
     //anything else 
     else if ((!isdigit(c) && !isalpha(c))){ 
      printf("%c", c); 
      current_token->character = c; 
      strcpy(current_token->whichOne, "char"); 
     } 

     //now that the current_token is plugged into token_array, free current_token 
     free(current_token); 

    }//end while(!feof(ifp)) 

    //print the token_array 
    Tokens* conductor; 
    conductor = token_array; 
    while(conductor != NULL){ 
     if(strcmp(conductor->whichOne, "num")){ 
      printf("%d ", conductor->number); 
     } 
     else if(strcmp(conductor->whichOne, "char")){ 
      printf("%c ", conductor->character); 
     } 
     conductor = conductor->next; 
    } 
    //done printing, so free conductor 
    free(conductor); 

    //done with program, so free token_array 
    free(token_array); 

    //close input file 
    fclose(ifp); 

    return 0; 
}//end main 

这里是我使用的输入文件(名为input.txt中):

<I don't know why every beginner program says hello world, 
but hello world anyway.> 

我真的很感激任何人谁看这个并指出我正确的方向。

+0

每个初学者程序

说“你好世界”,因为经典文本* C程序设计语言*开始于一个程序,打印“Hello ,世界!“。 – Caleb 2012-02-13 17:27:12

+0

您的程序有几个主要缺陷需要修复,然后才能继续。第一个缺陷是你要通过每次迭代收集一个新角色来重置和遍历你的列表。如果你只是坚持根(第一个)节点和终端(最后一个)节点,这是完全不必要的。接下来,您声明一个堆栈变量指向根节点并将其分配两次。最后,释放刚刚初始化的节点,从而创建无效指针的链接列表。你需要更好地理解C和完成你的任务的指针。 – BitBank 2012-02-13 17:37:47

回答

5

您不应该在读取循环结束时释放current_token。这会导致问题,因为您释放了链接列表中的节点的内存。

另外,作为旁注,当给定表示数字的字符时,isdigit成功,因此例如字符'1'。您仍然应该使用%c来打印出来,因为%d会为您提供字符'1'的ascii编号。

+0

我了解它的方式,一旦current_token被“插入”token_array,token_array将接管所有插入它的内容,即使当current_token被释放时也会存在。我是否明白这完全错误 - 我要走了吗?如果是这样,我应该在哪里free_array - 我应该释放它与自由(token_array)?或者如果两者仍然交织在一起,是否意味着我只需要释放token_array并且会自动消除current_array? – Tabitha 2012-02-13 17:49:29

0
//now that the current_token is plugged into token_array, free current_token 
     free(current_token); 

    }//end while(!feof(ifp)) 

尝试呼叫评论到free(current_token);

的malloc的工作和自由是跟踪的内存已经分配了什么。当你打电话给免费的时候,下一次malloc调用可能会发回你刚才使用的相同的内存地址。

此外

//create a struct for the current token that is read in 
Tokens* current_token = token_array; 

//let the current_token point to the beginning of token_array 
current_token = token_array; 

第二分配是多余的。不是一个错误(但),但只是一个新的程序员的笔记。

另外,让我们知道你正在得到什么数字。获取数字而不是字符有时可能表示您正在输出ASCII码而不是字符本身。

4

您需要if (strcmp(a,b)==0)来测试是否相等。

+1

这是您遇到的最大问题之一。您正在使用您的号码打印字符和字符打印数字。 – 2012-02-13 17:39:30

1
  • 你绝对不想free(current_token)
  • 如果你想为一个字符转换为int,一个简单的方法(在ASCII)要做到这一点是:
char c = '3'; 
    int i = c - '0'; 
    printf("As a char: %c\n", c); // Prints 3. 
    printf("As an int: %d\n", i); // Prints 3. 
  • 当你的malloc数据,这是可能的,可能会有是该地区的随机数据。一旦你使用memset malloc,你应该清除整个结构。
  • 正如其他答案中所提到的,strcmp在匹配时返回0。这意味着你正在做你想要的比较的反面。
  • 当字符是空格或换行符时,结构中的数据非常奇怪。这是因为数据以未确定的状态开始。

如果您修复上述错误(不包括memset),程序的输出更像您想要的。