2

I tried all the provided examples on the pset2 site, and I got all of them correct. But when I used check50 to check my code, it said: "timed out while waiting for program to exit" for some scenarios. Seems like it is trapped in some kind of infinite loop (probably in checking the repeated characters and the non-alphabetic numbers), but I couldn't figure out how to fix it. Also, if it is trapped in these two circumstances, why does my code still work in other scenarios?

Here are the two unsuccessful scenarios: enter image description here

Below is my code: (I know it's not very organized, and I should have created new methods)

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

int main(int argc, string argv[])
{
    //different error types
    
    //there should be only one command-line argument
    if (argc != 2)
    {
        printf("Usage: ./substitution KEY\n");
        return 1;
    }
    
    //there should not be non-alphabetic numbers
    for (int i = 0; i < argc; i++)
    {
        char character = argv[1][i];
        if (character < 'A' || (character > 'Z' && character < 'a') || character > 'z')
        {
            printf("Key must only contain alphabetic characters.\n");
            return 1;
        }
    }
    
    //there should not be repeated characters
    for (int f = 0; f < argc - 1; f++)
    {
        char character = argv[1][f];
        for (int s = f + 1; s < argc; s++)
        {
            if (character == argv[1][s])
            {
                printf("Key must not contain repeated characters.\n");
                return 1;
            }
        }
    }
    
    //there should be only 26 characters
    if (strlen(argv[1]) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }
    
    //if no error occurs, then ask for plain text
    else
    {
        string plain = get_string("plaintext: ");
        char cipher[strlen(plain)];
        int countc = 0;
        
        for (int i = 0, n = strlen(plain); i < n; i++)
        {
            char p = plain[i];
            
            int sub_lower = p - 'a';
            int sub_upper = p - 'A';
            
            //lower case scenerio
            if (p >= 'a' && p <= 'z')
            {
                cipher[countc] = tolower(argv[1][sub_lower]);
                countc ++;
            }
            
            //upper case scenerio
            else if (p >= 'A' && p <= 'Z')
            {
                cipher[countc] = toupper(argv[1][sub_upper]);
                countc ++;
            }
            
            //no change if it's not alphabetic number
            else
            {
                cipher[countc] = p;
                countc ++;
            }
        }
        
        printf("ciphertext: ");
        
        //print out the cipher text
        for (int i = 0; i < countc; i++)
        {
            printf("%c", cipher[i]);
        }
        printf("\n");
        return 0;
    }
}

2 Answers 2

3

It's failing because the code isn't handling invalid keys correctly. For the cases where the key contains a number or a duplicate letter, the program should terminate. Check50 is timing out because the code is waiting for user input that check50 isn't giving.

The problem lies here:

for (int i = 0; i < argc; i++)

It looks like you don't have an understanding of argc and argv. argc contains a count of the number of argument strings, not the length of a string. argv[] is an array of strings and each element in the argv array is a string in itself.

That means that the code should be checking each char in the argument string! which the code inside the for loop does.

The for loop that checks the validity of the key fails because it is only checking the first two chars in argv[1]. Remember, there's only one parameter, so argc == 2.

Maybe you need to determine the actual length of the string arg[1] first?

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

3
  • Thank you so much for the comment! I think I was confused about argc and argv before, so thanks for the clarification!
    – xinyis348
    Aug 8, 2021 at 1:39
  • 1
    So I basically change the line into this: for (int i = 0; i < strlen(argv[1]); i++) I think it then changes to the length of the argc[1], which is the length of a string. I checked the code again, and it works. So I just want to double-check if I understand it correctly.
    – xinyis348
    Aug 8, 2021 at 1:43
  • You do. understand it. .
    – Cliff B
    Aug 8, 2021 at 1:52
0

bro you have to check if there is a space in the key. and if there is return 1 and stop the program. I basically did that and my problem got solved

#include <cs50.h>

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

int checkKey(string key);// Skey - Key in String. int rotate(char ch);

int main(int argc, string argv[]) { if(argc != 2) { printf("Usage: ./substitution key\n" ); return 1; } string key = argv[1]; int check = checkKey(key);

if(check == 1)
{
    printf("Key must contain 26 character\n");
    return 1;
}
if(check == 2)
{
    printf("Key must contain only alphabets\n");
    return 1;
}
if(check == 3)
{
    printf("No character  be can repeated (case insensitive)\n");
    return 1;
}

string plain = get_string("plaintext:  ");
printf("ciphertext: ");
int pos;
for(int i = 0, n = strlen(plain); i < n ; i++)
{

    if(isalpha(plain[i]))
    {
        pos = rotate(plain[i]);
        if(isupper(plain[i]))
        {
        printf("%c", toupper(key[pos]));
        }
        if (islower(plain[i]))
        {
        printf("%c", tolower(key[pos]));
        }
    }
    else
    {
        printf("%c", plain[i]);
    }
}
printf("\n");

} //key is case insensitive. should be only alphabets. // no alphabet can be repeated. Can be 26 alphabets only int checkKey(string key) { int l = strlen(key); if(l != 26) { return 1; } for(int i = 0 ; i < l; i++) { if(key[i] == ' ') { return 2; }

    if(isalpha(key[i]) == false)
    {
        return 2;
    }

    for(int j = 0; j < l ; j++)
    {
        if(i != j )
        {
             if(key[i] == key[j] || key[i] == (key[j] + 32))
                {
                    return 3;
                }
        }

    }

}

return 0;

}

int rotate(char ch) {

    int pos;
    if(isupper(ch))
    {
        pos = ch  - 'A' ;
        return pos;

    }
    else
    {
        pos = ch - 'a';
        return pos;
    }

}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .