0

In this problem set, we are supposed to obtain one argument ( which omprises of digits), failing which, the user are prompted with a message, "Usage: ./caesar key". I have attached the problem statement below.

Here is the problem statement from the problem set for context.

Modify caesar.c at right such that instead of printing out the command-line argument provided, your program instead checks to make sure that each character of that command line argument is a decimal digit (i.e., 0, 1, 2, etc.) and, if any of them are not, terminates (with a return code of 1) after printing the message Usage: ./caesar key.

But if the argument consists solely of digit characters, you should convert that string (recall that argv is an array of strings, even if those strings happen to look like numbers) to an actual integer. As luck would have it, a function, atoi, exists for exactly that purpose. Here’s how you might use it:

int k = atoi(argv[1]); Once saved, print out the integer, as via %i with printf. So, for example, the behavior might look like this:

$ ./caesar 20

Success

20

or

$ ./caesar 20x

Usage: ./caesar key

Three issues:

Problem 1

1) When I input an integer(say 20, for convenience), I am prompted with the following outputs in the command line twice- not once as is desired:

./caesar

Success

20

Success

20

instead of

./caesar

Success

20

Problem 2

2) When I input a single argument, 20x, the user does not receive an error message. Instead, the code runs as if everything is allright(i.e)

Success

20x

Success

20x

Usage: ./caesar key

Admittedly, the programme returns a Usage:./caesar key. But why does it return success? Havent I already accounted for the fact in my code that it should not?

Problem 3:

When I input 0 or more than two arguments ( instead of strictly one argument), instead of reprompting the code, I am greeted with a blinking $ symbol in the terminal, instead of receiving the error mesasge " Usage:./caesar key"

int main(int argc, string argv[])

{
string s = argv[1];

if (argc == 2)
{
    for (int i=0, n = strlen(s); i < n ; i++)          
    {
        if(!isdigit(s[i]))
        {
            printf("Usage: ./caesar key \n");             
        }    

        else if(isdigit(s[i]))
        {    
            printf("Success\n%s\n", argv[1]);        
        }
    }

if( argc==1 || argc > 2) 

{
    printf("Usage: ./caesar key\n");
    return 1;
}   

}
}

c

1 Answer 1

2

This is a case of "the code does exactly what I told it, but not what I want."

The first and second problems are really the same issue. Look closely at how the loop is set up to test all the chars in the key. When it finds a char that isn't a digit, it prints the usage message like it should. The problem is what it doesn't do next. When a non-digit is found, it should immediately terminate the program with a return 1; statement. As written, the code just continues to test the rest of the string and to run the rest of the program.

It is a similar problem when it sees valid digits. Every time the code checks a char and sees a digit, it prints a success message and continues on. It should just continue without printing anything. A success message should only be printed when ALL the chars have been checked and found to be digits.

Combine these two issues and you get exactly what you saw. 20 results in two success messages because of two digits. 20x produces 2 success messages and 1 usage message. Similarly, 1x2c3v would produce 3 alternating messages each of success and usage.

When the number of parameters is incorrect, the code will never get to the usage statement. This is because the entire if statement block that checks the number of parameters is contained inside the curly braces for the code block for the first if statement. In other words, argc must be 2 (the first if statement) before the value of argc is checked (the second if statement). Examine the curly brace pairings and where the second if statement is placed inside them.

Side note: The code should check the number of parameters first. It's arguably most likely that the program will be run with an incorrect number of parameters (usually none, since people will do that to get a usage statement), so it's always best and more logical to check that the correct number of parameters exist before validating that they are in the correct form.

Also, when checking whether there's an exact number of parameters, like 2, it's more efficient to use the not form of the test: if(argc != 2) when checking for errors like incorrect number of parameters.

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

2
  • Dear Cliff, thank you so much for your comprehensive response. How do I account a success message should only be printed when ALL the chars have been checked and found to be digits. What particular function should I use?
    – Lim Dion
    Commented Aug 5, 2019 at 2:08
  • Think about it for a minute. If anything is found to be wrong, it should trigger a fault message and terminate the program. If the code completes all the tests and finds nothing wrong, then, it can assume all is well and print the success message.
    – Cliff B
    Commented Aug 5, 2019 at 10:28

You must log in to answer this question.

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