如何优化这段代码在c

时间:2011-10-18 09:01:50

标签: c

我在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;
 }

我如何在一个循环中执行此操作

3 个答案:

答案 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

相关问题