Reputation: 21
I just started learning computer science.
I'm studying through CS50 taught at Harvard online. Well, I'm working on this one problem where I need to get the key from the user in command line, then a plaintext, and then shift that text for key amount of numbers in ASCII to make a ciphertext.
here is what I've got so far.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./caesar key\n");
}
{
string plaintext = get_string("plaintext: ");
int key = atoi(argv[1]);
int n = strlen(plaintext);
char chr[n];
printf("ciphertext: ");
for (int i = 0; i < n; i++)
{
chr[i] = plaintext[i];
if (isalpha(chr[i]))
{
if (isupper(chr[i]))
{
chr[i] = (chr[i] - 65 + key) % 26 + 65;
printf("%c",chr[i]);
}
else if (islower(chr[i]))
{
chr[i] = (chr[i] - 97 + key) % 26 + 97;
printf("%c",chr[i]);
}
}
else
{
printf("%c",chr[i]);
}
}
printf("\n");
}
}
well I know this seems very floppy but man it's my second week into programming while working full time.
anyways, I'm trying to have the user to run this program by using ./caesar "any number for the key".
if the user puts in any other things, then I'd like to print "Usage: ./caesar key\n"
so far the only way i can think of is making the if statement with argc != 2 so that I can at least make sure the user puts in just one command on top of the program's name.
but the problem is that if the user puts in other things such as ./caesar HELLO ./caesar YolO
the program still runs.
I'm trying to figure out what I can do in order to prevent that from happening.
Really appreciate your time for reading this and help.
Upvotes: 1
Views: 129
Reputation: 7988
To rephrase your question: You want to perform validation on user input, where the only legal input values are numeric strings: 123
and 4534
and 000
could all be considered valid, but hello world
and f00
and one hundred thirty two
are not valid.
In most programming languages, including C, strings are more or less just arrays of individual char
elements (in other words, char
is a primitive data type, but string
is not.... C doesn't have a string
data type at all. hint: take a look at the way you've declared main
). So how can you use that to your advantage to validate the input to this program? Easy enough: every character in the input string must come from the domain [0123456789]
(plus the null terminator \0
at the end...).
So to solve this problem, you just need to implement a check that verifies that the inputted value has that property. There are a number of ways to do that, maybe the easiest of which is:
int num;
int y = scanf("%d", &num);
then check the value of y
. It will be set to the number of valid inputs that scanf
read (so it will be 1 if a number was given).
Note:
as mentioned in the comments, this will also accept things like 123abc
(it will strip off the numbers and ignore the characters at the end). If you absolutely must have only numbers for input, scanf
might not be the right function. In that case, using fgets
to read the input as a string and then looping over each input to check that it is from the valid input domain might be a better approach.
Upvotes: -1
Reputation: 149155
That is the reason way the old atoi
function has been superseded by strtol
. The former only try to convert an initial numeric part from the given string, while the latter also tells what remains after the converted part.
So to make sure that the user has given a number as sole argument, you could do:
int main(int argc, char *argv[]) {
long key;
int reject = 0;
if (argc != 2) { // ensure one argument
reject = 1;
}
else {
char *end;
key = strtol(argv[1], &end, 10); // ensure not empty and numeric
if ((*end != 0) || (end == argv[1])) reject = 1;
}
if (reject) {
printf("Usage: %s key\n", argv[0]);
return 1;
}
sscanf
could be used too. It even allows blank characters after the number, which should not happen as the argv
array is blank separated:
int main(int argc, char *argv[]) {
int key;
char empty[2];
if ((argc != 2) || (sscanf(argv[1], "%d%1s", &key, empty) != 1)) {
printf("Usage: %s key\n", argv[0]);
return 1;
}
...
Upvotes: 5