Search code examples
cif-statementcharnested-loopscs50

Else statement logic is wacko


#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
   string key_upper = "YTNSHKVEFXRBAUQZCLWDMIPGJO";
   string key_lower = "ytnshkvefxrbauqzclwdmipgjo";
   string alphabet_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   string alphabet_lower = "abcdefghijklmnopqrstuvwxyz";
   string word = "Hello daniel, ! ..";
   char letter_switch[strlen(word)];
   for (int i = 0; i < 26; i++)
   {
        for (int j = 0; j < strlen(word); j++)
        {
            if (word[j] == alphabet_upper[i])
            {
                letter_switch[j] = key_upper[i];
            }
            else if (alphabet_lower[i] == word[j])
            {
                letter_switch[j] = key_lower[i];
            }
            else 
            {
                letter_switch[j] = word[j];
            }
        }
    }

   for (int k = 0; k < strlen(word); k++)
   {
       printf("%c", letter_switch[k]);
   }
   printf("\n");
    
   return 0;
}

I am making a chiper program. It all works perfectly fine if the else statement is defined. SO if I switch the else part with:

            else if (word[j] == '!' || word[j] == '.' || word[j] == 
                     ',' || word[j] == ' ')
            {
                letter_switch[j] = word[j];
            }

Otherwise it just copies the original word... Why?

I am doing cs50 so that will probably change some variable definitions and such.


Solution

  • In the inner for loop

        for (int j = 0; j < strlen(word); j++)
        {
            if (word[j] == alphabet_upper[i])
            {
                letter_switch[j] = key_upper[i];
            }
            else if (alphabet_lower[i] == word[j])
            {
                letter_switch[j] = key_lower[i];
            }
            else 
            {
                letter_switch[j] = word[j];
            }
        }
    

    the if statements are executed in each iteration of the loop.

    So in each iteration of the outer loop if word[j] is not equal to the current character alphabet_upper[i] or alphabet_lower[i] then the else part

    else 
    {
        letter_switch[j] = word[j];
    }
    

    gets the control. The only case when a letter can be correctly converted is when it is 'z' or 'Z' that wll be converted in the last iteration of the outer for loop.

    Also the functon strlen is called a redundant number of times.

    You could esentially simplify the task by means of using standard C functon strchr.

    For example

    const size_t N = strlen( word );
    char letter_switch[N];
    
    for ( char *current = word, *target = letter_switch; *current != '\0'; ++current, ++target )
    {
        char *p;
    
        if ( ( p = strchr( alphabet_upper, *current ) ) != NULL )
        {
            *target = key_upper[p - alphabet_upper];
        }
        else if ( ( p = strchr( alphabet_lower, *current ) ) != NULL )
        {
            *target = key_lower[p - alphabet_lower];
        }
        else 
        {
            *target = *current;
        }
    }
    
    for ( size_t i = 0; i < N; i++ )
    {
        putchar( letter_switch[i] );
    }
    putchar( '\n' );        
    

    Here is a demonstration program.

    #include <stdio.h>
    #include <string.h>
    
    typedef char *string;
    
    int main( void )
    {
        string key_upper = "YTNSHKVEFXRBAUQZCLWDMIPGJO";
        string key_lower = "ytnshkvefxrbauqzclwdmipgjo";
        string alphabet_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        string alphabet_lower = "abcdefghijklmnopqrstuvwxyz";
        string word = "Hello daniel, ! ..";
    
        const size_t N = strlen( word );
        char letter_switch[N];
    
        for (string current = word, target = letter_switch; *current != '\0'; ++current, ++target)
        {
            char *p;
    
            if (( p = strchr( alphabet_upper, *current ) ) != NULL)
            {
                *target = key_upper[p - alphabet_upper];
            }
            else if (( p = strchr( alphabet_lower, *current ) ) != NULL)
            {
                *target = key_lower[p - alphabet_lower];
            }
            else
            {
                *target = *current;
            }
        }
    
        for (size_t i = 0; i < N; i++)
        {
            putchar( letter_switch[i] );
        }
        putchar( '\n' );
    }
    

    The program output is

    Ehbbq syufhb, ! ..