40

I tried to write code using strrev(). I included <string.h> but still I'm getting an "undefined reference to strrev" error.

I found that strrev() doesn't have man page at all. Why?

Doesn't Linux support strrev()?

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Dinesh
  • 16,014
  • 23
  • 80
  • 122
  • 10
    I still can't remember the last time I needed to reverse a string. – jørgensen Dec 16 '11 at 12:51
  • 20
    When was the last time you had a technical interview? That may well be the only time when a programmer actually needs to reverse a string. That's probably why string.h doesn't even have a string reverse function, but in an interview they wouldn't let you get away with a library function anyway. Well, maybe you would get bonus points for knowing the libraries and being clever, then ask you to implement it yourself. – Suboptimus Jul 30 '13 at 19:10
  • possible duplicate of [How do you reverse a string in place in C or C++?](http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c) – Fritz Apr 02 '15 at 09:07
  • 4
    `strrev()` is not part of any C standard but it is commonly included in some library implementations. – Gerhard Jun 03 '16 at 06:30
  • 3
    If you write your own string reversal function, and you're not writing a C library implementation, pick another name. Names starting with `str` and a lowercase letter are reserved to the implementation. `str_rev` is OK. – Keith Thompson Nov 17 '19 at 07:52

7 Answers7

43

Correct. Use one of the alternative implementations available:

#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;
}
Stargateur
  • 24,473
  • 8
  • 65
  • 91
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 3
    Be aware that the linked implementation will *not* work if you use a multi-byte character encoding (such as Big5, or any Unicode encoding, in particular UTF-8). But I guess that goes for most `strrev` implementations... – sleske Dec 16 '11 at 09:30
  • 4
    Ick. That implementation uses six dereferences. The most you should need is four. – user1329482 Oct 28 '14 at 17:30
  • 2
    Dereferences are usually cheap, and certainly sequential dereferences like this would be optimized by the compiler. Unless your compiler sucks. – Ignacio Vazquez-Abrams Oct 28 '14 at 17:32
  • 2
    @IgnacioVazquez-Abrams If you find it trivial to detect that writing to `*p1` does not modify `*p2` in your implementation, allowing to move assignments across read accesses for the purpose of simplifying them, you should write compilers instead of wasting your time on StackOverflow. clang-5.1 -O3 generates three reads and three writes, perhaps you should give them a hand. – Pascal Cuoq Oct 28 '14 at 22:02
  • @PascalCuoq: Yes, three reads and three writes, not nine reads and three writes. – Ignacio Vazquez-Abrams Oct 28 '14 at 22:04
  • Good point, I miscounted. The final xor with memory destination should count for one read and one write, and I forgot one read at the beginning. The generated assembly is here. There is nothing to be proud of: http://pastebin.com/MwGVuxYE – Pascal Cuoq Oct 28 '14 at 22:09
  • 54
    Why on earth would anyone use the XOR swapping trick? Does it make people feel clever? It just makes the code less readable than simply using a temporary variable and may even be slower on modern superscalar out-of-order CPU architectures, because the three statements have data dependencies. – Fritz Apr 02 '15 at 09:06
  • @Fritz: Not that I'm defending the XOR method, but any in-place reverse operation will be full of dependencies. – Ignacio Vazquez-Abrams Apr 02 '15 at 11:07
  • @PascalCuoq Alias analysis can't see that `p2 != p1` in a `for` loop with a condition that is `p2 > p1`? Wow. – doug65536 Mar 07 '17 at 18:14
  • 2
    @Fritz Last time I checked (yesterday), I measured it as over 2 times slower than simply using a temporary. – Petr Skocik Sep 19 '17 at 09:57
34
#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;
}
fnisi
  • 1,181
  • 1
  • 14
  • 24
Sumit Naik
  • 744
  • 1
  • 7
  • 11
  • 6
    This answer is far more readable than the one selected as the "best" answer. – fnisi Feb 20 '16 at 02:25
  • @FehmiNoyanISI It's also broken. If `str` is empty, `strlen(str) - 1` is garbage. If `strlen(str)` is bigger than `INT_MAX`, you're also going to have problems. – melpomene Oct 17 '18 at 04:23
  • 1
    @melpomene, updated the answer with a `NULL` pointer and empty string check. `strlen()` returns `size_t` and handling `INT_MAX` should be done the library implementation. – fnisi Oct 17 '18 at 10:44
  • I think the author is not expecting the code but an answer on if it is available under Linux? – Premkumar chalmeti Nov 10 '22 at 14:04
5

To accurately answer your question,

Is strrev() not available on Linux?

The functions strrev() available in the string.h library. Functions strrev() including some other string functions such as like strupr(), strlwr(), strrev(), which are only available in ANSI C (Turbo C/C++) and are not available in the standard C-GCC compiler.

It’s not about the system. It is about the C compiler you are using.

References:

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

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

Premkumar chalmeti
  • 800
  • 1
  • 8
  • 23
2

Unfortunately, strrev seems to be absent from glibc's string.h.

Obviously, I'm late to the here's-some-code party, but I like this implementation.

#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;
}
cat
  • 3,888
  • 5
  • 32
  • 61
  • 2
    Traditionally(the is no specification) `strrev()` performed in place reversal. This code does not. – Gerhard Jun 03 '16 at 06:25
  • @Gerhard it minimises code duplication because I would have to copy the string myself every time I want to use this. I didn't say it was better than other code, I said I liked it more, because I almost never want destructive operations to be in-place. Constructive functions, like the `readln` I use, can be in place. – cat Jun 03 '16 at 11:02
  • this got two upvotes and lasted more than 18 months and nobody realised that the call to strnlen needed 2 arguments – cat Jan 02 '18 at 01:37
1

How about this:

#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;
}
raygard
  • 105
  • 6
  • I think the author is not expecting the code but an answer on if it is available under Linux? – Premkumar chalmeti Nov 10 '22 at 14:05
  • You are right, I did not answer the OP’s question. Sorry. I saw several possible implementations proposed and I thought mine was better, so I got carried away. – raygard Nov 10 '22 at 15:13
0

There is no string library function to reverse a string.

strrev() Is not present in GCC compiler in Linux. Make your own reverse function:

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);
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Amarendra Deo
  • 55
  • 1
  • 9
  • 2
    None of the string functions are present in gcc. gcc is the compiler. The string functions are provided by the library implementation (for example glibc). – Keith Thompson Nov 17 '19 at 07:50
0

At the time I needed to terminate the source string at a given point, then reverse:

// terminate and reverse string
char* tstrrev(char* s, int pt)
{
  char *r = malloc( (pt+1) * sizeof(char) );

    s[pt] = r[pt] = '\0';
    s+= pt - 1;

     while ( *s )
      *r++ = *s--;

 return r-pt;
}