c中的链表,意外结果

c中的链表,意外结果,c,linked-list,C,Linked List,我是编程新手,正在努力学习链表。我决定通过编写一个简单的程序来试验链表,该程序将从文件中读取,每次读取一个字符,然后将每个字符插入链表中。然后我把链表打印出来。很简单,对吧?如果这是你的第一次,也许不会。我正在关注在线教程哦,非常仔细,但我的输出不是它应该是什么。(程序编译和运行时没有错误或警告。我使用的是代码块。)我得到的不是任何字符,而是两个数字,仅此而已 以下是我编写的代码: #include <stdio.h> #include <stdlib.h> #inclu

我是编程新手,正在努力学习链表。我决定通过编写一个简单的程序来试验链表,该程序将从文件中读取,每次读取一个字符,然后将每个字符插入链表中。然后我把链表打印出来。很简单,对吧?如果这是你的第一次,也许不会。我正在关注在线教程哦,非常仔细,但我的输出不是它应该是什么。(程序编译和运行时没有错误或警告。我使用的是代码块。)我得到的不是任何字符,而是两个数字,仅此而已

以下是我编写的代码:

#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
#包括
#包括
#包括
typedef结构标记\u读取\u{
字符;
整数;
char-whichOne[5];
在*下一步中读取结构标记;
}代币;
int main()
{
//声明变量
字符c;
//为将保存令牌的数组创建一个结构
令牌*令牌数组;
令牌数组=malloc(sizeof(令牌));
令牌\u数组->下一步=空;
//打开输入文件
FILE*ifp;//输入文件指针
char*filename=“input.txt”;
ifp=fopen(文件名,“r”);
如果(!ifp){
printf(“打开“%s”进行读取时出错!”,文件名);
出口(0);
}
而(!feof(ifp)){
//准备在文件中一次读取一个字符
c=getc(ifp);
//为读入的当前令牌创建结构
令牌*当前令牌=令牌数组;
//让当前\u令牌指向令牌\u数组的开头
当前\u令牌=令牌\u数组;
//让当前\u令牌指向令牌\u数组的最后一个
while(当前\u令牌->下一步!=NULL){
当前\u令牌=当前\u令牌->下一步;
}
//在令牌数组的末尾创建一个节点
当前令牌->下一个=malloc(sizeof(令牌));
//将当前\u令牌移动到令牌\u数组的最后一个(新)位置
当前\u令牌=当前\u令牌->下一步;
if(当前_标记==NULL){
printf(“内存不足”);
出口(0);
}
//将字符插入当前\u令牌
当前\u令牌->下一步=空;
//书信
if(isalpha(c)){
printf(“%c”,c);
当前令牌->字符=c;
strcpy(当前令牌->whichOne,“char”);
}
//数
否则,如果(i数字(c))
{
printf(“%d”,(int)c);
当前令牌->数字=(int)c;
strcpy(当前令牌->whichOne,“num”);
}
//空间
//这不需要进入令牌数组
else if(c==“”){
printf(“”);
}
//新线
//这不需要进入令牌数组
else如果(c=='\n'){
printf(“\n”);
}
//还有别的吗
如果(!isdigit(c)和(!isalpha(c)),则为else{
printf(“%c”,c);
当前令牌->字符=c;
strcpy(当前令牌->whichOne,“char”);
}
//现在,当前\u令牌已插入令牌\u数组,释放当前\u令牌
免费(当前_令牌);
}//结束时(!feof(ifp))
//打印令牌数组
代币*售票员;
导体=令牌_阵列;
while(导体!=NULL){
if(strcmp(导体->whichOne,“num”)){
printf(“%d”,导体->编号);
}
否则如果(strcmp(导体->whichOne,“字符”)){
printf(“%c”,导体->字符);
}
导体=导体->下一步;
}
//完成了打印,所以是自由导体
自由(导体);
//完成与程序,所以免费令牌_数组
免费(令牌_数组);
//关闭输入文件
fclose(ifp);
返回0;
}//端干管
下面是我正在使用的输入文件(名为input.txt):


不应在读取循环结束时释放当前\u令牌。这将导致问题,因为您正在释放链接列表中某个节点的内存

另外,作为旁注,当给定一个表示数字的字符时,isdigit成功,例如字符“1”。您仍应使用%c打印此内容,因为%d将为您提供字符“1”的ascii数字

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

    }//end while(!feof(ifp))
尝试对调用
free(当前_令牌)进行注释

malloc和free的任务是跟踪分配的内存。当您调用空闲时,下一个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;
第二项任务是多余的。这还不是一个bug,只是给新程序员的一个提示

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

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

  • 您绝对不想
    免费(当前\u令牌)
  • 如果要将字符转换为int,一种简单的方法(ASCII)是:
  • 当您删除malloc数据时,该区域中可能存在随机数据。一旦使用memset对整个结构进行malloc,就应该清除它
  • 如其他答案所述,strcmp在匹配时返回0。这意味着你正在做与你想要的相反的比较
  • 当字符是空格或换行符时,结构中的数据非常奇怪。这是因为数据在未确定状态下启动

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

strcmp在两个字符串相等时返回零

大概你想避免使用eof字符

在你要的第99行

conductor = (token_array->next);
而不是

conductor = token_array;

每个初学者程序都会说“hello world”,因为C编程语言的经典文本是以打印“hello,world!”的程序开始的。在继续之前,您的程序有几个主要缺陷需要修复。第一个缺陷
conductor = (token_array->next);
conductor = token_array;