【问题标题】:Is the strrev() function not available in Linux?strrev() 函数在 Linux 中不可用吗?
【发布时间】:2012-01-21 23:40:05
【问题描述】:

我尝试使用strrev() 编写代码。我包含了<string.h>,但我仍然收到“对strrev 的未定义引用”错误。

我发现strrev() 根本没有手册页。为什么?

Linux 不支持strrev()

【问题讨论】:

  • 我仍然不记得上一次需要反转字符串是什么时候。
  • 你最后一次接受技术面试是什么时候?这很可能是程序员真正需要反转字符串的唯一时间。这可能就是为什么 string.h 甚至没有字符串反转函数的原因,但在一次采访中,他们无论如何都不会让你摆脱一个库函数。好吧,也许你会因为了解库和聪明而获得加分,然后要求你自己实现它。
  • strrev() 不是任何 C 标准的一部分,但它通常包含在某些库实现中。
  • 如果您编写自己的字符串反转函数,并且您没有编写 C 库实现,请选择另一个名称。以str 和小写字母开头的名称保留给实现。 str_rev 可以。

标签: c string


【解决方案1】:

这个怎么样:

#include <string.h>

char *strrev(char *s)
{
    if (s && *s) {
        char *b = s, *e = s + strlen(s) - 1;
        while (b < e) {
            char t = *b;
            *b++ = *e;
            *e-- = t;
        }
    }
    return s;
}

【讨论】:

    【解决方案2】:

    为了准确回答您的问题,

    strrev() 在 Linux 上不可用吗?

    string.h 库中可用的函数 strrev()。函数 strrev() 包括一些其他字符串函数,例如 strupr()、strlwr()、strrev(),它们仅在 ANSI C (Turbo C/C++) 中可用,在标准 C-GCC 编译器中不可用。

    这与系统无关。这是关于你正在使用的 C 编译器。

    参考资料:

    https://discuss.codechef.com/t/is-strrev-function-not-available-in-standard-gcc-compiler/2449

    https://www.csestack.org/undefined-reference-to-strrev/

    【讨论】:

    • 如果存在系统实现,最好使用系统实现。
    • 同意!不想偏离轨道。删除评论。 @RichieHH
    • @RichieHH 删除了我的这个。
    【解决方案3】:

    没有用于反转字符串的字符串库函数。

    strrev() 在 Linux 的 GCC 编译器中不存在。 制作自己的反向函数:

    reverse.c:

    /*
     * C program to reverse a string using recursion
     */
    #include <stdio.h>
    #include <string.h>
    
    void reverse(char [], int, int);
    int main()
    {
        char str1[20];
        int size;
    
        printf("Enter a string to reverse: ");
        scanf("%s", str1);
        size = strlen(str1);
        reverse(str1, 0, size - 1);
        printf("The string after reversing is: %s\n", str1);
        return 0;
    }
    
    void reverse(char str1[], int index, int size)
    {
        char temp;
    
        temp = str1[index];
        str1[index] = str1[size - index];
        str1[size - index] = temp;
    
        if (index == size / 2)
        {
            return;
        }
        reverse(str1, index + 1, size);
    }
    

    【讨论】:

    • gcc 中不存在任何字符串函数。 gcc 是编译器。字符串函数由库实现(例如 glibc)提供。
    【解决方案4】:
    #include <string.h>
    
    char *strrev(char *str)
    {
        if (!str || ! *str)
            return str;
    
        int i = strlen(str) - 1, j = 0;
    
        char ch;
        while (i > j)
        {
            ch = str[i];
            str[i] = str[j];
            str[j] = ch;
            i--;
            j++;
        }
        return str;
    }
    

    【讨论】:

    • 这个答案比被选为“最佳”答案的那个更具可读性。
    • @FehmiNoyanISI 它也坏了。如果str 为空,则strlen(str) - 1 是垃圾。如果strlen(str) 大于INT_MAX,你也会遇到问题。
    • @melpomene,用NULL 指针和空字符串检查更新了答案。 strlen() 返回 size_t 和处理 INT_MAX 应该在库实现中完成。
    【解决方案5】:

    不幸的是,glibc 的string.h 中似乎没有strrev

    显然,我参加这里的一些代码派对迟到了,但我喜欢这个实现。

    #define MAX_CHARS 10000
    // safe_usub -- perform safe unsigned subtraction
    size_t safe_usub (size_t x, size_t y) {
      return x > y ? x - y : y - x ;
    }
    
    char* str_reverse (const char* const str) {
      if (!str) { return NULL; }
    
      size_t len = strnlen(str, MAX_CHARS);
      char*  new = malloc( sizeof(char) * len );
    
      size_t i;
      for (i = 0; i < len; i++) {
        new[i] = str[ safe_usub(i + 1, len) ];
      }
    
      new[i] = 0;
    
      return new;
    }
    

    【讨论】:

    • 传统上(没有说明)strrev() 执行就地反转。这段代码没有。
    • @Gerhard 它最大程度地减少了代码重复,因为每次我想使用它时我都必须自己复制字符串。我没有说它比其他代码更好,我说我更喜欢它,因为我几乎从不希望破坏性操作就位。建设性的功能,比如我使用的readln,可以到位。
    • 这得到了两个支持并持续了超过 18 个月,没有人意识到对 strnlen 的调用需要 2 个参数
    【解决方案6】:

    正确。使用可用的alternative 实现之一:

    #include <string.h>
    
    char *strrev(char *str)
    {
          char *p1, *p2;
    
          if (! str || ! *str)
                return str;
          for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
          {
                *p1 ^= *p2;
                *p2 ^= *p1;
                *p1 ^= *p2;
          }
          return str;
    }
    

    【讨论】:

    • 请注意,如果您使用多字节字符编码(如 Big5 或任何 Unicode 编码,尤其是 UTF-8),则链接实现将工作。但我想这适用于大多数 strrev 实现......
    • 伊克。该实现使用六个取消引用。您最多需要四个。
    • 取消引用通常很便宜,而且像这样的顺序取消引用肯定会被编译器优化。除非你的编译器很烂。
    • @IgnacioVazquez-Abrams 如果您发现在您的实现中检测到写入*p1 不会修改*p2 很简单,允许跨读取访问移动分配以简化它们,您应该编写编译器而不是在 StackOverflow 上浪费时间。 clang-5.1 -O3 生成三个读取和三个写入,也许你应该帮助他们。
    • 为什么会有人使用 XOR 交换技巧?是不是让人觉得很聪明?与简单地使用临时变量相比,它只会降低代码的可读性,甚至在现代超标量乱序 CPU 架构上可能会更慢,因为这三个语句具有数据依赖性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2011-03-03
    相关资源
    最近更新 更多