segmentation fault cs50 week 2 - c

I am writing a program to encrypt plain text. It forces the user to input a number in the command line, when i convert the data type of the number from string to int using atoi the program gives me segmentaion fault. I am not able to understand why.
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, string argv[])
{
//make sure the program was run by using just one command line argument
string x = argv[1];
if(argc !=2)
{
printf("Usage: ./caesar key\n");
}
else
{
int y = strlen( argv[1]);
//makeing sure the command line argument input is a digit
for( int i = 0; i < y; i++)
{
if( isdigit( x[i])==0)
{
printf( "Usage: ./caesar key\n");
}
return 1;
}
}
printf( " hello \n");
//convert argv[1] from string to an int
int user_key = atoi( argv[1]);
printf( "key = %i\n",user_key);
//promt user for plaintext
//for each charecter in plaintext
// rotate charecter if it is a letter
}

Related

C, Why there is a Segmentation fault (core dumped)

#include <cs50.h>
#include <stdio.h>
#include<ctype.h>
int main(int argc, string argv[])
{
int KEY;
if(isdigit(argv[1]))
{
KEY = (int)argv[1];
}
else
{
printf("Usage: ./caesar key");
}
printf("\n");
printf("%i\n",argc);
}
I can't find out the problem when I type the following
How do I fix it?
This is not a high-level language with various syntax sugar features.
Important Notes:
Conversion of const char * to int is not done by just type-casting it.
isdigit() works only for int (single characters), not const char * it will cause Undefined Behavior.
argc is the length of pointer array argv
string is not a valid type for main() function arguments, it should be int main(int argc, char const **argv) { }
Must check whether argv[1] even exists or not
Once you print the usage your program should exit
Any error message should be printed on stderr
Must Use return EXIT_SUCCESS;, which is defined in the header file stdlib.h, when exiting the application, or use return EXIT_FAILURE; if something goes wrong.
Final Code
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char const **argv)
{
if(argc == 1)
{
fprintf(stderr, "Usage: %s <KEY>", argv[0]);
return EXIT_FAILURE;
}
for(size_t i = 0; argv[1][i]; i++)
{
if(!isdigit(argv[1][i]))
{
fprintf(stderr, "expected only integer value\n");
return EXIT_FAILURE;
}
}
// we don't need to check whether `argv[1]` is all digit or not at this point
int KEY = strtod(argv[1], NULL);
printf("argc = %d\n", argc);
printf("KEY = %d\n", KEY);
return EXIT_SUCCESS;
}

isdigit function is not catching mixed values in argv[]

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// check for correct 1 integer argument else print instructions
if (argc == 2 && isdigit(*argv[1]))
{
printf("plaintext: ");
printf("rawtext: ");
return 0;
}
else
{
printf("Usage: [KEY]\n");
return 1;
}
}
The program should print "Usage: [KEY]" if the user enters ./program 2z but isdigit is not catching "z". Is there a way to correct this or is there any other alternative to isdigit function?
You need to call isdigit() in a loop, testing each character, since it only checks one character at a time.
if (argc == 2 && argv[1][0]) {
for (int i = 0; argv[1][i]; i++) {
if (!isdigit(argv[1][i]) {
printf("Error: key must be numeric\n");
return 1;
}
}
printf("plaintext: ");
printf("rawtext: ");
return 0;
} else {
printf("Usage: %s key\n", argv[0]);
return 1;
}

Using argc and argv in Caesar cipher in C

So, I am trying to use argc and argv in Caesars cipher in order to execute the program with just [./ key ;string] (e.g. ./ 13 Caesar). I have tried in lots of ways, although I must admit I am really lost here. I was thinking I should just use main(void) and ask the input with fgets, but I still have some curiosity in: How could I make it work with “int main(int argc, char *argv[])?”. Any clues you can give me?
Thank you for your help. Here is the code with the current outputs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int key;
int result;
char str[60];
int k = 0;
printf("argc =%d\n", argc);
printf("argv =%d\n", argv);
printf("key =%d\n", key);
if (argc != 2)
{
printf("You didn't enter a key.\n");
return 1;
}
else
{
int k = key % 26;
printf("k =%d\n", k);
if (k == 0)
{
printf("Invalid key.\n");
return 1;
}
}
}
Output:
$ ./ceasar 13
argc =2
argv =-13216
key =0
k =0
Invalid key.
Edit: Tentative Answer
int main(int argc, char* argv[])
{
int i;
int key = atoi(argv[1]);
int result;
char str[60];
for (i = 0; i < argc; i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
if (argc != 2)
{
printf("You didn't enter a key.\n");
return 1;
}
else
{
if (key == 0)
{
printf("Invalid key.\n");
return 1;
}
}
}
Printing argv with the "%d" specifier is undefined behavior, read printf()'s manual and use "%p".
On the other hand, if you want to print the string you should access the appropriate element with array notation. For example
printf("First Argument: %s\n", argv[1]);
this applies to all arguments, noting that argv[0] is the name of the executable as invoked in the command line.
You should also be careful before accessing argv[1] to check that argc > 2, and always check the current argument + !.

Segmentation fault in program using command line arguments

I'm trying to write a program that finds the largest and smallest of 10 numbers.
To use my program, you must use the command line argument -l then numbers to determine largest number, the same for the command -s for smallest numbers.
However, when I don't enter a command at all, and just try to run the program, I receive a segmentation fault. Not sure where I went wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
int i;
int min,max,num;
char *argv1 = argv[1];
char *small = "-s";
char *large = "-l";
min=max=0;
if (0==strcmp(argv1, small))
{
for (i=2; i<argc; i++)
{
num=atoi(argv[i]);
if(i==2)
{
min=num;
}
else
{
if(min>num)min=num;
}
}
printf("The smallest number is %d\n",min);
}
else if (0==strcmp(argv1, large))
{
for (i=2; i<argc; i++)
{
num=atoi(argv[i]);
if(i==2)
{
max=num;
}
else
{
if(max<num)max=num;
}
}
printf("The largest number is %d\n",max);
}
else
{
printf("Invalid option");
}
return 0;
}
Check the number of arguments before accessing to arguments.
int main(int argc, char* argv[])
{
int i;
int min,max,num;
char *argv1 = argv[1];
char *small = "-s";
char *large = "-l";
/* add from here */
if(argc < 2)
{
fprintf(stderr, "Usage: %s command numbers...\n", argc > 0 ? argv[0] : "");
return 1;
}
/* add until here */
min=max=0;
You're setting char *argv1 = argv[1]; without first checking argc to see how many arguments were passed. This will cause a segfault when you later do if (0==strcmp(argv1, small)) because argv1 isn't pointing at a string like you are expecting it to.
To fix it, just check argc before you start comparing argv1 with anything:
if (argc == 1)
{
printf("Error: -s or -l required\n");
exit(1);
}

How can I break a number that I input in the terminal into digits?

Ok so what I have to do is input a binary number IN THE TERMINAL, probably using argv[] or something, and then break it into each digit.
What I have is this:
int bits[31];
for(int i=0; i<31 && 1 == fscanf(stdin, "%1d", &bits[i]); ++i);
This works for the scanf, but I would want a SIMPLE way of doing so but with the input being in the terminal
This code accepts a binary number as the program argument. Most of the code is devoted to weeding out any invalid argument.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int len;
long bin;
if (argc < 2) {
printf("Please try again with an argument supplied\n");
return 1;
}
len = strlen(argv[1]);
if (strspn(argv[1], "01") != len) {
printf("The argument is not a binary number\n");
return 1;
}
printf("First bit is %c\n", argv[1][0]);
printf("Last bit is %c\n", argv[1][len-1]);
bin = strtol(argv[1], NULL, 2);
printf("As a long integer variable, the input is %ld\n", bin);
return 0;
}
Without error checking (except against crashing), this reduces to
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int len;
if (argc > 1) {
len = strlen(argv[1]);
printf("First bit is %c\n", argv[1][0]);
printf("Last bit is %c\n", argv[1][len-1]);
printf("As a long integer the input is %ld\n", strtol(argv[1], NULL, 2));
}
return 0;
}

Resources