I wrote this code to take input from the command line, and depending on the input, will perform a set of actions, or if the input is incorrect, throws an error. However, I also need to check if no arguments are supplied, which I try to account for in my else statement.
if(strcmp(argv[1], "-L") == 0)
{
//does stuff
}
else if(strcmp(argv[1], "-W") == 0)
{
//does stuff
}
else if (*(argv[1]) != 1)
{
puts("error: invalid input");
}
else //should check if no arguments
{
puts("error: expected command line argument");
return 1;
}
I am getting a segmentation fault whenever there are no arguments from the command line, and I'm not sure how to fix it. I have also tried to write the else statement this way:
else if(argc < 2)
{
puts("error: expected command line argument");
return 1;
}
This was based on my previous research on here where I found "C produce error if no argument is given in command line," but it won't work either. I am a beginner in C and do not fully understand argc and argv, so if anyone has any suggestions or logic I'm completely overlooking, please let me know.
You need to check if argc < 2 before anything else.
Else you get segmentation fault because argv[index] could be something you have not privileges to access.
Whatever you do, make sure you never try to access an index of argv that is greater or equal to argc. In your case, you are accessing index 1 when the last available index is 0 (argc is 1), that's why the segmentation fault. See this post for more info: What does int argc, char *argv[] mean?
Related
Why is the return 1 necessary in the code below? Is this to stop the loop from 'looping' after '1' cycle since it will go ON forever if the Boolean expression is false?
while (argc != 2 || isnumber(argv[1]) == false)
{
printf("Usage: .caesar key\n");
**return 1;**
}
Can you explain this step by step?
The statement should actually be if statement instead of while, as you execute the program once (with some input) and you cannot change it on-the-run.
return 1 (as well as EXIT_FAILURE macro) means that there was an error in the program, which in your case is bad number of arguments.
return 0 (and EXIT_SUCCESS macro) means that program finished without any errors.
The return 1 is necessary as if you provide the wrong number of command line arguments, it will return 1 to indicate a failure, which is to stop the program. You actually do not need the while loop, you can actually do
if (argc != 2 || isnumber(argv[1]) == false)
{
printf("Usage: .caesar key\n");
return 1;
}
You can also use other numbers bigger than 0 for failure and return 0 is for success.
Okay so overall im trying to complete a basic CLI C program which will complete functions such as clear, quit, cd, ls, help (bring up the unix man) etc.. i altered my code and so far i have this, im getting segmination error when trying to execute the cd command part of the program, (im very new to c btw);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main (int argc, char *argv[])
{
char input[] = " ";
char *argument;
while(strcmp(input, "quit")!= 0)
{
printf("$");
scanf ("%s", input);
if(strcmp(input,"clear") == 0)
{
printf("\e[1;1H\e[2J");
}
else if(strcmp(argv[1],"cd") == 0)
{
if(chdir(argv[2]) == -1)
{
printf("\n directory does not exists");
}
}
else if(strcmp(input, "echo") == 0)
{
char str[50];
scanf("%[^\n]+", str);
printf(" %s", str);
}
}
}
input is declared as a ' ' (space) character. It will never match 'cd'.
This is probably more along the lines of what you want to achieve, where the first parameter is the command (cd), and the second will be the directory:
int main (int argc, char *argv[])
{
char *argument;
if(strcmp(argv[1],"cd") == 0)
{
if(chdir(argv[2]) == -1)
{
printf("\n directory does not exists");
}
}
Edit Also please note that there is no need for the else satement. If chdir does not return an error, it will change the directory, thus no need to call it again in an else.
Additionally, another tip for using system calls in general, it would be of great help if you print the error number returned by the system upon a failure in system call. This will make things easier when things start going wrong. To do this simply include <errno.h>' and modify the printf to printerrno` which gives specific details about the error:
printf("Chdir error: %d", errno);
For instance chdir() does not only return an error when the directory does not exist, but also for example if you do not have permissions to view the contents of the directory. See the man page for a list of possible errors.
To implement your own shell, you need to take input directly from stdin, not from command-line arguments (argv) from another shell. The basic pattern is like this:
Read input
Execute command
Print results
Loop back to step 1
I am trying to make a program check whether the user is passing a program parameter when running the program. fx:
./dev --print
I came up with the following:
int main(int argc, char *argv[]) {
char print[] = "--print";
if(strcmp(argv[1], print) == 0) {
solve_a_bunch_of_functions_and_print_without_user_input();
}
else {
ask_for_user_input();
then_solve_bunch_of_functions();
}
}
Is this the correct / smartest way to do so?
Currently I am experiencing issues with seg-faults after this implementation for everytime i get into the else statement. Not sure my implementation here has anything to do with it.
Yes, that's one way although I think most C programmers wouldn't bother with the separate variable, and just do:
if(strcmp(argv[1], "--print") == 0)
Of course, you should first validate that there is an argument in argv[1], by checking argc, too. Otherwise you're passing NULL to strcmp(), which is a bad idea.
if(argc > 1 && strcmp(argv[1], "--print") == 0)
{
}
I need to keep prompting the user until they give me 1 argument. I have a while(1) loop with a break statement inside but it exits early when it is run with 2 arguments. How do I continue prompting instead of exiting? I want to do something like this:
bool flag = true;
while(flag)
{
// ..code
flag = false;
}
but that does not work in C. This is what I have so far.
int main(int argc, char* argv[])
{
while(1)
{
if(argc == 2)
{
reverse(argv[1]);
printf("Reversed string: %s\n", argv[1]);
}
else
{
printf("Error, wrong number of arguments. Please provide only one argument");
}
break;
}
return 0;
}
I tried deleting the break statement and got an infinite loop, as expected, but no "pause" of execution for the input argument.
You cannot do that. Command line arguments are passed to a program when it is started. You can't ask for more arguments just like that. The best you can do is notify the user to run the program with one argument only. I recommend simply ignoring the second argument if it is not needed, but still notifying the user that it was not needed.
I am working on a program that determines the mode of a set of values for example (3 4 2 3 3) should print out "3". The catch is the program must receive the option of the mathematical function to execute and its arguments as parameters in the main function so no user input. Everything must be inserted in the command line and check by using pointers. My program works except for example say the user enters (mode) but doesn't enter in any values after. This should then print a message that just says "ERROR" and the program ends. However it does not instead it prints
Johns-MacBook-Pro-2:AdvanceCalc jvdamore$ ./a.out mode
Segmentation fault: 11
when it should print
Johns-MacBook-Pro-2:AdvanceCalc jvdamore$ ./a.out mode ERROR
below is my code. So my question is does my if statement with strcmp(p[2], "") == 0 work in order to produce the desired error message? or am I doing something wrong?
int main(int n, char **p)
{
int i, x, A[100];
if (strcmp(p[1], "mode")==0){
if (strcmp(p[2], "") == 0){
printf("ERROR");
return -1;
}
for(i=2;i<n;i++){
if (sscanf(p[i], "%d", &x) != 1) {
printf("ERROR");
return -1;
}
if (x<1 || x>30){
printf("ERROR");
return-2;
}
A[i-2]= x;
}
find_mode(A, n-2);
}
Rather than comparing a string to "" with strcmp, you need to see if it is NULL. strcmp( NULL, "" ) does not work very well, and you should instead do:
if( p[2] == NULL )
(well, really, you should rename the varaible argv, and there are several other issues, but this is the main problem. Make sure you have checked that p[1] is not NULL before you reference p[2])