将字符串转换为带有转义序列的字符串
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
=].只有在避免编译器警告时才需要强制转换。
我有一个包含十六进制字符的 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
=].只有在避免编译器警告时才需要强制转换。