将字符串转换为带有转义序列的字符串

Converting string to one with escape sequences

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

char *A = "0a0b0c";

我想从中获得

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

有没有有效的方法来做到这一点?谢谢!

编辑:明确地说,我希望生成的字符串包含 3 个字符 \x0a\x0b\x0c,而不是一个 12 个字符的字符串 "\x0a\x0b\x0c" 其中 \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] = '[=12=]';

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

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

您可以编写一个函数,将所需的 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] = {'[=10=]'};

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

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

    return 0;
}

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

您可以修改它以满足您的需要或根据您的感觉使其更高效。

请随意编辑;通过必要的检查使其更安全。我刚刚提供了一个工作逻辑。

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

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

char A[7]  = "0a0b0c"; /* not 6, because size for the termianting [=10=] 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 中的每个字符的。然后,在你表现出这种努力之后,我可以提供更多帮助。

如果您只想在 string-literal A 中的每个 '0' 之前添加 "\x",结果是一个新字符串B,一个简单直接的循环就足够了,B 中的存储足以处理 A 中每个 '0'"\x" 的加法。

例如:

#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 中的 space 不足以处理字符添加。您始终可以声明 A 足够大,然后在每次添加 "\x" 时将字符向右移动两位,但将结果写入新字符串更有意义。

例子Use/Output

$ ./bin/straddescx
\x0a\x0b\x0c

如果您需要不同的东西,请告诉我,我很乐意进一步提供帮助。这可能是处理添加您想要的字符序列的更直接的方法之一。

#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] = '[=10=]';
    printf("%s\n", str2);
    return 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
}

您的代码中存在多个混淆点:

  • 输入字符串有 6 个字符和一个空终止符
  • 输出字符串应定义为 const char B[3]; 或可能 const char B[4]; 如果您打算在 3 个转换后的字节后设置空终止符。
  • 您代码中的定义 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个字节转换为十六进制编码的无符号整数,并将结果值存入[=25]处的unsigned char =].只有在避免编译器警告时才需要强制转换。