Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

The isupper() function appears to not identify certain letters (A, B, C, D, E, F, Z) as uppercase for some reason. Why is that so?

I am currently working on a practice problem which intends to encrypt some plaintext with a quite
simple algorithm. All alphabetical characters are to be encrypted, that’s why I’m passing each character of my plaintext to the isupper() function to determine whether or not the character should be encrypted.
Weirdly, every character I’m checking seems to get processed as intended except of the letters "A", "B", "C", "D", "E", "F" & "Z". I did some testing and whenever I check those characters, the else clause is run and not the intended else if clause, as if the given characters aren’t identified as uppercase by the else if clause with the isupper() function.

That’s my code (the problem is within the rotate() function on the very bottom):

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

// Prototypes
bool only_digits(string s);
char rotate(char c, int key);

int main(int argc, string argv[])
{
    // In case of improper usage, print feedback and return with 1
    // Check for single command-line argument
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Make sure the provided input is a decimal
    if (only_digits(argv[1]) != true)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Store privided key in k (Convert to int)
    int k = atoi(argv[1]);

    // Prompt user for plaintext
    string plaintext = get_string("plaintext: ");

    // Encrypt plaintext
    int len = strlen(plaintext);
    for (int i = 0; i < len; i++)
    {
        plaintext[i] = rotate(plaintext[i], k);
    }

    // Output ciphertext and return from main
    printf("ciphertext: %s\n", plaintext);
    return 0;
}

bool only_digits(string s)
{
    bool condition = true;
    for (int i = 0; i < strlen(s); i++)
    {
        if (isdigit(s[i]) == false)
        {
            condition = false;
        }
    }

    if (condition == true)
    {
        return true;
    }
    else
    {
        return false;
    }
}

char rotate(char c, int key)
{
    // Prepare for wrapping around
    key = key % 26;

    // Check for alphabetical letter
    if (isalpha(c) == false)
    {
        return c;
    }

    // Hardcoding because the following letters were for some reasons not recognized as uppercase from the isupper function
    else if (isupper(c) == true || c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F' || c == 'Z')
    {
        return (char) (((int) c - 65 + key) % 26 + 65);
    }
    else
    {
        return (char) (((int) c - 97 + key) % 26 + 97);
    }
}

As I said, from my testing it seems like that only the letters "A", "B", "C", "D", "E", "F" & "Z" are causing the issue. I identified that the else if clause isn’t run for them although it actually should and instead the else clause runs. I also checked what character I’m passing to the isupper() function as char c by printing it one line earlier and I can confirm that the right (uppercase) characters are stored in the variable c.
I really have no idea why this is happening. I know that the issue most likely can’t be the standard library function isupper() but I have no clue what else it could be. I’m new to coding, maybe I overlooked something obvious. Thank you for your help!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

THe problem is isupper(c) does not return a boolean value, it returns an int that is 0 if c is not an uppercase letter and non zero otherwise. The test if (isupper(c) == true ...) is incorrect, you should just write

    if (isupper(c)) { ...

Here is a modified version:

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

// Prototypes
bool only_digits(string s);
char rotate(char c, int key);

int main(int argc, string argv[])
{
    // In case of improper usage, print feedback and return with 1
    // Check for single command-line argument
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Make sure the provided input is a decimal
    if (!only_digits(argv[1]))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Store provided key in k (Convert to int)
    int k = atoi(argv[1]);

    // Prompt user for plaintext
    string plaintext = get_string("plaintext: ");

    // Encrypt plaintext
    int len = strlen(plaintext);
    for (int i = 0; i < len; i++)
    {
        plaintext[i] = rotate(plaintext[i], k);
    }

    // Output ciphertext and return from main
    printf("ciphertext: %s\n", plaintext);
    return 0;
}

bool only_digits(string s)
{
    for (int i = 0; i < strlen(s); i++)
    {
        if (!isdigit(s[i]))
        {
            return false;
        }
    }
    return true;
}

char rotate(char c, int key)
{
    // Prepare for wrapping around
    key = key % 26;

    // Check for alphabetical letter
    if (!isalpha(c))
    {
        return c;
    }

    if (isupper(c))
    {
        return (char)(((int)c - 'A' + key) % 26 + 'A');
    }
    else
    {
        return (char)(((int)c - 'a' + key) % 26 + 'a');
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading