C 字符指针赋值
这里是程序的代码,该程序计算某些输入中所有单词的出现次数。摘自《K和R》一书。除了作者为什么要使用strdup()之外,我几乎什么都懂。为什么我们不能(在函数addtree中)赋值C 字符指针赋值,c,pointers,C,Pointers,这里是程序的代码,该程序计算某些输入中所有单词的出现次数。摘自《K和R》一书。除了作者为什么要使用strdup()之外,我几乎什么都懂。为什么我们不能(在函数addtree中)赋值p->word=w。在结构tnode中,word显然是指向字符的指针,addtree函数的参数是字符指针 #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #incl
p->word=w
。在结构tnode中,word显然是指向字符的指针,addtree函数的参数是字符指针
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXWORD 100
#define BUFSIZE 100
struct tnode { /* the tree node: */
char *word; /* points to the text */
int count; /* number of occurrences */
struct tnode *left; /* left child */
struct tnode *right; /* right child */
};
struct tnode *addtree(struct tnode *, char *);
struct tnode *talloc(void);
void treeprint(struct tnode *);
void ungetch(int);
int getword(char *, int);
int getch(void);
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int main(void) { /* word frequency count */
struct tnode *root;
char word[MAXWORD];
root = NULL;
while(getword(word, MAXWORD) != EOF)
if(isalpha(word[0]))
root = addtree(root, word);
treeprint(root);
exit(0);
}
/* getword: get next word or character from input */
int getword(char *word, int lim) {
int c, getch(void);
void ungetch(int);
char *w = word;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalpha(c)) {
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch())) {
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
/* addtree: add a node with w, at or below p */
struct tnode *addtree(struct tnode *p, char *w) {
int cond;
if(p == NULL) { /* a new word has arrived */
p = talloc(); /* make a new node */
p->word = strdup(w);
p->count = 1;
p->left = p->right = NULL;
} else if((cond = strcmp(w, p->word)) == 0)
p->count++; /* repeated word */
else if(cond < 0) /* less than into left subtree */
p->left = addtree(p->left, w);
else /* greater than into right subtree */
p->right = addtree(p->right, w);
return p;
}
/* talloc: make a tnode */
struct tnode *talloc(void) {
return(struct tnode *)malloc(sizeof(struct tnode));
}
/* treeprint: in-order print of tree p */
void treeprint(struct tnode *p) {
if(p != NULL) {
treeprint(p->left);
printf("%4d %s\n", p->count, p->word);
treeprint(p->right);
}
}
int getch(void) {
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) {
if(bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
#包括
#包括
#包括
#包括
#包括
#定义MAXWORD 100
#定义BUFSIZE 100
struct tnode{/*树节点:*/
char*word;/*指向文本*/
int count;/*出现次数*/
结构tnode*左;/*左子级*/
结构tnode*右;/*右子级*/
};
struct tnode*addtree(struct tnode*,char*);
结构tnode*talloc(无效);
void treeprint(struct tnode*);
无效未蚀刻(int);
int getword(char*,int);
int getch(无效);
字符buf[BUFSIZE];/*非蚀刻缓冲区*/
int bufp=0;/*buf中的下一个自由位置*/
int main(void){/*字频计数*/
结构tnode*根;
字符字[MAXWORD];
root=NULL;
while(getword(word,MAXWORD)!=EOF)
if(isalpha(字[0]))
root=addtree(root,word);
treeprint(根);
出口(0);
}
/*getword:从输入中获取下一个单词或字符*/
int getword(字符*word,int lim){
int c,getch(无效);
无效未蚀刻(int);
char*w=单词;
while(isspace(c=getch())
;
如果(c!=EOF)
*w++=c;
如果(!isalpha(c)){
*w='\0';
返回c;
}
对于(;--lim>0;w++)
如果(!isalnum(*w=getch()){
未蚀刻(*w);
打破
}
*w='\0';
返回字[0];
}
/*addtree:添加一个w、p或p以下的节点*/
struct tnode*addtree(struct tnode*p,char*w){
int-cond;
如果(p==NULL){/*一个新词已经到达*/
p=talloc();/*创建一个新节点*/
p->word=strdup(w);
p->count=1;
p->left=p->right=NULL;
}如果((cond=strcmp(w,p->word))=0)
p->count++;/*重复单词*/
如果(cond<0)/*小于左子树*/
p->left=addtree(p->left,w);
else/*大于右子树*/
p->right=addtree(p->right,w);
返回p;
}
/*塔洛克:做一个tnode*/
结构tnode*talloc(无效){
return(struct tnode*)malloc(sizeof(struct tnode));
}
/*树打印:按顺序打印树p*/
void treeprint(struct tnode*p){
如果(p!=NULL){
树打印(p->左);
printf(“%4d%s\n”,p->count,p->word);
树打印(p->右);
}
}
int getch(无效){
返回(bufp>0)?buf[--bufp]:getchar();
}
无效取消蚀刻(内部c){
如果(bufp>=BUFSIZE)
printf(“取消蚀刻:字符太多\n”);
其他的
buf[bufp++]=c;
}
@DCoder是对的,这才是真正的答案,因此这篇文章
首先分配单词的行是:
char word[MAXWORD];
程序一次又一次地进入这个记忆。如果不为每个节点复制此数据,它们都会指向此缓冲区。因为如果没有
strdup
,您只需分配变量的地址,以便两者都指向相同的内存(因此数据相同)
使用strdup时,分配一个新的内存块,并将字符复制到新的内存块中:
char *ptr2 = strdup(ptr1);
+----------+ +---------+
| PTR1 |---------->| VALUE |
+----------+ +---------+
+----------+ +---------+
| PTR2 |---------->| VALUE |
+----------+ +---------+
你看到区别了吗?因为如果没有
strdup
,所有节点都会指向同一个内存。但是我们每次都用一个新参数对addtree进行不同的调用,这非常微妙,但我想我已经做到了。是的,但是所说的参数是一个字符串,不是通过=
进行相等性比较,而是与strcmp进行比较,strcmp接受两个字符*
,并将它们分别比较一个字符。所以,即使指向不同字符串的点在数据相等的意义上是相等的(addressess确实是不同的),我明白了,即使word在每次调用addtree时指向不同的字符串,但它的地址是相同的。因此,每个p->单词都会被分配到相同的地址。不,这是相反的。地址改变,数据也不同,但当比较时,如果每个字符相等,则两个字相等。它们的存储位置无关紧要。
char *ptr2 = strdup(ptr1);
+----------+ +---------+
| PTR1 |---------->| VALUE |
+----------+ +---------+
+----------+ +---------+
| PTR2 |---------->| VALUE |
+----------+ +---------+