【问题标题】:In C I am getting segmentation fault, i do not know why在 C 中我遇到分段错误,我不知道为什么
【发布时间】:2018-11-30 01:35:21
【问题描述】:

我正在制作一个在一个实例中存储多个事物的二叉搜索树,我遇到了两个错误。函数insert 中发生的第一个用于工作而不是随机停止,第二个在print_tree_inorder 中,我不知道为什么会被破坏。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h> 
#include <string.h>
#include <malloc.h>


char* nameArray[50] = {};
char* number[50] = {};
char* ID[50] = {};
char* hours[50] = {};
char* pPH[50] = {};
int flag;
typedef struct node
{

    char* name;
    char* phoneNum;
    char* ID;
    char* hours;
    char* pPH;
    struct node * left;
    struct node * right;
} node_t;




void insert(node_t * tree, char* name, char* phoneNum, char* hours, char* pPH);
void print_tree_inorder(node_t * current);

int main()
{
    char* n,p,id,h,pph;
    int numberOfTimes = 0;

    node_t * test_list = malloc(sizeof(node_t));

    /* set values explicitly, alternative would be calloc() */
    test_list->name =  "";
    test_list->phoneNum = "";
    //test_list->ID = "";
    test_list->hours = "";
    test_list->pPH = "";


    test_list->left = NULL;
    test_list->right = NULL;
    printf("Please enter in the amount of people you want: ");
    scanf("%d",&numberOfTimes);
    printf("\n");

         for(int i = 0; i<numberOfTimes; i++){
             printf("Please enter in name: ");
             scanf("%s", &n);
             nameArray[i] = n; 

             printf("Please enter in PhoneNumber: ");
             scanf("%s", &p);
             number[i] = p;
             printf("Please enter in Hours: ");
             scanf("%s", &h);
             hours[i] = h;
             //printf("\n");
             printf("Please enter in pay per hour: ");
             scanf("%s", &pph);
             pPH[i] = pph;


            insert(test_list,nameArray[i],number[i],hours[i], pPH[i] );

        }

    printf("\n In order\n");
    print_tree_inorder(test_list);
}

void insert(node_t * tree, char* name, char* phoneNum,  char* hours, char* pPH)
{  
    //unsigned int number = (unsigned int)ptr

    if (tree->name == 0)
    {
        /* insert on current (empty) position */
        tree->name = name;
        tree->phoneNum = phoneNum;
        //tree->ID = ID;
        tree->hours = hours;
        tree->pPH = pPH;
    }
    else
    {

        if ( strcmp(tree->name, name) > 0)
        {
            /* insert left */
            if (tree->left != NULL)
            {
                insert(tree->left, name, phoneNum, hours, pPH);
            }
            else /* no left nodes*/
            {
                tree->left = malloc(sizeof(node_t));
                /* set values explicitly, alternative would be calloc() */
                tree->left->name = name;
                tree->left->phoneNum = phoneNum;

                tree->left->hours = hours;
                tree->left->pPH = pPH;
                tree->left->left = NULL;
                tree->left->right = NULL;
            }
        }
        else /*add node to right */
        {
            if ( strcmp(tree->name, name) <= 0)
            {
                /* insert right */
                if (tree->right != NULL)
                {
                    insert(tree->right, name, phoneNum,  hours, pPH);
                }
                else
                {
                    tree->right = malloc(sizeof(node_t));
                    /* set values explicitly, alternative would be calloc() */
                    tree->right->name = name;
                    tree->right->phoneNum = phoneNum;

                    tree->right->hours = hours;
                    tree->right->pPH = pPH;
                    tree->right->left = NULL;
                    tree->right->right = NULL;
                }
            }
        }
    }

}

void print_tree_inorder(node_t * current) {
    if (current == NULL) return;
    print_tree_inorder(current->left);
    printf(" %s %s %s %s\n", current->name, current->phoneNum,current->hours, current->pPH);

    print_tree_inorder(current->right);
}

【问题讨论】:

  • 查看char* n; .... scanf("%s", &amp;n);。名称保存在哪里?
  • 那是后面的代码。调用scanf("%s", &amp;n) 保存的名称在哪里? n 是指向无处的指针。 scanf("%s", &amp;n); 应该引起警告。你用的是什么编译器?
  • 这段代码有很多东西,比我期望的 C 新手开始的要多得多。查看如何读取一行用户输入并将其保存为字符串,然后再打印。 char buf[80]; scanf("%79s", buf); printf("%s\n", buf);
  • 也可以在insert方法中去掉第二个strcmp。
  • @GlenvillePecor - 将警告视为错误

标签: c binary-search-tree


【解决方案1】:

您的代码中有几个问题。首先you should not include malloc.h。它已被弃用。

看起来n,p,id,h,pph 变量的声明有些混乱。本声明:

char* n,p,id,h,pph;

仅将n 声明为char * 类型,其余变量p,id,h,pph 声明为char 类型。

让我们谈谈编译器报告的警告(我使用gcc编译器并在编译期间提供-Wall-Wextra选项):

$ gcc -Wall -Wextra prg.c 
prg.c:56:26: warning: format specifies type 'char *' but the argument has type 'char **' [-Wformat]
             scanf("%s", &n);
                    ~~   ^~
prg.c:61:24: warning: incompatible integer to pointer conversion assigning to 'char *' from 'char'; take the address with & [-Wint-conversion]
             number[i] = p;
                       ^ ~
                         &
prg.c:64:23: warning: incompatible integer to pointer conversion assigning to 'char *' from 'char'; take the address with & [-Wint-conversion]
             hours[i] = h;
                      ^ ~
                        &
prg.c:68:21: warning: incompatible integer to pointer conversion assigning to 'char *' from 'char'; take the address with & [-Wint-conversion]
             pPH[i] = pph;
                    ^ ~~~
                      &
prg.c:35:15: warning: unused variable 'id' [-Wunused-variable]
    char* n,p,id,h,pph;
              ^
5 warnings generated.

您不应忽略编译器警告消息。他们在那里是出于某种原因。

警告 1:
nchar * 类型,因此 &amp;nchar ** 类型。 scanf() 中的 %s 格式说明符需要将参数作为一个数组,并且该数组必须至少有空间容纳 input_size+1 个字符。

您应该将n 声明为字符数组,如下所示:

char n[50];
// and for input
scanf("%49s", n);

警告2

pchar 类型,number[i]char * 类型。因此,分配是不兼容的。 &amp;p 也是 char * 类型,这就是为什么编译器没有报告任何关于语句的警告:

scanf("%s", &p);

但这是不正确的,因为pchar 类型,它没有足够的空间来输入字符串。阅读有关scanf() 格式说明符的更多信息。

你可以这样做:

char p[50];
// and for input
scanf("%49s", p);
number[i] = strdup(p);

如果不使用strdup,则number 数组的所有指针最终都指向同一位置。或者,您可以将p 声明为char * 并显式处理内存分配/释放操作。完成后,确保freestrdup 返回的内存。 警告 34 的解释相同。

警告 5:
从代码中删除未使用的变量。

您的代码有一定的改进空间。尝试自己弄清楚它们。

【讨论】:

  • TY 这真的会帮到我!