如何在C语言中高效地替换字符串

如何在C语言中高效地替换字符串,c,linux,gcc,libc,C,Linux,Gcc,Libc,我有一个由linux代码libc生成的字符串: 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb 我需要替换此字符串中的一些字符: -与_ 2加f 4加x 我正在使用循环生成200个UUID 因此,对于我需要使用自定义函数替换的每个uuid,必须对该函数进行最大程度的优化才能做到这一点,我如何才能做到这一点?我想您使用的是char[]str 切换版本 C库函数可以优化,并且比手工编码的迭代要快得多 char* uuid; // = ... // size_t uui

我有一个由linux代码libc生成的字符串:

1b4e28ba-2fa1-11d2-883f-b9a761bde3fb 我需要替换此字符串中的一些字符:

-与_ 2加f 4加x

我正在使用循环生成200个UUID

因此,对于我需要使用自定义函数替换的每个uuid,必须对该函数进行最大程度的优化才能做到这一点,我如何才能做到这一点?

我想您使用的是char[]str

切换版本


C库函数可以优化,并且比手工编码的迭代要快得多

char* uuid; // = ...
//    size_t uuid_len; // = ... length of uuid


char* ptr = strpbrk(uuid, "-24");
while (ptr)
{
   switch(*ptr)
   {
      case '-':
          *ptr = '_';
          break;
      case '2':
          *ptr = 'f';
          break;
      case '4':
          *ptr = 'x';
          break;
   }
//       if (ptr-uuid == uuid_len) break;

   ptr = strpbrk(ptr+1, "-24");
}
编辑:根据似乎不必要的示例进行范围检查

编辑:所以我决定在这里测试这3种算法,看看哪一种更快。我有一个100000个字符串的循环,在一个老式的2006 Mac Pro上,用gcc,-O3编译。我平均跑了1000次,做了5个循环

获胜者是。。。 @约翰森的平均时间为7.85毫秒

@永维武紧随其后,平均时间为7.89毫秒。差异看起来很明显;不幸的是,今晚去做一个适当的统计测试是不可能的

…strpbrk以32毫秒的速度遥遥领先第三名。很高兴我用“可能”、“可能”等限定了我所有的优化声明


编辑:Clang-j@WY的算法与Clang-j@WY的算法有很大的不同,在Clang-j@WY的算法下需要10毫秒,而我的算法没有变化。

像这样琐碎的东西是你想要的吗

void my_replace(char* str)
{
    while (*str) {
        switch (*str) {
        case '-':
            *str = '_';
            break;
        case '2':
            *str = 'f';
            break;
        case '4':
            *str = 'x';
            break;
        default:
            break;
        }
        ++str;
    }
}
它真的很快很简单。我真的看不出你怎么能让它更快


编辑:我知道某些字符串操作中有一些优化,但我不知道它们在这里如何适用。例如,在memcpy的情况下,一次可以复制4个或更多字节,具体取决于处理器。在比较正确对齐的字符串时,作为整数进行比较可能更有效。我只是看不到一种适用的技术。

200?这不是一个很大的数字,要想在现代计算机上不让它几乎是即时的,需要一些真正的工作。还有,到目前为止你有什么?你可以通过编写一个程序来实现这一点。最好早点开始。如果您有任何问题,请在这里发布。@SchighSchagh,这是打开每个字符的好方法吗,并为200个UUID相应地替换它?@RobertHarvey OP正在替换单个字符,而不是子字符串本身,所以这个问题不是重复的。用常规字符替换怎么样expression@Kajal通过正则表达式替换是不正确的slower@Kajalreg-ex太过分了。我认为用我在上面的评论中所说的开关来编写它,而不是用if/else if更具可读性,但它很可能编译成相同或非常相似的代码。您可能对我的测试结果感兴趣。@MattPhillips您在编译器参数中使用了-O3吗?@user93353否,请看最后一行。在字符find strpbrk在下一个字符重新启动后,它不会在开始时重新启动。高性能库(如LAPACK和BLAS)通常在汇编中使用经过微调的特定于处理器的代码,以实现比高级语言快很多倍的速度,即使是像矩阵乘法这样简单的运算。我希望C标准库也是如此。@MattPhillips您的期望是无效的。你最近有没有测试过你的编译器实现的优化?有吗?是什么让您确信C库没有优化?作为@Matt所说的一个例子,glibc使用SSE优化memcpy、strnlen和其他函数。事实上,一些libc实现确实采用了这样的优化。
char* uuid; // = ...
//    size_t uuid_len; // = ... length of uuid


char* ptr = strpbrk(uuid, "-24");
while (ptr)
{
   switch(*ptr)
   {
      case '-':
          *ptr = '_';
          break;
      case '2':
          *ptr = 'f';
          break;
      case '4':
          *ptr = 'x';
          break;
   }
//       if (ptr-uuid == uuid_len) break;

   ptr = strpbrk(ptr+1, "-24");
}
void my_replace(char* str)
{
    while (*str) {
        switch (*str) {
        case '-':
            *str = '_';
            break;
        case '2':
            *str = 'f';
            break;
        case '4':
            *str = 'x';
            break;
        default:
            break;
        }
        ++str;
    }
}