【问题标题】:strcpy() to copy string from struct member to char array is failing. Why?strcpy() 将字符串从 struct 成员复制到 char 数组失败。为什么?
【发布时间】:2019-05-09 09:05:20
【问题描述】:

我有一个结构node,用于创建二叉搜索树。在每个节点中,我存储了一个整数 KEY 和一个相应的字符串 value。我正在树中执行一些搜索,并希望返回仅包含特定节点的键值对的数组。

为此,我通过引用传递数组并将整数 KEY 保存到该数组。这很好用,但是当我尝试使用相同的字符串时,我得到的结果很差。

在下面的代码中,我试图将root[count].value; 中的字符串复制到p_value_arr[*p_unique_count],这是一个字符数组。

结构定义

   typedef struct node {
        int KEY;
        char *value;
        int node_count;
        struct node *left, *right;
        int unique_count;
    } node;

遍历图和复制唯一键值对的功能。 KEY 被正确复制到数组中,而 value 没有。

void unique_key(node *root, int *p_unique_count, int p_unique_arr[], char *p_value_arr[]) { 
    int count = 0;      
    //unique *temp = (unique *)malloc(n * sizeof(unique));
        
    if (root != NULL)
    {
        unique_key(root->left, p_unique_count, p_unique_arr, p_value_arr);
        if (root->node_count == 1) {

            root[count].unique_count = *p_unique_count;
            p_unique_arr[*p_unique_count] = root[count].KEY;
            printf("%s\n", root[count].value);
            //"warning: assignment makes integer from pointer without a cast"
            strcpy(p_value_arr[*p_unique_count],root[count].value);  
                        
            printf("%d(%d) -> %s %d\n", root->KEY, root->node_count, root->value, root->unique_count);
                        (*p_unique_count)++;
            count++;
        }
        unique_key(root->right, p_unique_count, p_unique_arr, p_value_arr);
    }
}

使用 BST 中的给定键插入新节点的实用函数

node* insert_node(node* node, int key, char *value)
{
    /* If the tree is empty, return a new node */
    if (node == NULL) 
        return newNode(key,value);

    // If key already exists in BST, icnrement count and return 
    if (key == node->KEY)
    {
        (node->node_count)++;
    //  return node;
    }

    /* Otherwise, recur down the tree */
    if (key < node->KEY)
        node->left = insert_node(node->left, key, value);
    else
        node->right = insert_node(node->right, key, value);

    /* return the (unchanged) node pointer */
    return node;
}

node *newNode(int KEY, char *value)
{
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->KEY = KEY;
    strcpy(temp->value, value);
    temp->left = temp->right = NULL;
    temp->node_count = 1;
    return temp;
}

主驱动代码

int main() {
    int unique_count = 0;
    int in_count = 0;
    int unique_arr[10]; /
    char *value_arr[10];   // an array of pointers  
    
    /* Let us create following BST.  Passing values along with key */
    node *root = NULL;
    
    //this is for storing commands 
    root = insert_node(root, 2, "Hello");
    root = insert_node(root, 3, "Thanks");

    printf("\nkeys of the given tree \n");
    unique_key(root, &unique_count, unique_arr, *value_arr);
    for(int i = 0; i < 10; i++) {                
        printf("%d %s\n", unique_arr[i], value_arr[i]);  //Mismatching the argument type "char" and conversion specifier "s" and nothing prints here
    }
   
}

输出:

你好

给定树的键

分段错误

关于如何有效地将结构成员中的字符串复制到字符数组中的任何建议?


编辑:

完整代码: https://pastebin.com/CB4Gp0gY

由于char *value_arr[10]; 是一个指针数组,我按照 K&R The C 编程语言的第 5.6 章将指针数组传递给函数。我现在没有收到任何警告,但段错误仍然存​​在。

我还在我的 NetBeans 8.2 上设置了 more warnings

调试器的输出:

/cygdrive/C/Users/****/AppData/Roaming/NetBeans/8.2/bin/nativeexecution/dorun.sh: line 71: 16516 Segmentation fault      (core dumped) sh "${SHFILE}"

【问题讨论】:

  • 您将char * 类型的值分配给char 类型的数组元素。如果您的编译器没有发出警告,请调高警告级别。无论如何,这似乎是你的问题。
  • temp-&gt;value = value; 这是指针的软拷贝,而不是字符串本身的拷贝。这意味着您的所有值指针都可能指向相同的文本。请参阅How to correctly assign a new string value? 如果您来自某种高级语言,则需要确认 C 没有字符串类。
  • 编译器是你的朋友。确保警告级别已调高,并注意它发出的警告。特别要注意(并解决)您现在应该在调用函数 unique_key 时收到的关于指针类型不匹配的警告。
  • 为什么这不是一个特定的编程问题?我无法使用strcpy() 将字符串从结构成员复制到数组。请提出建议,我会尽量使问题更具体。
  • 我看不到您实际为 char 数组分配任何空间的位置。我看到您为一个节点分配空间,然后立即将一个字符串复制到一个未初始化的(并且可能是完全随机的)指针。请参阅@Lundin 的链接。

标签: c arrays function pointers


【解决方案1】:

char *value_arr[10]; // 问题出在这里

这会初始化一个指针数组,但在将它们用于strcpy() 之类的东西之前不会为这些指针分配内存。根据 K&R 第 5.6 章,应该使用 alloc() 为函数内部的指针数组分配内存。

如果你想让一个指针指向一些内存来存储一个字符串,那么你必须创建这样一个内存区域并设置指针指向它。

 char *p;

 alloc(strlen(root[count].value) +1);

 strcpy(p, root[count].value);
 p_value_arr[*p_unique_count] = p;

【讨论】:

    【解决方案2】:

    我会在这里跟进 Lundin 的情况

    node *newNode(int KEY, char *value)
    {
      // Allocate a new overall structure
      struct node *temp = (struct node *)malloc(sizeof(struct node));
    
      //Copy the integer key
      temp->KEY = KEY;
    
      // uh oh - copy the given string into a random location in memory and segfault.
      // Hint - you need to allocate enough memory to hold the incoming string.
      // Advanced hint - If you don't want to make a copy of the string, you can 
      // just store its pointer, but it would want to be marked constant at the least... 
      strcpy(temp->value, value);
    
      // Set tree stuff and count, but we are already dead...
      temp->left = temp->right = NULL;
      temp->node_count = 1;
      return temp;
    }
    

    还有,

    printf("%d %s\n", unique_arr[i], value_arr[i]);  //Mismatching the argument type "char" and conversion specifier "s" and nothing prints here
    

    将失败,因为value_arr[i] 不是字符串,而是char *。为此,它必须指向一个有效的 C 字符串,或者需要指向具有正确 '\0' 终止字符串的内存。

    查看他给出的链接,因为您需要更深入地了解 C 字符串的工作原理。

    【讨论】:

    • 感谢您的回答。在使用temp-&gt;value = value; 存储后,我正在正确打印root[count].value。这不是表明*newNode 正确存储了字符串吗?
    • 按原样,您正在使用 strcpy() 调用未定义行为 (UB)。因此,任何事情都可能发生。由于您在字符串内存管理方面遇到问题,请考虑使用固定大小的 char 数组,直到您掌握它们为止。
    猜你喜欢
    • 2022-01-14
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2016-12-21
    • 2015-06-12
    相关资源
    最近更新 更多