I try to get the user to type a specific command line to execute my program, but ./caesar leads to segmentation fault, while no return statement is included. With return statement, everything works perfectly.
Can someone explain to me why that's the case and if there is another solution to fix this?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
int main(int argc, string argv[])
{
if(argc != 2)
{
printf("Usage: ./caesar key\n");
//return 1;
}
for(int i = 0, p = strlen(argv[1]); i < p; i++)
{
if(isalpha(argv[1][i]))
{
printf("Usage: ./caesar key\n");
}
}
}
return exits your function early, so the code afterwards doesn't get run. If you don't provide an argument, argc won't be 2, and argv[1] wouldn't be a valid string. With a return, then usage message prints and then the return stops execution there, so you don't try to call strlen(argv[1]), which will segfault.
Without the return, you print the usage message, but the code keeps running, and you call strlen(argv[1]), which will cause a segfault.
Related
when I input debug50 Caeser 1024 into my code space argc shows as 2 which is correct but argv shows as 0x7ffd87a68798
as shown here and idk why it doesn't show as 1024?
this is the first time I've used command line arguments so would appreciate any help, please.
This is my code so far also would appreciate any checks on my function I think that's wrong as well :/
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
bool only_digit(string argv[1]);
int main(int argc, string argv[])
{
//Make sure program was run with command line argument (argc)
if (argc == 2){
return 0;
}
else{
printf("Usage: ./caesar key\n");
return 1;
}
}
//Make sure every character in argv[1] is a number
bool only_digit(string argv[1]){
if (isdigit((*argv[1]))){
return true;
}
else{
return false;
}
}
You should check if no. of arguments doesn't match what you expect first and return if it doesn't.
Also, you should learn how to declare/define functions properly with arguments. argv[1] means you are expecting an array of strings of size 1.
Also, your function can be a single return statement.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
bool only_digit(string s);
int main(int argc, string argv[]) {
// Make sure program was run with command line argument (argc)
if (argc != 2) {
printf("Usage: ./caesar key\n");
return 1;
}
printf("%d\n", only_digit(argv[1]));
}
// Make sure every character in argv[1] is a number
bool only_digit(string s) {
return isdigit(*s);
}
So I've been working on this code for about a day now and finally managed to create the file without an error message popping up. As soon as I run it, though, this pops up:
Segmentation fault (core dumped)
`
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int k=atoi(argv[1]);
if (argc!=2)
{
printf("Usage: ./caesar key\n");
return 1;
}
else if (argv[1]<0)
{
printf("Usage: ./caesar key\n");
return 2;
}
else if (argv[1]== NULL)
{
printf("Usage: ./caesar key\n");
return 3;
}
string plaintext= get_string("plaintext: ");
printf("ciphertext: ");
for(int i=0; i<strlen(plaintext); i++)
{
if(plaintext[i]>='a' && plaintext[i]<='z')
{
printf("%c", ((plaintext[i]-97+k)%26)+97);
}
else if(plaintext[i]>='A' && plaintext[i]<='Z')
{
printf("%c", ((plaintext[i]-65+k)%26)+65);
}
}
printf("\n");
}
`
Can anyone tell me what I'm doing wrong here?
Haven't really tried anything to resolve this yet.
Even without seeing where it core dumps, I can see a number of issues with the code.
First thing is that you try to dereference argv[1] before checking how many parameters there are. i.e.
int k=atoi(argv[1]);
comes before
if (argc!=2)
{
printf("Usage: ./caesar key\n");
return 1;
}
If you run your program without putting in a value for the offset, this will cause a segmentation fault because C runtimes put a null pointer after the pointer to the last argument. So if you just typed ./caesar on the command line, argc is 1 and argv[1] is NULL.
This is the most likely cause of your crash.
This line:
else if (argv[1]<0)
doesn't really make any sense. You're comparing a pointer to 0. In many (all?) implementations, pointers behave like unsigned integers under comparison, so no pointer is ever less than zero.
This line
else if (argv[1]== NULL)
Is redundant if you have already checked that argc is two. Because, if argc is two argv[0] and argv[1] are guaranteed to point to strings.
On an unrelated note, I'd say that you should never do what that cs50.h header file does, which is have a typedef of something to char *. It just obfuscates what a string is.
This segment of code is meant to check if a user has entered only one numeric command-line argument, and return an error code of "1" if this is not the case. I have the code set up so that it first checks if argc is anything other than 2. Unfortunately, I am still receiving Segmentation Faults if no command line argument is entered, and I'm not sure why this code doesn't catch a null amount of command line arguments.
I tried moving the "if (argc !=2)" formula above the entire "for" statement to try and catch the command line argument issue right from the beginning, but I received the same result.
My question is, why am I receiving a Segmentation Fault when no command line argument is provided, and what am I missing to ensure the program doesn't Seg Fault with no command line argument?
Due to course policy, I will only be providing the segment of code in question.
#include <unistd.h>
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
// add'l variables //
int k = atoi(argv[1]);
for (int i = 0; i < strlen(argv[1]); i++)
{
if (argc != 2)
{
printf("Please enter only 1 command-line argument.\n");
return 1;
}
else if (!isdigit(argv[1][i]))
{
printf("Usage: ./caesar key\n");
return 1;
}
}
// add'l code //
Error as shown in Terminal
You must first check the argc before using the argv[1], because argv[1] may not have a valid pointer if argc < 2. A corrected version of your code could be like that:
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int i = 0;
if (argc != 2) {
printf("Please enter only 1 command-line argument.\n");
return 1;
}
while (isdigit(argv[1][i]))
++i;
if (argv[1][i] != '\0') {
printf("Usage: ./caesar key\n");
return 1;
}
return 0;
}
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
//Get the plain text
do
{
string pt = get_string("plaintext: ");
}
while (argc == 1);
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
Any reason I am getting an "expected expression" error on the "else" line? It says the expected expression is
"else {" but even when I move the bracket to the same line as the else, it still gives me the error. Also my first time posting on stack and one of my first programs so please let me know if I need to post additional details about the issue.
else cannot stand by itself. You need to have an if before the else. Apparently what you want is
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
//Get the plain text
if(argc == 1)
{
string pt = get_string("plaintext: ");
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
Even if your program had compiled it would have looped forever if argc was 1, since the value of argc would never have changed and the condition while(argc == 1) would have been true forever.
"else" needs "if" statement preceding it somewhere in the code...
Example:
if{
...
}
else {
...
}
I am stuck trying to iterate over each character to detect whether or not it is a digit, while only printing the answer once. The problem I'm having is I can get it to detect whether a character is a digit or not, but it prints out an answer for each number I put in until it reaches a letter. I'm looking how to get it to detect whether or not the input is a number or letter, and then make a decision on what to print out instead of printing success every time it detects a number. Feel like its something with my for loop but cant quite figure it out. Thanks.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
string n = argv[1];
if (argc != 2)
{
printf("usage: ./caesar key\n");
return 1;
}
else
{
for(int i = 0, length = strlen(n); i < length; i++)
if(!isdigit(n[i]))
{
printf("usage: ./caesar key\n");
return 1;
}
else
{
int convert = atoi(n);
printf("Success\n");
printf("%i\n", convert);
}
}
}
The problem is that inside the for you have an if-else statement... that means that one of both will always execute for every iterarion.
For printing success just once, you should erase the else keyword (and for clarity the brackets) but keeping the else code.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
string n = argv[1];
if (argc != 2)
{
printf("usage: ./caesar key\n");
return 1;
}
else
{
for(int i = 0, length = strlen(n); i < length; i++)
{
if(!isdigit(n[i]))
{
printf("usage: ./caesar key\n");
return 1;
}
}
int convert = atoi(n);
printf("Success\n");
printf("%i\n", convert);
}
}
What do I need to change so cs50 Caesar only prints the correct message after i iterate over each character?
It seems you aren't aware that you don't have to do that. The Caesar Specification says:
You can assume that, if a user does provide a command-line argument, it will be a non-negative integer (e.g., 1). No need to check that it’s indeed numeric.