Is the strrev() function not available in Linux?
Asked Answered
A

7

43

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()?

Avent answered 16/12, 2011 at 6:1 Comment(6)
I still can't remember the last time I needed to reverse a string.Jack
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.Kesterson
possible duplicate of How do you reverse a string in place in C or C++?Randers
strrev() is not part of any C standard but it is commonly included in some library implementations.Evangel
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.Galer
Here u can find itEphod
D
46

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;
}
Discontinuous answered 16/12, 2011 at 6:18 Comment(10)
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...Macfadyn
Ick. That implementation uses six dereferences. The most you should need is four.Fenella
Dereferences are usually cheap, and certainly sequential dereferences like this would be optimized by the compiler. Unless your compiler sucks.Discontinuous
@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.Nothing
@PascalCuoq: Yes, three reads and three writes, not nine reads and three writes.Discontinuous
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: pastebin.com/MwGVuxYENothing
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.Randers
@Fritz: Not that I'm defending the XOR method, but any in-place reverse operation will be full of dependencies.Discontinuous
@PascalCuoq Alias analysis can't see that p2 != p1 in a for loop with a condition that is p2 > p1? Wow.Flynn
@Randers Last time I checked (yesterday), I measured it as over 2 times slower than simply using a temporary.Polychromatic
P
36
#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;
}
Proceed answered 2/4, 2015 at 8:33 Comment(4)
This answer is far more readable than the one selected as the "best" answer.Aspidistra
@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.Sessoms
@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.Aspidistra
I think the author is not expecting the code but an answer on if it is available under Linux?Dosi
D
6

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/

Dosi answered 17/11, 2019 at 7:10 Comment(1)
Agreed! Don't want to go on off-track. Deleting the comment. @RichieHHDosi
C
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;
}
Colorcast answered 23/5, 2016 at 15:24 Comment(3)
Traditionally(the is no specification) strrev() performed in place reversal. This code does not.Evangel
@Evangel 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.Colorcast
this got two upvotes and lasted more than 18 months and nobody realised that the call to strnlen needed 2 argumentsColorcast
I
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;
}
Icsh answered 28/2, 2022 at 16:2 Comment(2)
I think the author is not expecting the code but an answer on if it is available under Linux?Dosi
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.Icsh
L
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);
}
Lumen answered 1/1, 2018 at 15:56 Comment(1)
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).Galer
R
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;
}
Rajiv answered 30/6, 2023 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.