【问题标题】:integer array to char pointer string整数数组到 char 指针字符串
【发布时间】:2019-02-23 09:21:29
【问题描述】:

我正在尝试将 int 数组转换为 char 指针字符串(数组值转换为十六进制)。我正在使用代码块编辑器。
所以,

                           int arr[4] = {30, 40, 15, 205};

应该转换成

                            char *str =  "1e280fcd";

为此,我编写了以下程序:

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

int main()
{
    char *cur_str, *prev_str;
    char *comp_str, *comp_str_copy;
    int arr[] = {30,40,15,205}, i, j, arr_length;
    arr_length = (sizeof(arr)/sizeof(arr[0]));
    prev_str = malloc(sizeof(0));
    cur_str = malloc(sizeof(0));
    comp_str = malloc(sizeof(0));
    for(i=0;i<arr_length;i++)
    {
        cur_str = malloc(2);
        sprintf(cur_str,"%02x",arr[i]);

        comp_str = malloc(sizeof(cur_str)+sizeof(prev_str));
        sprintf(comp_str,"%s%s",prev_str,cur_str);
        printf("%s\n",comp_str);

        free(prev_str);
        prev_str = malloc(sizeof(comp_str));
        sprintf(prev_str,"%s",comp_str);

        if(i==(arr_length-1)){
            comp_str_copy = malloc(sizeof(comp_str));
            sprintf(comp_str_copy,"%s",comp_str);
        }

        free(comp_str);
        free(cur_str);
    }
    printf("%s %d\n",comp_str_copy,strlen(comp_str_copy));
    return 0;
}

这个程序的输出要么是

  • 分段错误或
  • 在初始位置具有垃圾值的字符串

我在不同的在线编译器上运行过相同的程序。他们都给出了正确的字符串作为输出。是我使用的编辑器有问题还是我的内存管理方法?

【问题讨论】:

  • sizeof(0)sizeof(int),大部分是 4。sizeof(cur_str)sizeof(prev_str)sizeof(char*),可能是 8。我想你的意思是 strlen 那里。
  • 另外不要忘记 C 中的 char 字符串实际上称为 null-terminated 字节字符串。 null-terminator 也需要空格(这意味着两个字符的字符串需要 三个 的空格)。
  • 您的输出是纯文本。请将此文本复制并粘贴到您的问题中,而不是添加图像。它们不会增加价值。

标签: c memory-management malloc


【解决方案1】:

    cur_str = malloc(2);
    sprintf(cur_str,"%02x",arr[i]);

sprintf写了3个字符,包括最后一个空字符,而你只分配了2个

comp_str = malloc(sizeof(cur_str)+sizeof(prev_str));

分配长度不是正确的,因为size_of 没有返回您所期望的,必须是

comp_str = malloc(strlen(cur_str)+strlen(prev_str)+1);

但当然假设prev_str开头也是一个正确的字符串,事实并非如此

这两个malloc会产生内存泄漏,因为没有空闲(也没有使用)

cur_str = malloc(sizeof(0));
comp_str = malloc(sizeof(0));

为什么不使用realloc来增加prev_str的大小?

注意最终需要的大小很容易知道:sizeof(arr)/sizeof(arr[0]) * 2 + 1 如果数字限制为 255(十六进制中的 2 位)

一个提案(不假设所有数字

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

int main()
{
    int arr[] = {30,40,15,205};
    size_t arr_length = sizeof(arr)/sizeof(arr[0]);
    size_t i;
    size_t sz = 0;
    char * r = malloc(0);

    for (i=0; i!= arr_length; ++i)
    {
      char s[20];
      int l = sprintf(s, "%02x",arr[i]);

      r = realloc(r, sz + l + 1);
      strcpy(r + sz, s);
      sz += l;
    }
    printf("%s %d\n", r, sz);
    free(r);
    return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra a.c
pi@raspberrypi:/tmp $ ./a.out
1e280fcd 8

valgrind下执行

pi@raspberrypi:/tmp $ valgrind ./a.out
==2985== Memcheck, a memory error detector
==2985== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2985== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2985== Command: ./a.out
==2985== 
1e280fcd 8
==2985== 
==2985== HEAP SUMMARY:
==2985==     in use at exit: 0 bytes in 0 blocks
==2985==   total heap usage: 6 allocs, 6 frees, 1,048 bytes allocated
==2985== 
==2985== All heap blocks were freed -- no leaks are possible
==2985== 
==2985== For counts of detected and suppressed errors, rerun with: -v
==2985== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

【讨论】:

    【解决方案2】:

    对于一个简单的任务来说,这是很多动态内存分配。如果数组和字符串保持“小”,则使用堆栈对您有利:

    #include <assert.h>
    #include <stdio.h>
    
    int main() {
        int const arr[] = {30, 40, 15, 205};
        int const arr_length = sizeof(arr) / sizeof(arr[0]);
        char str[2 * arr_length + 1];
        int len = 0;
        for (int i = 0; i < arr_length; i++) {
            len += sprintf(&str[len], "%02x", arr[i]);
        }
        assert(len == 2 * arr_length);
        printf("%s %d\n", str, len);
        return 0;
    }
    

    但如果你真的需要一个动态字符串,即char *str只需将char str[2 * arr_length + 1];修改为

    char *str = malloc(2 * arr_length + 1);
    

    并添加free(str);

    注意:所有这些都假设您的整数数组值小于 256。

    【讨论】:

      【解决方案3】:

      以下建议的代码:

      1. 消除了不需要的代码逻辑
      2. 消除不需要的变量
      3. 消除了对动态内存的不必要使用
      4. 干净编译
      5. 没有段错误
      6. 执行所需的功能
      7. 注意strlen() 返回的是size_t,而不是int
      8. 注意sizeof() 返回的是size_t 而不是int
      9. 将数组 arr[] 的长度乘以 2 以计算显示转换后数组所需的字符数
      10. 将计算的长度加 1 以允许尾随 NUL 字节
      11. 按必要顺序列出变量,以便在需要时始终提供特定参数

      现在,建议的代码:

      #include <stdio.h>
      #include <string.h>
      
      int main( void )
      {
          int arr[] = {30,40,15,205};
          char comp_str[ sizeof( arr )*2 +1 ] = {'\0'};  
      
          size_t arr_length = (sizeof(arr)/sizeof(arr[0]));
      
          for( size_t i=0; i<arr_length; i++ )
          {          
              sprintf( comp_str,"%s%02x", comp_str, arr[i] );
              printf("%s\n",comp_str);
          }
      }
      

      运行建议的代码会导致:

      1e
      1e28
      1e280f
      1e280fcd
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 2020-11-21
        • 2021-08-20
        • 1970-01-01
        • 1970-01-01
        • 2016-06-27
        相关资源
        最近更新 更多