我在C中有一段代码可以删除字符串中的任何重复字符。但是我在两个循环中执行它并且希望它优化到一个循环。
void removeDuplicates(char* ptr)
{
int end = 1;
int length = strlen(ptr);
int current;
int i;
current = 1;
for(end=1; end<length; end++)
{
for(i=0; i<end; i++)
{
if(ptr[end] == ptr[i])
break;
}
if(i == end)
{
ptr[current] = ptr[i];
current++;
}
}
ptr[current] = 0;
}
int main(int argc, char** argv)
{
char str[256] = {0,};
gets(str);
removeDuplicates(str);
printf("%s\n", str);
return 1;
}
我如何在一个循环中执行此操作
答案 0 :(得分:4)
您可以通过以下方式一次性完成此操作:
#include <stdio.h>
#include <string.h>
int main (void) {
char str[] = "p123h12p97h62p32h"; // Input string.
int found[256]; // Assumes 8-bit char.
char *src, *dst; // Source and destination pointers.
// Output initial value and set found flags to false.
printf ("Before: [%s]\n", str);
memset (found, 0, sizeof(found));
// One loop, processing each source character in string.
for (src = dst = str; *src != '\0'; src++) {
// If not yet found, flag it found and transfer it, else do nothing.
if (!found[(unsigned int)(*src)]) {
found[(unsigned int)(*src)] = 1;
*dst++ = *src;
}
}
// Insert new end of string, then output it.
*dst = '\0';
printf (" After: [%s]\n", str);
return 0;
}
这会在一次传递中删除重复项,使用两个指针独立地通过字符串前进:
src
|
v
p123h12p97h62p32h
^
|
dst
src
指针在循环的每次迭代中前进一次。将字符从src
复制到dst
,并且dst
指针仅在之前未看到该字符(使用found
数组)时才会前进。输出是:
Before: [p123h12p97h62p32h]
After: [p123h976]
注意"assumes 8-bit char"
注释 - 如果你知道字符集是ASCII(或任何其他8位字符集),这很好,但它可能无法移植到更奇特的实现。您只需确保found
数组中有足够的元素用于所有字符。例如,10位char
类型需要1024个元素(210 = 1024
)。
答案 1 :(得分:1)
void removeDuplicates(char* ptr)
{
int exists[256] = {0};
int end;
int current = 0;
int length = strlen(ptr);
for(end = 0; end < length; end++)
{
if (exists[ptr[end]]) break;
exists[ptr[end]] = 1;
ptr[current++] = ptr[end];
}
ptr[current] = '\0';
}
int main(int argc, char** argv)
{
char str[256] = {0,};
gets(str);
removeDuplicates(str);
printf("%s\n", str);
return 1;
}
答案 2 :(得分:1)
这是我最初的想法。微优化为“char see”数组耗尽更少的内存,否则与其他人发布的想法相同。
void removeDuplicates(char* src) {
// Bitfield to remember which chars we 've seen, assumes 8-bit char type
char bitfield[32] = { 0 }; // 32 * 8 = 256 bits
char* dest = src; // initialize "output" ptr
while(*src) {
// Bitfield manipulation
char ch = *src;
int pos = ch >> 3; // ch / 8
int bit = ch & 0x7; // ch % 8
char mask = 1 << bit;
// If char seen for first time, mark and write to "output"
if(!(bitfield[pos] & mask)) {
bitfield[pos] |= mask;
*dest++ = ch;
}
++src;
}
*dest = 0; // null terminator
}
<强> See it in action