0

使用此结构定义:

struct word {
    char *cont; //content of the word
    char *wsp; //whitespace following the word
    int ctr;
};

一句话,我正在尝试编写一个函数来从标准输入中获取第一个单词,然后是所有空格。这里是:

struct word *getword(){
    char cont[WORDLIM];
    char wsp[WORDLIM];
    cont[0] = '\0';
    wsp[0] = '\0';
    if (peekchar() == EOF) return NULL; //peekchar defined elsewhere as getting a char and ungetc-ing it

    REPEAT{ //macro for for(;;)
            char c = getchar();
            char buf[2];
            buf[0]=c;
            buf[1]='\0';
            if (c == '\n' || c == ' '){
                    strcat(wsp, buf);
                    if (peekchar() != '\n' && peekchar() != ' '){
                            struct word *toret;
                            toret = malloc(sizeof(struct word));
                            toret->cont = cont;
                            toret->wsp = wsp;
                            toret->ctr = -1;
                            printf("---%s---\n", toret->wsp); //just for debugging
                            return toret;
                    }
                    continue;
            }
    }
    printf("PANIC PANIC PANIC THIS IS GOING WROOOOONG!!!!!\n");
    return NULL;
}

现在有趣的是,我可以在仅用于调试的行中获得正确的空白输出,但是当我尝试访问 getword()->wsp 时,我得到了随机垃圾。更有趣的是, getword()->cont 有效...

我是 C 的新手……我做错了什么?

4

3 回答 3

4

您正在返回指向超出范围的内存的指针。

您动态分配 a struct word,但实际字符保存在wsp数组中。一旦你的函数返回,那就超出了范围,所以可以包含任何东西。

于 2013-01-29T19:44:33.660 回答
3
REPEAT{ //macro for for(;;)

失去那个宏后急速。使用预处理器去丑化 C 语法是胃灼热的秘诀。只需使用for(;;)or while(1)。编译器通常足够聪明,可以将其变成无条件跳转。

至于你的问题:

toret->cont = cont;
toret->wsp = wsp;

cont和数组在函数wsp本地声明getword;一旦函数退出,数组就不再存在,任何指向它们的指针都不再有效。您需要做的是除了为自身 分配内存之外,还为cont和的wsp成员分配内存。torettoret

toret = malloc(sizeof(struct word));
if (toret) // ALWAYS check the result of a `malloc` call
{
  toret->cont = malloc(strlen(cont) + 1);
  if (toret->cont)
    strcpy(toret->cont, cont);
  toret->wsp = malloc(strlen(wsp) + 1);
  if (toret->wsp)
    strcpy(toret->wsp, wsp);
  ...
}

请注意,当您需要为结构释放内存时,您首先需要为contandwsp成员释放内存。

于 2013-01-29T19:50:13.847 回答
1

*toret是程序中的悬空指针

于 2013-01-29T19:46:25.903 回答