【问题标题】:Converting binary to string from one location to other将二进制文件从一个位置转换为字符串到另一个位置
【发布时间】:2021-04-08 21:00:44
【问题描述】:

我正在尝试将数据从二进制形式转换为字符串资源, 到目前为止,我得到了这段代码,但它不能正常工作,有任何建议吗? 代码是c/c++

char* binaryToString(char* b) {
    int length = strlen(b);
    char* result = (char*)malloc(length / 8);
    for (int i = 0; i < length; i++, b += 8) {
        result[i] = strtol(b, NULL, 2);
    }
    return result;
}

【问题讨论】:

  • 请解释每一行代码背后的想法。输入是什么?实际输出是多少?您期望的输出是什么?
  • 您问的是 C 还是 C++?它们不是同一种语言,答案可能不同。

标签: c++ c byte converters


【解决方案1】:

您分配了一个 length/8 元素数组,但您在索引 0 到 length - 1 处写入 => 您从分配的数组中写入,行为未定义

替换

char* result = (char*)malloc(length / 8);

通过

char* result = malloc(length);

或者当然改变你的循环

目前您也很可能会从 b 管理的数组中读出,因为您每次进步 8 个字符,所以您从索引 0 调用 strtol,然后是 8 ...然后8*(length-1),将数组读取为未定义行为

其他问题

  • 您将charlong 分配给您的数组,您真的要这样做吗?
  • strtol 肯定不会像你在输入字符串中那样产生你期望的值

根据您的评论,一种方法是:

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

char* binaryToString(char * b)
{
  size_t n = (strlen(b) + 7) / 8;
  char * result = malloc(n + 1);
  size_t i;
  
  for (i = 0; i < n; i++, b += 8) {
    char s[9];
    
    strncpy(s, b, 8);
    s[8] = 0;
    result[i] = (char) strtol(s, NULL, 2);
  }
  result[i] = 0;
  
  return result;
}

int main(int argc, char ** argv)
{
  while (--argc) {
    argv += 1;
    
    char * r = binaryToString(*argv);
    
    printf("%s -> %s\n", *argv, r);
    free(r);
  }
  
  return 0;
}

我使用缓冲区复制每个最多 8 个字符的块,以不修改输入字符串。

警告:

  • 假设 char 可以支持从 0 到 255 的值(请参阅 CHAR_BIT
  • 即使 strtol 允许这样做,也不会检查输入字符串的有效性。
  • 如果输入字符串的长度不是 8 的倍数但大于 8,即使没有未定义的行为,结果也不是预期的。
  • 结果可以包含不可读的字符,包括在分配数组的最后位置放置的空字符之前的空字符。

编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall -g cv.c 
pi@raspberrypi:/tmp $ 
pi@raspberrypi:/tmp $ ./a.out 01100001011100110110010001100110 100001 0110000100000000011100110110010001100110
01100001011100110110010001100110 -> asdf
100001 -> !
0110000100000000011100110110010001100110 -> a
pi@raspberrypi:/tmp $ 
pi@raspberrypi:/tmp $ valgrind ./a.out 01100001011100110110010001100110 100001 0110000100000000011100110110010001100110
==12327== Memcheck, a memory error detector
==12327== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12327== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==12327== Command: ./a.out 01100001011100110110010001100110 100001 0110000100000000011100110110010001100110
==12327== 
01100001011100110110010001100110 -> asdf
100001 -> !
0110000100000000011100110110010001100110 -> a
==12327== 
==12327== HEAP SUMMARY:
==12327==     in use at exit: 0 bytes in 0 blocks
==12327==   total heap usage: 4 allocs, 4 frees, 1,037 bytes allocated
==12327== 
==12327== All heap blocks were freed -- no leaks are possible
==12327== 
==12327== For lists of detected and suppressed errors, rerun with: -s
==12327== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
pi@raspberrypi:/tmp $ 

(在 0110000100000000011100110110010001100110 的情况下,结果的第二个字符是空字符,因此不会打印下一个字符)

【讨论】:

  • 如果它得到 01010101 它的 strlen 将是 8?我需要 1
  • result 需要是未来字符串的长度,它需要比二进制 'string' 小 8 倍
  • @NikolaNikolic 索引必须介于 0 和元素数减一之间
  • @NikolaNikolic 你的目标是什么?获取一个表示二进制数的字符串并生成一个与基数为 256 的相同数字对应的数组?
  • strtol 没有按照您的设想进行,因为它适用于从 b 然后 b+8 等的所有字符串
【解决方案2】:

strtol 将输入字符串解释为一个整数,因为每个 8 字符组之间没有空格。所以,我为你提出了一个简单的解决方法,将每组字符复制到一个缓冲区中,并在缓冲区的末尾附加一个 '\0'。

另外,我修复了长度计算错误。

char* binaryToString(char* b) {
    int length = (strlen(b)+7)/8 + 1;
    char buf[9];
    buf[8] = '\0';
    char* result = (char*)malloc(length);
    for (int i = 0; i < length; i++, b += 8) {
        strncpy(buf, b, 8);
        result[i] = strtol(buf, NULL, 2);
    }
    result[length - 1] = '\0';
    return result;
}

【讨论】:

  • 为什么要在长度上加上+1?我认为代码运行良好,只需删除 +1 并将 null 更改为 result[length]
【解决方案3】:

strtol 将使用尽可能多的字符来转换为整数值。它不知道您只想转换接下来的 8 个二进制数字。您可以自己进行转换,而不是尝试解决该行为。例如:

char *binaryToString(const char *b)
{
    int length = strlen(b) / 8;
    char *result = malloc(length + 1);
    if (result) {
        for (int i = 0; i < length; ++i) {
            // convert 8 binary digits to integer value
            int value = 0;
            for (int j = 0; j < 8; ++j) {
                value = (value << 1) + *b++ - '0';
            }
            result[i] = value;
        }
        result[length] = '\0'; // string must be null terminated
    }
    return result;
}

请注意,这不会像 strtol 那样进行错误检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-30
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    相关资源
    最近更新 更多