使用转义序列将字符串转换为一个

时间:2019-12-23 07:21:23

标签: c arrays hex

我有一个包含十六进制字符(不包含0x\x的char字符串):

char *A = "0a0b0c";
我想从中获得的

const char *B = "\x0a\x0b\x0c";

是否有一种有效的方法来做到这一点?谢谢!

编辑:为了清楚起见,我希望结果字符串包含3个字符\x0a\x0b\x0c,而不是包含"\x0a\x0b\x0c"的12个字符串\x被读取为单独的字符。

这是我尝试过的:

const char *B[12];

for (j = 0; j < 4; ++j) {
    B[4 * j + 0] = '\\';
    B[4 * j + 1] = 'x';
    B[4 * j + 2] = A[2 * j];
    B[4 * j + 3] = A[2 * j + 1];
};
B[12] = '\0';

这给了我12个字符串"\x0a\x0b\x0c",但是我希望B像这样分配:

const char *B = "\x0a\x0b\x0c";

6 个答案:

答案 0 :(得分:0)

您可以编写一个将所需的sprintf转换为字符串,然后将其与目标字符串连接的函数。

类似的事情...

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

void createB (char B[10], const char *start)
{
    char temp[10];
    sprintf(temp, "\\x%c%c", start[0], start[1]);
    strcat(B, temp);
}

int main ()
{
    char A[] = "0a0b0c";

    char B[10] = {'\0'};

    for (int i=0; A[i] != '\0'; i = i+2)
    {
        createB(B, A+i);
    }

    printf("%s\n", B);

    return 0;
}

$ ./main.out
\x0a\x0b\x0c

您可以对其进行修改以适合您的需求,或者使其具有更高的效率。

请根据需要进行编辑;通过必要的检查使其更安全。我刚刚提供了一个可行的逻辑。

答案 1 :(得分:0)

根据kiran的建议,虽然使用char A[] = "0a0b0c";可以更改字符串,但仍不允许插入字符。因为那样会使字符串更长,因此不适合可用内存。如果您无法立即以所需的大小创建目标字符串,这又是一个问题。

如果输入始终具有相同的长度并且始终需要相同数量的插入字符,例如,可以预先知道所需的大小。如果像您的示例中那样,目标字符串是输入字符串大小的两倍。对于简单的字符数组定义,您需要在编译时已经知道大小。

char A[7]  = "0a0b0c"; /* not 6, because size for the termianting \0 is needed */
char B[13] = "";       /* 2*6+1 */

因此,您可以使用char * A =“ 0a0b0c”;通过设置适当大小的内存作为目标,可以使您的生活更轻松。为此,您需要首先确定所需内存的长度,然后分配它。

确定大小(如果容易),如果您知道它将是输入大小的两倍。

/* inside a function, this does not work as a variable definition */
int iLengthB = 2*length(A);

char* B = malloc(iLengthB+1); /* mind the terminator */ 

然后在A上循环,将每两个字符复制到B,并在其前面加上两个字符“ \ x”。我认为这部分对您来说很明显。否则,请说明如何如上所述设置程序,并进行循环以分别输出A中的每个字符。然后,在您证明了自己的努力之后,我可以提供更多帮助。

答案 2 :(得分:0)

如果您只想在 string-literal "\x"中的每个'0'之前添加A,并在结果中添加一个新字符串B ,那么就需要一个简单而直接的循环,并且B中的存储足以处理"\x"中每个'0'的{​​{1}}的加法。

例如:

A

您不能简单地将#include <stdio.h> #define MAXC 32 int main (void) { char *A = "0a0b0c", *pa = A, B[MAXC], *pb = B; do { /* loop over all chars in A */ if (*pa && *pa == '0') { /* if chars remain && char is '0' */ *pb++ = '\\'; /* write '\' to B, adv ptr */ *pb++ = 'x'; /* write 'x' to B, adv ptr */ } *pb++ = *pa; /* write char from A, adv ptr */ } while (*pa++); /* while chars remain (writes nul-termining char) */ puts (B); /* output result */ } 更改为带有A的数组,然后写回char A[] = 0a0b0c";,因为A中没有足够的空间来处理字符加法。您总是可以声明A足够大,然后每​​次添加A时将字符向右移动两个,但是将结果写入新字符串更有意义。

使用/输出示例

"\x"

如果您需要其他帮助,请告诉我,我们很乐意进一步提供帮助。这可能是处理所需字符序列的更直接方法之一。

答案 3 :(得分:0)

#include <stdio.h>

int main(void)
{
    char str1[] = "0a0b0c";
    char str2[1000];
    int i, j;
    i = j = 0;
    printf("sizeof str1 is %d.\n", sizeof(str1)-1);
        for(i = 0; i < sizeof(str1)-1; i += 2)
    {
        str2[j] = '\\';
        str2[j+1] = 'x';
        str2[j+2] = str1[i];
        str2[j+3] = str1[i+1];
        j+=4;
    }
    str2[j] = '\0';
    printf("%s\n", str2);
    return 0;
}

我认为您可以这样做。

答案 4 :(得分:0)

假设没有错误的输入,假设“ a”至“ f”是按顺序排列的,假设没有大写字母:

// remember to #include <ctype.h>
char *input = "0a0b0c";
char *p = input;
while (*p) {
    v = (isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10) * 16;
    p++;
    v += isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10;
    p++;
    printf("0x%d", v); // use v
}

答案 5 :(得分:0)

您的代码中存在多个困惑:

  • 输入字符串包含6个字符和一个空终止符
  • 如果您打算在3个转换后的字节之后设置一个空终止符,则输出字符串应定义为const char B[3];const char B[4];
  • 代码中的定义const char *B[12];定义了一个由12个指向字符串的指针组成的数组,这是一个非常不同的野兽。
  • for很好,但是它根本不能满足您的要求。您想将十六进制编码值转换为字节值,而不要插入额外的\x字符。
  • ;之后的}没用
  • 您在B[12]处设置了一个空终止符,该终止符超出了B的结尾。

以下是使用sscanf的更正版本:

const char *A = "0a0b0c";
const char B[4] = { 0 };

for (j = 0; j < 3; j++) {
    sscanf(&A[j * 2], "%2hhx", (unsigned char *)&B[j]);
}

转换格式%2hhx表示最多将A[j * 2]的前2个字节转换为以十六进制编码的无符号整数,并将结果值存储到unsigned char的{​​{1}}中。强制转换仅是为了避免编译器警告。