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';