简体   繁体   中英

C code to reverse a string - including NULL character at the end of string

1.) Is it possible to reverse a string including the NULL character (which means that “abcd” is represented as five characters, including the null character.)

2.) In my current implementation, that doesn't take 1.) into account, I am getting segmentation error during swapping. ie while assigning: *str = *end;

void reverse(char *str)
    {
        char * end = str;
        char tmp;
        if (str)
        {  // to handle null string
            while (*end)
            {  // find the end character
                ++end;
            }
            --end; // last meaningful element
            while (str < end) // terminal condition: str and end meets in the middle
            {   tmp = *str; // normal swap subroutine
                *str = *end; // str advance one step
                *end = tmp;   // end back one step

                str++;
                end-- ;
            }
        }
        return;
    }

Your function is correct. It seems that the problem is that you are trying to reverse a string literal. You may not change string literals. They are immutable. Any attemp to change a string literal results in undefined behaviour of the program.

From the C Standard (6.4.5 String literals)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined

Only take into account that it would be better to write

if ( *str )

instead of

 if (str)

Or if you want to check that the poinetr is not NULL then

if ( str && *str )

In this case this decrement

--end;

will be valid even if the original string is empty.

Nevertheless the function itself could be defined the following way as it is shown in the demonstrative program

#include <stdio.h>

char * reverse( char *s )
{
    char *last = s;

    while ( *last ) ++last;

    if ( last != s )
    {        
        for ( char *first = s; first < --last; ++first )
        {
            char c = *first;
            *first = *last;
            *last = c;
        }
    }

    return s;
}    

int main( void )
{
    char s[] = "Hello arshdeep kaur";

    puts( s );
    puts( reverse( s ) );
}    

The program output is

Hello arshdeep kaur
ruak peedhsra olleH
  1. I'm quite certain you can. You just need the length of the string and be aware to test NUL.

  2. Strings can and probably should be thought of as character arrays. In particular, trying to direction assign a string literal to an already initialized string is an invalid operation.

An Example:

Here is one way to reverse a string:

void reverse(char *str) {
  // First calculate the length
  unsigned int length = 0;
  int i = 0;
  for (; str[i] != '\0'; i++) {
    ++length;
  }
  ++length;
  // Allocate temporary storage
  char tmp = malloc(length);
  int x = 0;
  // Loop through starting at the end and go backwards
  // It is perfectly legal to change the characters themselves, just not the pointer
  for (i = length - 1; i >= 0; i++, x++) {
    if (str[i] != '\0') {
      tmp[x] = str[i];
    }
  }
  tmp[length - 1] = '\0';
  // Reassign to the given argument
  for (i = 0; i < length; i++) {
    str[i] = tmp[i];
  }
  // Free memory
  free(tmp);
}

Like the other answer stated, you're trying to do something that is left as undefined behavior in the standard.

Calling your code like this:

int main()
{
    char a[]="abcd";
    int i;
    reverse(a);
    for (i=0;i<5;i++) {
        printf("a[%d]=%02x\n",i,a[i]);
    }
}

Outputs this:

a[0]=64
a[1]=63
a[2]=62
a[3]=61
a[4]=00

So you're probably passing in a string literal (ie char *a="abcd"; ). These literals are commonly stored in a read-only section of memory, which is likely why it is core dumping.

That being said, doing a reversal including the null character is not of much practical usage when you're dealing with strings.

You can try this :

void reverse(char *str) {
    char *end = str;
    char tmp;
    if (str) {
        while (*end){
            ++end;
        }
        --end;
        while (str < end) {
            tmp = *str;
            *str++ = *end;
            *end-- = tmp;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM