我试图在图书馆中开发一个功能,以寻找字符&#39;&lt;&#;;&#39;&gt;&#39;&#39;和&#39;&amp;&#39 ;;并将其替换为<
,>
和&
。
到目前为止,我已经开发了这个功能:
char *sXMLspecialReplace(char *rawString) {
char *old_pointer = rawString;
int new_index = 0;
/*In most cases there won't be character substitution, so we can
start allocating with the original length and only reallocate if
a special char is spotted, therefore, memory reallocation will
take place in few circumstances.
+ 1 for NULL terminator.*/
int result_size = strlen(rawString) + 1;
char *result = (char *) malloc(result_size);
do {
switch (*old_pointer) {
case '&':
result_size += 4; // From 1 to 5
result = (char *) realloc(result, result_size);
strcpy(result + new_index, "&");
new_index += 5;
break;
case '<':
result_size += 3; // From 1 to 4
result = (char *) realloc(result, result_size);
strcpy(result + new_index, "<");
new_index += 4;
break;
case '>':
result_size += 3; // From 1 to 4
result = (char *) realloc(result, result_size);
strcpy(result + new_index, ">");
new_index += 4;
break;
default:
//Most frequent case
result[new_index++] = *old_pointer;
}
old_pointer++;
} while (*old_pointer != '\0');
/*do-while ensures the function exits with a null terminator*/
return result;
}
虽然它在某些情况下有效,但在有些情况下它还有其他情况。在测试中,我尝试执行以下操作:
char *my_company = "HELLO INDUSTRIES EUROPE";
char *xml_company = sXMLspecialReplace(my_company);
sprintf(sXMLanswer,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<company>%s</company>\n",
xml_company);
printf(sXMLanswer);
输出
<?xml version="1.0" encoding="UTF-8"?>
<company>HELLO INDUSTRIES EUROPE[[[[[</company>
编辑1:格式<
,>
和&
。
答案 0 :(得分:3)
你没有终止你的字符串副本。
do
{
switch (*old_pointer)
{
...
default:
//Most frequent case
result[new_index++] = *old_pointer;
}
old_pointer++;
} while (*old_pointer != '\0');
在switch
中复制字符。然后你推进你的源指针。
然后检查高级指针是否指向'\0'
。
这意味着在字符串的最后一个字符之后,您将离开do while
循环,并且不会复制终止'\0'
字节。
这会在您复制字符串后留下随机垃圾。
你可能会这样解决:
...
}
// No incement here!
} while (*old_pointer++ != '\0');
答案 1 :(得分:1)
可能更好(1)在三个单独的步骤中做你想做的事情:
要获得最终的len,它非常简单:您只需遍历字符串,每次看到要替换的字符时,都会相应地增加len。
要填充它,它也非常简单:再次遍历字符串,如果看到一个字符,则添加替换文本而不是原始字符。
鉴于你已经做了什么,我认为这个算法对你来说是件小事。
如果你想保持它基本的,你可以对所有东西进行编码(就像你已经做过的那样),或者你可以使用结构来允许更多的进化代码(比如addind另一个角色来代替)。
编辑:(1)我说&#34;更好&#34;因为你可能最终在运行时做了很多realloc / malloc,这根本不是很有效。此外,每次你想要添加一个替换字符(我不知道XML是否有&#34;&amp;&lt;&gt;&#34;),你将不得不做一个realloc,这将是无所事事地增加你的代码。 想象一下,有23个特征可以替换......你的代码最终会处于维护状态。
typedef struct swap {
char src;
char *dst;
size_t dstLen;
} swap_s;
swap_s *SwapList_FoundBySrc(swap_s *list, char searched)
{
for (size_t i = 0; list[i].src; ++i) {
if (list[i].src == searched) {
return (&list[i]);
}
}
return (NULL);
}
char *PlainStringToXmlString(char *input)
{
char *output = NULL;
size_t len = 1; // Final '\0'
swap_s list[] = {{'&', "&", strlen("&")},
{'<', "<", strlen("<")},
{'>', ">", strlen(">")},
{'\0', NULL, 0}};
swap_s *swap = NULL;
// Get the final len sum
for (size_t i = 0; input[i]; ++i) {
if ((swap = SwapList_FoundBySrc(list, input[i]))) {
len += swap->dstLen;
} else {
++len;
}
}
// Allocate it
if (!(output = malloc(len))) {
// Log ?
return (NULL);
}
output[len - 1] = '\0';
// Fill it
size_t j = 0;
for (size_t i = 0; input[i]; ++i) {
if ((swap = SwapList_FoundBySrc(list, input[i]))) {
strcpy(output + j, swap->dst);
j += swap->dstLen;
} else {
output[j] = input[i];
++j;
}
}
return (output);
}