我有一个函数可以将字符串的内容从十六进制符号转换为二进制符号. 在我的简单示例中,我只使用了两个十六进制符号ab,并且相同的字符串被转换了两次.

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

char * decode_hex(char hex[])
{
   static char bin[9];
   bin[0] = '\0';
   for (int i=0; hex[i]!='\0'; i++)
   {
        switch(hex[i])
        {
            case 'a':
                strcat(bin, "1010");
                break;
            case 'b':
                strcat(bin, "1011");
                break;
        }
    }
    return  bin;
}

int main()
{
   char *r = malloc(9);
   for (int i=0; i<2; i++)
   {
      r[0] = '\0';
      strcat(r, "ab");
      printf("Original string:  %s\n", r);
      r = decode_hex(r);
      printf("Converted string: %s\n\n", r);
   }
}

在第一次传递中,函数返回正确的转换字符串,但在第二次传递中返回空字符串.

Original string:  ab
Converted string: 10101011

Original string:  ab
Converted string:

有人能告诉我为什么会这样吗?

ADDITION

我知道我可以使用两个单独的字符串省略这个问题:

int main()
{
   char h[3];
   char *r = malloc(9);
   for (int i=0; i<2; i++)
   {
      h[0] = '\0';
      strcat(h, "ab");
      printf("Original string:  %s\n", h);
      r = decode_hex(h);
      printf("Converted string: %s\n\n", r);
   }
}

但我想知道是否有可能像这样重复使用字符串

r = decode_hex(r)

以及如何避免内存泄漏?

推荐答案

函数decode_hex返回指向静态数组bin的第一个字符的指针:

char * decode_hex(char hex[])
{
   static char bin[9];
   //...
   return  bin;
}

因此,在函数的第一次调用之后,Main中定义的指针r被返回的指针重新赋值

r = decode_hex(r);

因此,该程序会产生内存泄漏,因为以前分配的内存地址现在已丢失.

在第二个调用中,这些语句

  r[0] = '\0';
  strcat(r, "ab");

在函数中声明的静态array.当函数被调用时,它立即将其静态数组的第一个字符设置为终止零字符'\0':

char * decode_hex(char hex[])
{
   static char bin[9];
   bin[0] = '\0';
   //...

因此,在本例中,数组bin包含一个空字符串,而参数hex又指向这个具有空字符串的array.

在函数中使用静态数组是不好的,而且使用等于某个幻数的固定大小.始终try 编写更通用的函数.

该函数应动态创建一个新数组,其中将存储传递的字符串的二进制表示形式.传递给函数的数组应该保持不变.

我可以建议如下函数实现,如下面的演示程序所示.

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

char * decode_hex( const char hex[] )
{
    size_t n = strlen( hex );

    char *bin = malloc( 4 * n + 1 );

    if (bin != NULL)
    {
        bin[4 * n] = '\0';

        for (size_t i = n, j = 4 * n; i-- != 0; )
        {
            unsigned char c = hex[i];
            c = toupper( c );

            if (c > '9') c = 10 + c - 'A';
            else c -= '0';

            for (size_t k = 0; k < 4; ++k)
            {
                bin[--j] = '0' + c % 2;
                c /= 2;
            }
        }
    }

    return bin;
}

int main( void)
{
    const char *hex = "ab";

    puts( hex );

    char *bin = decode_hex( hex );

    if (bin) puts( bin );

    free( bin );

    hex = "123456789abcdef";

    puts( hex );

    bin = decode_hex( hex );

    if (bin) puts( bin );

    free( bin );
}

程序输出为

ab
10101011
123456789abcdef
000100100011010001010110011110001001101010111100110111101111

注:一开始,我在这条语句中打错了字

if (c > 9) c = 10 + c - 'A';
       ^^^

现在,代码已更新,语句看起来如下所示

if (c > '9') c = 10 + c - 'A';
        ^^^

C++相关问答推荐

理解没有返回语句的递归C函数的行为

由Go调用E.C.引起的内存快速增长

*p[num]和(*p)num的区别

DPDK-DumpCap不捕获端口上的传入数据包

如何在C中通过套接字自定义数据类型读取原始变量?

为什么sscanf不能正确地从这个字符串格式中提取所有数字?

Sizeof(&Q;字符串&Q;)的正确输出是什么?

如何在下面的C代码中正确管理内存?

在句子中转换单词的问题

一旦运行长度超过2,编译器是否会优化";strnlen(mystring,32)>;2";以停止循环?

我的C函数起作用了,但我不确定为什么

MacOS下C++的无阻塞键盘阅读

C11/C17标准允许编译器清除复合文字内存吗?

C:Assignment中的链表赋值从指针目标类型中丢弃‘const’限定符

GETS()在C++中重复它前面的行

atoi函数最大长-长误差的再创造

无法理解 fgets 输出

为什么INT_MIN是在c语言的头文件limits.h中定义的(-INT_MAX-1)而不是直接使用-2147483648

使用邻接表创建图

段错误try 访问静态字符串,但仅有时取决于构建环境