二叉搜索树上的段错误 - 大排序

时间:2017-09-16 18:28:53

标签: c string algorithm sorting pointers

尝试this Big Sorting problem on Hackerrank。我知道有更简单的方法来编写算法,但我正在努力提高我的C知识,因此我想挑战自己并为此问题编写二进制搜索树。

我写的二进制搜索树似乎适用于整数,但问题是数字形式的输入类型的字符串。所以我尝试将其更改为使用字符数组,并strcmp()以便比较数字字符串。

有人可以帮我弄清楚这里发生了什么,以及我如何解决这个问题?

波段-故障:

GDB trace:
Reading symbols from solution...done.
[New LWP 11287]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  strlen () at ../sysdeps/x86_64/strlen.S:106
#0  strlen () at ../sysdeps/x86_64/strlen.S:106
#1  0x00007f4f76b2e455 in __strcpy_chk (dest=0xfb0020 "", src=0x0, 
    destlen=105) at strcpy_chk.c:28
#2  0x00000000004007e3 in strcpy (__src=0x0, __dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string3.h:110
#3  create_node (key=0x0) at solution.c:25
#4  0x00000000004006af in main () at solution.c:70

代码:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

#define MAXLEN 105

struct tree_node {
    char key[MAXLEN];
    struct tree_node *left;
    struct tree_node *right;
}; typedef struct tree_node Node;

Node *create_node(char *key) {
    Node *new_node;

    if ((new_node = (Node*)malloc(sizeof(Node))) == NULL) {
        printf("Cannot allocate memory for new node");
        exit(1);
    }

    strcpy(new_node->key, key);

    //new_node->key = key;
    new_node->left = NULL;
    new_node->right = NULL;

    return (new_node);
}

Node *insertNode(Node *node, char *keyInput) {
    if (node == NULL) {
        return (create_node(keyInput));
    } else {
        if (strcmp(keyInput, node->key) <= 0) {
            node->left = insertNode(node->left, keyInput);
        } else {
            node->right = insertNode(node->right, keyInput);
        }
        return (node);
    }
    return 0;
}

void printTree(Node *tree) {
    if (tree != NULL) {
        printTree(tree->left);
        printf("%s\n", tree->key);
        printTree(tree->right);
    }
}

int main() {
    // Enter your code here. Read input from STDIN. Print output to STDOUT
    int i, n = 0;
    char *input;
    Node *tree = NULL;

    scanf("%d", &n);

    for (i = 0; i < n; i++) {
        scanf("%s", input);
        tree = insertNode(tree, input);
    }

    printTree(tree);

    return 0;
}

2 个答案:

答案 0 :(得分:1)

将未初始化的指针传递给scanf()以读取字符串。您应该将input定义为数组:

int main(void) {
    // Enter your code here. Read input from STDIN. Print output to STDOUT
    int i, n;
    char input[105];
    Node *tree = NULL;

    if (scanf("%d", &n) == 1) {
        for (i = 0; i < n; i++) {
            if (scanf("%104s", input) != 1)
                break;
            tree = insertNode(tree, input);
        }
        printTree(tree);
    }
    return 0;
}

这种方法的问题在于它不适合问题空间:

  • 该网站称这些行包含以十进制编码但没有前导零的数字,但最多包含10个 6 字节。您无法使用`scanf()。
  • 轻松有效地解析此类输入
  • 此外,strcmp()不适合比较这些条目:您应首先比较长度,并仅对具有相同位数的条目使用strcmp()

答案 1 :(得分:1)

关注点:

char *input;
for (i = 0; i < n; i++) {
    scanf("%s", input);
}

将要存储的读取字符串在哪里? input是指向有效内存空间附近的char指针!

让我们通过将其定义为数组来为它分配一些内存:

char input[MAXLEN];
for (i = 0; i < n; i++) {
    scanf("104%s", input);
}

不要忘记空终止符所需的空间,这就是我使用104(MAXLEN - 1)的原因,这是一种预防措施,以便不占用比{{1}更多的内存可以存储。

此外,您可以利用CloudFront返回的内容并执行此操作:

input