Home > database >  Reverse line function in C works unpredictably
Reverse line function in C works unpredictably

Time:09-03

I'm doing the exercises from C Programming Language, the one where you need to make a function to reverse a line. So I did and it works sometimes. But only some times. With the same test it gives different results. I really don't get it, and would appreciate some help. 3 tries out of 4 it would print around 150 spaces and 1 out of 4 it would print the reversed line just like I wanted, though with some junk in the end for some reason. I was thinking of doing it with pointers, but couldn't figure them out as of now. Here's my code:

#include <stdio.h>

void reverse(char theline[150]){
    int i, j;
    char tmp[150];
    for (i = 0; theline[i] != 0; i  ){
        tmp[i] = theline[i];
    }
    for (j = 0; i >= 0; j  ){
        theline[j] = tmp[i];
        i--;
    }
}

int main() {
    char line[150];
    char c;
    int counter = 0;
    do {
        counter = 0;
        while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
            line[counter] = c;
            counter  ;
        }
        if (counter > 80){
            reverse(line);
            printf("%s\n", line);
        }
    } 
    while (c != EOF);

    return 0;
}

I compile it with "gcc -g -Wall program -o test" and the compiler doesn't give me any errors or warnings. My OS is Ubuntu and I test it with "./test < longtext.txt". This text file has a few lines of different length.

CodePudding user response:

After this loop

    while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
        line[counter] = c;
        counter  ;
    }

the character array line does not contain a string because the stored characters are not appended with the terminating zero character '\0'.

So this loop within the function

for (i = 0; theline[i] != 0; i  ){
    tmp[i] = theline[i];
}

invokes undefined behavior.

You need to append the array with the terminating zero character '\0'.

But even if the passed character array will containe a string the second for loop

for (i = 0; theline[i] != 0; i  ){
    tmp[i] = theline[i];
}
for (j = 0; i >= 0; j  ){
    theline[j] = tmp[i];
    i--;
}

writes the terminating zero character '\0' in the first position if the array theline. As a result you will get an empty string.

Also the function shall not use the magic number 150 and an auxiliary array.

Pay attention to that the variable c should be declared as having the type int. In general the type char can behave either as the type signed char or unsigned char depending on compiler options. If it will behave as the type unsigned char then this condition

c != EOF

will always evaluate to true.

Without using standard C string functions the function can be declared and defined the following way

char * reverse( char theline[] )
{
    size_t i = 0;

    while ( theline[i] != '\0' ) i  ;

    size_t j = 0;

    while ( j < i )
    {
        char c = theline[j];
        theline[j  ] = theline[--i];
        theline[i] = c;
    }

    return theline;
}

Here is a demonstration program

#include <stdio.h>

char * reverse( char theline[] )
{
    size_t i = 0;

    while ( theline[i] != '\0' ) i  ;

    size_t j = 0;

    while ( j < i )
    {
        char c = theline[j];
        theline[j  ] = theline[--i];
        theline[i] = c;
    }

    return theline;
}

int main( void ) 
{
    char s[] = "Hello World!";

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

The program output is

Hello World!
!dlroW olleH

CodePudding user response:

Why muck-around with reversing a buffer when you can simply store-up the entered characters as they arrive.

#include <stdio.h>

int main() {

    for( ;; ) {
        char line[ 150 ];
        int c, counter = sizeof line;

        line[ --counter ] = '\0';

        // NB: EOF is an int, not a char
        while( ( c = getchar() ) != '\n' && c != EOF && counter > 0 )
            line[ --counter ] = (char)c;

        printf( "%s\n\n", line   counter );
        counter = sizeof line;
    }

    return 0;
}

Output:

the quick
kciuq eht

Once upon a time in a land far awy
ywa raf dnal a ni emit a nopu ecnO

I wish I was what I was when I wished I was what I am now.
.won ma I tahw saw I dehsiw I nehw saw I tahw saw I hsiw I
  • Related