Identifies the differences between pairs of strings

Viewed 60

I'm going to identify the difference between two string. I can't see what I'm missing here. The output from my code is correct by the sample. But when I test run it with other test, it fails. I can't see what the other tests are.

The input:

The first line of input contains an integer 1<= n <= 500, indicating the number of test cases that follow. Each test case is a pair of lines of the same length, 1 to 50 characters. Each string contains only letters (a-z,A-Z) or digits (0-9).

The Output:

For each test case, output the two lines in the order they appear in the input. Output a third line indicating similarities and differences as described above. Finally, output a blank line after each case.

Sample:

enter image description here

enter image description here

int main()
{
     
    int n;
    
    // scan the integer for number of test cases
    if(scanf("%d", &n) != 1) {
        return 1;
    }

    //Loop through the test cases
    for (int i = 0; i < n; i++)
    {
        char string1[1024], string2[1024], output[50];

        //Scan first and second string
        if(scanf("%s", string1) != 1) {
            return 1;
        }
        
        if(scanf("%s", string2) != 1) {
            return 1;
        }

        //Loop through the strings and compare them
        for (int i = 0; string1[i] != '\0' || string2[i] != '\0'; i++)
        {
            //Convert to lowercase
            string1[i] = tolower(string1[i]);
            string2[i] = tolower(string2[i]);

            //Compare
            if (string1[i] == string2[i])
            {
                output[i] = '.';
            } else {
                output[i] = '*';
            }
            
        }

        //Print the strings and the output.
        printf("%s\n%s\n%s\n", string1, string2, output);

        if(i + 1 < n) {
            printf("\n");
        }
        

    }
    
    
    return 0;
}
4 Answers

Maybe the problem is that when you have an input string in upper case ("ABCD") you print it in lowercase in the output ("abcd")?

The output string is never terminated, a '\0' should be added after the loop is over, otherwise printf would read over to the memory filled by previous test cases if their inputs were longer.

There is no great sense to declare the variable n as having the signed integer type int. Declare it at least as having type unsigned int.

unsigned int n;

// scan the integer for number of test cases
if(scanf("%u", &n) != 1) {
    return 1;
}

The three character array should be declared as having 51 elements

char string1[51], string2[51], output[51];

The calls of scanf will look like

    //Scan first and second string
    if(scanf(" %50s", string1) != 1) {
        return 1;
    }
    
    if(scanf(" %50s", string2) != 1) {
        return 1;
    }

Also you need to check that the entered strings have the same length as for example

    if( strlen( string1) != strlen( string2 ) ) {
        return 1;
    }

This for loop

   for (int i = 0; string1[i] != '\0' || string2[i] != '\0'; i++)

can invoke undefined behavior if the lengths of strings are not equal each other. If you will include the above shown if statement then the for loop can look the following way

size_t i = 0;
for ( ; string1[i] != '\0'; i++ )

These statements change the original strings

//Convert to lowercase
string1[i] = tolower(string1[i]);
string2[i] = tolower(string2[i]);

that you should not do. Just compare corresponding characters like

if (string1[i] == string2[i])
{
    output[i] = '.';
} else {
    output[i] = '*';
}

If you want to compare characters independent on their cases then write

if ( tolower( ( unsigned char )string1[i] ) == tolower( ( unsigned char )string2[i] ) )
{
    output[i] = '.';
} else {
    output[i] = '*';
}

After the for loop write

output[i] = '\0';

tp form a string in the array output.

It seems this if statement

if(i + 1 < n) {
    printf("\n");
}

is redundant. Just output the new line character '\n'

putchar( '\n' );

after each test case.

Needlessly complicated. And, if the source strings contain any whitespace characters, scanf won't satisfy your needs. Below is both simpler and more robust.

Challenge assures no line more than 50 (or 500???) chars, so use only two small arrays. Challenge is to also output LF after EVERY test case, so suppressing final one with special code is wrong.

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

void readAline( char *p, size_t n ) { // do or die
    if( fgets( p, n, stdin ) == NULL )
        exit( 1 );
}

int mmain() {
    char buf[2][ 50 + 1 + 1 ]; // +2 = up to 50 + LF + '\0' from fgets()

    readAline( buf[0], sizeof buf[0] );
    int n = atoi( buf[0] );

    while( n-- ) {
        readAline( buf[0], sizeof buf[0] );
        readAline( buf[1], sizeof buf[1] );

        // can't be too careful when dealing with input
        assert( strlen( buf[0] ) == strlen( buf[ 1 ] ) );

        printf( "%s%s", buf[0], buf[1] ); // echo to stdout

        // source data defined "up to 50 chars, so no test for '\0'
        // recycle buf[0] for output
        for( int i = 0; buf[0][i] != '\n'; i++ )
            buf[0][i] = buf[0][i] == buf[1][i] ? '.' : '*';

        puts( buf[0] ); // uses loaded LF and appended LF
    }

    return 0;
}

Demonstration

1
the cat sat on the mat
the fat cat in the vat
the cat sat on the mat // here is the echo
the fat cat in the vat
....*...*...*......*.. // here is the analysis
// blank line
Related