C 将输入文件标记为链表

C 将输入文件标记为链表,c,string,pointers,linked-list,tokenize,C,String,Pointers,Linked List,Tokenize,我试图标记一个输入文件,并将其单个单词存储在按单词数组织的链接列表中。我一直在努力将标记化字符串存储到一个节点中,并且努力理解我的标记化/插入过程中的错误。当前,当打印存储的字符串时,每个字符串的第一个字母被截断,并且似乎存在随机垃圾和每个字符串的结尾。我已尝试以下方法来修复我的错误: 标记化后终止每个字符串的Null(我将其保留在 我的程序(看起来是正确的) 使用strncpy()代替new\u word->str=str 将标记化字符串的指针传递给我的插入函数, 而不仅仅是传递字符串本身 下

我试图标记一个输入文件,并将其单个单词存储在按单词数组织的链接列表中。我一直在努力将标记化字符串存储到一个节点中,并且努力理解我的
标记化/插入过程中的错误。当前,当打印存储的字符串时,每个字符串的第一个字母被截断,并且似乎存在随机垃圾和每个字符串的结尾。我已尝试以下方法来修复我的错误:

  • 标记化后终止每个字符串的Null(我将其保留在 我的程序(看起来是正确的)
  • 使用
    strncpy()
    代替
    new\u word->str=str
  • 将标记化字符串的指针传递给我的插入函数, 而不仅仅是传递字符串本身
  • 下面是我的代码:

    #包括
    #包括
    #包括
    #包括
    #包括
    typedef结构字{
    整数长度;
    char*str;
    结构字*左;
    结构词*对;
    结构字*向下;
    }字;
    无效打印列表(字**头){
    字*temp_traverse=*头;
    word*temp_down;
    对于(;temp_traverse!=NULL;temp_traverse=temp_traverse->right){
    温度向下=温度横向移动;
    对于(;temp_down!=NULL;temp_down=temp_down->down){
    printf(“计数:%d,字符串:%s\n”,临时向下->长度,临时向下->str);
    }
    }
    }
    int是空的(单词**头,单词**尾){
    如果((*head==NULL)| |(*tail==NULL))
    返回1;
    返回0;
    }
    空白插入(字**头,字**尾,字*新字){
    如果(是空的(头、尾)){
    (*head)=新单词;
    (*tail)=新单词;
    返回;
    }
    如果((新单词->长度)长度){
    新单词->右=(*标题);
    (*head)->左=新单词;
    (*head)=新单词;
    返回;
    }
    单词*温度=*头部;
    而(((临时->右)!=NULL)和(((临时->长度)长度)))
    温度=温度->右侧;
    如果((临时->长度)=(新单词->长度)){
    while(临时->停机!=NULL)
    温度=温度->下降;
    temp->down=新单词;
    返回;
    }
    如果(临时->右==NULL){
    单词*last=(*tail);
    最后->右=新单词;
    新单词->左=最后一个;
    (*tail)=新单词;
    返回;
    }
    word*next=temp->right;
    临时->右=新单词;
    下一步->左=新单词;
    新单词->左=临时;
    新单词->右=下一步;
    返回;
    }
    无效创建(单词**头,单词**尾,字符**str){
    单词*新单词=(单词*)malloc(单词大小);
    整数长度=strlen(*str);
    if(新单词==NULL){
    fprintf(stderr,“创建新单词节点时出错。\n”);
    出口(0);
    }
    新单词->str=(char*)malloc(sizeof(*str));
    strncpy(新单词->str,*str,长度);
    //新单词->str=*str;
    新单词->长度=长度;
    printf(“%s”,新单词->str);//测试打印
    新单词->左=空;
    新单词->右=空;
    new_word->down=NULL;
    插入(头、尾、新单词);
    返回;
    }
    void标记化(单词**头,单词**尾,字符单词_buffer[]){
    char*cur;
    cur=strtok(字_buffer,;()\t\r\v\f\n);
    *cur++='\0';
    创建(头、尾和cur);
    /*标记下一个字符串并重置“复制”变量*/
    while((cur=strtok(NULL,,;()\t\r\v\f\n”)!=NULL){
    //cur=strtok(NULL,,;()\t\r\v\f\n);
    *cur++='\0';
    如果(当前){
    创建(头、尾和cur);
    }
    }
    }
    intmain(intargc,char*argv[]){
    文件*fp;
    word*head=NULL;
    单词*tail=NULL;
    /*如果(argc1)
    标记化(头、尾、字和缓冲区);
    }
    //打印列表(&head);
    fclose(fp);
    返回0;
    } 
    
    我留下了我的测试字符串打印供您参考。您还会注意到,我现在没有使用
    print\u list
    ,因为我还没有正确存储字符串

    由于末尾的垃圾,我假设我不是错误地使用了指向字符串的指针,就是
    malloc()
    占用了太多的空间。至于截断,我不确定,但我认为它与我的
    *cur++='\0'有关


    非常感谢您的帮助,感谢您抽出时间查看

    您没有使用
    strncpy()
    复制整个字符串

    事实上,使用以下方法获取长度时,复制的字符太少:

    int-length=strlen(*str)

    strncpy()
    manpage中所述:

    警告:如果src的前n个字节中没有空字节,则放置在dest中的字符串将不会以空结尾

    因此,当您使用在以null结尾的字符串上操作的函数时,例如大多数标准库
    str*()
    函数,请确保您使用以下方法解释
    '\0'
    终止符:

    int-length=strlen(*str)+1

    另外,由
    malloc()
    返回的
    void*
    会隐式转换为任何对象指针类型,而不是:

    word*新单词=(word*)malloc(sizeof(word))

    您只需使用:

    word*new_word=malloc(sizeof(word))

    或者更好:

    word*new\u word=malloc(sizeof*new\u word)

    避免由于更改声明中的指针类型而不是调用
    malloc()
    而导致的错误

    sizeof
    操作符不计算非可变长度数组表达式,因此这是获取对象大小的更可靠的方法

    编辑

    至于缺少的每个字符串的第一个字符,我认为这是由于:

    *cur++ = '\0';
    

    因为这只是无用地将
    cur[0]
    设置为
    '\0'
    ,然后递增指针;字符串现在从单词的第二个字母开始。

    嗨,乔伊,谢谢你正确地回答了这两个问题。你修复的后续行动:现在我有了imp
    *cur++ = '\0';