简体   繁体   中英

Why is my function to reverse string in c not working?

I am writing some C Code where the user enters the desired string size and then a string which will be reversed then printed (as opposed to being printed in reverse.) I also would like to mention that I don't want to use external libraries, the whole point of this is to be able to do it manually. I used dynamic memory allocation to create a string of a size inputted by the user and called a "Reverse Array" function. Everything works fine until the function is called. My method for reversing the string followed the same principle as reversing a normal array but instead of moving integers around I moved characters around. Can you explain to me what I have done wrong?

My Code:

#include <stdio.h>
#include <stdlib.h>

int RvsArr(char *Str, int end)
{
    int start = 0;
    char tmp;
    while (start < end)
    {
        tmp = Str[start];
        Str[start] = Str[end];
        Str[end] = tmp;
        start++;
        end--;
    }
    printf("%s", Str);
    return 0;
}

int main()
{
    int ArrSz;
    printf("Please enter array size: ");
    scanf("%i", &ArrSz);
    char *Str;
    Str = (char *)malloc(ArrSz * sizeof(char));
    printf("Please enter your string: ");
    scanf("%s", Str);
    RvsArr(Str, ArrSz);
    free(Str);
    return 0;
}

You need to reverse the actual string, not the full buffer.

char *RvsArr(char* Str)
{
    char *end, *wrk = Str;
    char tmp;
    if(wrk && *wrk)
    {
        end = Str + strlen(wrk) - 1;
        while(wrk < end)
        {
            tmp = *wrk;
            *wrk++ = *end;
            *end-- = tmp;
        }
    }
    return Str;
}

int main()
{
    int ArrSz;
    printf("Please enter array size: ");
    scanf(" %i", &ArrSz);
    char* Str;
    Str = malloc(ArrSz * sizeof(char));
    printf("Please enter your string: ");
    scanf(" %s", Str);
    printf("\n`%s`\n", RvsArr(Str));
    free(Str);
    return 0;
}

https://godbolt.org/z/azob5s

For starters the user can enter a string the size of which can be less than the size of the dynamically allocated character array that stores the string.

So passing the size of the array does not make a sense. The size of the array is not the same as the size of the entered string.

Also this expression Str[end] access memory beyond the allocated array in the first iteration of the while loop.

And the return type int also does not make a sense.

Apart from this the function should not output anything. It is the caller of the function that will decide to output the result string or not.

Pay attention to that this call

scanf("%s", Str);

is unsafe. It would be better to use the function fgets. For example

fgets( Str, ArrSz, stdin );

In this case you will need to remove the new line character '\n' that the function can append to the entered string.

Without using standard string functions the function can be defined the following way as it is shown in the demonstrative program below. Instead of the senseless return type int the function returns a pointer to the first character of the reversed string.

#include <stdio.h>

char * RvsArr( 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 World!";
    
    puts( s );
    puts( RvsArr( s ) );
    
    return 0;
}

The program output is

Hello World!
!dlroW olleH

If you are allowed to use standard string functions then the function RvsArr can look the following way (provided that the header <string.h> is included)

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

Character arrays or string in c(as it is generally referred to) requires one extra byte which store null character ( '\o' or 0 ) to indicate the end of string. You can store ArrSz - 1 character in your array and ArrSz byte stores the termination character( '\o' or 0 ).

int RvsArr(char* Str, int end)
{
    if (Str == 0 || end <= 1)
        return 0;

    int start = 0;
    char tmp;
    while(start < end)
    {
        tmp = Str[start];
        Str[start] = Str[--end];   // pre decrement the counter to last char
        Str[end] = tmp;
        start++;
    }
    printf("%s", Str);
    return 0;
}

or in other version

int RvsArr(char* Str, int end)
{
    if (Str == 0 || end <= 1)
        return 0;

    int start = 0;
    int last = end - 1;
    char tmp;
    while(start < last)
    {
        tmp = Str[start];
        Str[start] = Str[last];
        Str[last] = tmp;
        start++;
        last--;
    }
    printf("%s", Str);
    return 0;
}

And some changes in main function are

int main()
{
    int ArrSz;
    printf("Please enter array size: ");
    scanf("%i", &ArrSz);
    char *Str;
    Str = (char *)malloc(ArrSz * sizeof(char));
    printf("Please enter your string: ");
    scanf("%s", Str);
    Str[ArrSz] = '\0';            // Here we have no control on how many characters are read, scan is a security vulnerability becuse of this
    printf("Input=%s, len=%d\n", Str, strlen(Str));
    RvsArr(Str, strlen(Str));
    free(Str);
    return 0;
}

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