Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 字符指针赋值_C_Pointers - Fatal编程技术网

C 字符指针赋值

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

这里是程序的代码,该程序计算某些输入中所有单词的出现次数。摘自《K和R》一书。除了作者为什么要使用strdup()之外,我几乎什么都懂。为什么我们不能(在函数addtree中)赋值
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  |
+----------+           +---------+