C:创建索引,我做错了什么?

时间:2017-04-26 18:31:56

标签: c string pointers indexing struct

我创建了下一个索引代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

struct wordlist {
    char *value;
    int *lines;
    struct wordlist *next;
};

int compare (struct wordlist *one , struct wordlist *two) {
    return strcmp(one->value, two->value);
}

void add(struct wordlist **pp, char *value, int line) {

    struct wordlist *new;
    new = malloc(sizeof(*new));
    new->value = value;

    for ( ; *pp != NULL; pp = &(*pp)->next) {
        if (compare(*pp, new) == 0) {
            return;
        }
        else if (compare(*pp, new) > 0) {
            break;
        }
    }

    new->next = *pp;
    *pp = new;
}

void display(struct wordlist *ptr) {

    for (; ptr != NULL; ptr = ptr->next) {
        printf("%s\n", ptr->value);
    }
}

它的代码太多了 所以我打破它提交。遗憾

int main(void) {
    struct wordlist *root = NULL;
    int c;
    char *word;
    word = malloc(sizeof(char*));
    int line = 1;
    for (int i = 0;;i++) {
        c = getchar();
        if (c == EOF) {
            break;
        }
        if (!isalpha(c)) {
            i = -1;
            add(&root, word, line);
            word = malloc(sizeof(char));
            if (c == '\n') {
                line++;
            }
            continue;
        }
        c = tolower(c);
        word[i] = c;
        word = realloc(word,(i+1)*sizeof(char));
    }
    display(root);

    return 0;
}

假设每个不是a-z或A-Z字符的东西都会破坏字符串。

当我通过给他一个像

这样的字符串来调试我的代码时
  

yonatan.lif

他在打印:

  

lif yonatanp

因为我的输出应该是

  

lif yonatan

(我不希望&#39; p&#39;或任何其他字符在那里)

只要输入的字符串之后的字符长度就越长

它有效,但它以我用长输入描述的方式起作用,我无法弄清楚原因。你能帮我弄清楚我做错了吗?

感谢所有帮助者。

1 个答案:

答案 0 :(得分:2)

当您使用大多数标准标头提供的功能时,

C中的字符串必须为空终止 ,例如strcmp(),{{1} }, 等等。来自strcmp()的参考号:

  

此函数开始比较每个字符串的第一个字符。   [...]它继续[...] 直到终止空字符为止   达到

这是导致您正在调用的 Undefined Behavior 的原因,但不是null终止您的字符串。为此,请将代码修改为:

printf()

现在你的单词将被终止,你的程序将正常运行。

以下是您的计划发生了什么情况(应该拿一张纸和一支铅笔,并在下次绘制您的代码所做的事情。)

  1. word[i] = '\0'; i = -1; add(&root, word, line); 指向&#34; yonatan&#34;。
  2. 你肉#39;。#,因此word被召唤。
  3. 创建了add()结构,其成员new成员 设置为nextrootNULLvalue所指的位置, 和word ......这个成员将保持未初始化(它应该 可能被设置为0,但你知道的更好。)
  4. 我们继续,现在line忘记&#34; yonatan&#34;并指出 &#34; LIF&#34;
  5. 再次调用
  6. word,其中创建了另一个add()结构 它的new到&#34; lif&#34;及其value到先前创建的 结构,在第3步。这就是为什么你的单词将被保留打印的原因 从他们的输入订单。 next将再次未初始化。
  7. 调用
  8. line,但display()格式寻求null 停止的终止符,你的字符串可能缺少,从而调用 未定义的行为(你正在见证的垃圾字符,如 &#39; P&#39;)
  9. 现在你应该问我的for循环和%s函数怎么样?第二次调用compare()后,您将进入该循环,并调用add()函数,但没有空终止字符串compare()无法正常工作,我的猜测是它返回一个垃圾正值,打破了循环。

    PS:不是问题,但可能会引起读者的困惑:

    strcmp()

    为什么要为指针分配空间?你可能只是为了这个:

    char *word;
    word = malloc(sizeof(char*));