C program with command line options - c

I wonder how to write a C program with options that can be invoked by a terminal.
Example : Person.c
#include <stdio.h>
void main ()
{
char option;
if(option == 'f') printf("First Name");
else if(option == 'l') printf("Last Name");
else printf("Full Name");
}
Compile it with
cc Person.c -o Person
Objective :
I want to reach my program options through terminal.
Example :
./Person -f
Output : First Name

void main () is wrong, if you copied this from a book, throw the book away
It should be int main(int argc, char **argv), argc will then be set to the number of arguments and argv[1] .... argv[argc-1] are the argument strings (argv[0] is the name of the program)

Here's my $0.02:
#include <stdio.h>
#include <string.h>
int
main (int argc, char *argv[])
{
if (argc != 2) {
printf ("USAGE: ./Person [-f|-l]\n");
return 1;
}
if (strcmp (argv[1], "-f") == 0) {
printf("First Name");
}
else if (strcmp (argv[1], "-l") == 0)
printf("Last Name");
}
else {
printf ("Unknown argument\n");
return 1;
}
return 0;
}
Important points:
1) In C, you can't just compare strings (like "aaa" == "bbb"). You need special library functions, like "strcmp()" ("compare strings").
2) In order to use library functions, you need to #include headers (like "stdio.h", for "printf()", or "string.h", for "strcmp()"). You can find out which headers you need by using "man" ... or simply Googling for the relevant call ("google strcmp" should give you the same results as "man strcmp")
3) It's a good general convention to use the programs return values to indicate "success" or "failure". "0", by convention, usually means "success".
4) Finally, for your purposes, it's essential to use "argc" and "argv" to access your command line arguments.
5) The "if (argc != 2)" at the top insures that you've entered at least one command line argument (argument "0" is the name of the program itself). This is important because trying to read an argument you don't have ("trying to read off the end of the array") could cause a crash ;)
'Hope that helps!

Please change your main prototype as
int main(int argc, char *argv[])
The options as asked by you in your question can be passed using the input arguments to the main function as given above.
The argc parameter tells you how many inputs has been passed through terminal and the argv will provide you each input as an array of char *. Please note that the first input (argv[0]) will be by default the filename of the executable with full path and the rest of inputs will follow it.
http://www.cprogramming.com/tutorial/c/lesson14.html - This tutorial will also be of some help.

The correct form for a main function is:
int main(int argc, char **argv) {
}
Then argv holds your command line arguments:
int main(int argc, char **argv) {
for(int i = 0; i < argc; ++i) {
printf("arg %d is %s", i, argv[i]);
}
return 0; // indicates that the program completed successfully
}

Call main with these inputs:
int main ( int argc, char **argv)
argc is the number of args, and argv is an array of the command line arguments. Note that the first argument of argv is the program name.

you have to tell C that your giving it options
int main(int argc, char **argv)
argc is the number of arguments and argv is the argument you call
so then ./Person -f
you need to tell it
if (strncmp(argv[i],"-f",1) == 0) {

You should also look at some of the parsing libraries out there. Many people have written great libraries for parsing command line options so that you don't have to repeat all of the work of validating options. Most are pretty easy to use, as well.

Related

How to solve segmentation fault in c?

When I was making my program I got an error type of thing called Segmentation Fault.
#include <cs50.h>
#include <string.h>
#include <stdio.h>
int main(int argc, string argv[])
{
char i = strlen(argv[2]);
if (argc == 2)
{
printf("%i %s %hhd", argc, argv[2], i);
}
}
I run this program using these commands
make substitution
and then
./substitution abcdefghijklmnopqrstuvwxyz
In this we have to add a 26 word key which in the above line is a to z.
Please help if you know to solve
If you invoke your program with:
./substitution abcdefghijklmnopqrstuvwxyz
argc will be 2, and argv will be an array of 3 pointers:
argv[0] points to the string ./substitution, argv[1] points to the string abcdefghijklmnopqrstuvwxyz, and argv[2] is NULL. If you attempt to compute the length of NULL by calling strlen(argv[2]), that is an error. You must not pass NULL to strlen. I think your error is simply mis-indexing the argv array. Arrays in C are zero based. If you want to compute the length of the first argument, you want to work with argv[1], not argv[2]:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int rc = EXIT_FAILURE;
if( argc > 1 ){
size_t i = strlen(argv[1]);
printf("%i %s %zd\n", argc, argv[1], i);
rc = EXIT_SUCCESS;
}
return rc;
}
You got hit with segfault because the number of required arguments specified was done poorly. The main problem is here:
if (argc == 2)
The number of actual arguments passed by the user is equal to the number of required arguments minus 11. It should be:
int main(int argc, char *argv[]) {
if (argc != 3) {
// Number of arguments are either greater or lesser than 3
// Handle the error
}
// Ok...
}
You can safely use the arguments now.
1. The calling command for the program, for example ./a.out is also counted as an argument (argv[0]).

How to check if command line parameters are integers

First of all, I am talking about old-fashioned ANSI-C (I mean the ANSI standard and no C99 or newer) compiled with gcc. I am only allowed to use the libraries that can be seen below in the code.
My problem is I have a program that is called in the following way on the Terminal:
program < integer_1 integer_2
While I have been able to figure out how to check for the number of arguments, I'm stuck on checking if those are integers.
If the program is called like this:
program < 1 -13
it should run without complaining but if it is run like this:
program < s 7
it should throw out an error.
Whatever I have tried so far has been utter rubbish. The best thing I have managed so far has been an error message if the second number has been a character. None of my tries has been able to deal with more than one digit but I have figured out why that is.
The problem is that I haven't used command line / terminal arguments with any programming language i now (C++, Java). I would really appreciate it if someone could show me how check for correct input as frankly I am out of ideas.
Am I correct that if I want to deal with numbers bigger than 9, I have to iterate through argv starting from index 2 until I find a space?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int arc, char *argv[])
{
if(arc != 3)
{
printf("Error: You have entered %d arguments, but two were expected!", arc - 1);
return -1;
}
return 0;
}
The easiest way out is to iterate over the argv[n]s and pass one by one to them to strtol() or similar. Then, check for the error and make the decision. To quote the man page, (emphasis mine)
long int strtol(const char *nptr, char **endptr, int base);
[...]
If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
That said, program < integer_1 integer_2 is not exactly the way to pass the command-line arguments. If you want to pass the values arguments as command-line arguments, you shall lose the redirection operator and work with argc and argv[n]s directly..
Best way is to create a function for checking whether it is number or not.if the below function returns true then use atoi(argv[]) to convert them to integers to use it further.
bool isNumber(char number[])
{
int i = 0;
//checking for negative numbers
if (number[0] == '-')
i = 1;
for (; number[i] != 0; i++)
{
//if (number[i] > '9' || number[i] < '0')
if (!isdigit(number[i]))
return false;
}
return true;
}
Just a comment: not an answer
If you are going to use
program < arg1 arg2
You will not see arg1 or arg2 in the main parameters. arg1 is typically a filename or device which contain data which will be read by the program. I don't know if the program will even be able to access arg2. If you wish to pick up arg1 arg2 etc, lose the <
program arg1 arg2
You can try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int check_cmd_args(char const *str[], int numargs);
int
main(int argc, char const *argv[]) {
if (argc < 2) {
printf("Not enough command line arguements entered\n");
exit(EXIT_FAILURE);
}
if (check_cmd_args(argv, argc)) {
printf("All Command line arguements are integers\n");
} else {
printf("Error, non-integer command line arguement entered\n");
}
return 0;
}
int
check_cmd_args(char const *str[], int numargs) {
int n, i = 0;
for (n = 1; n < numargs; n++) {
if (str[n][0] == '-') {
i = 1;
}
for (; str[n][i]; i++) {
if (!isdigit(str[n][i])) {
return 0;
}
}
}
return 1;
}

Comparing C strings vs. string pointers for equality

So I am working on a project to create and use a shell. One thing that must be done is "|executable| -p |prompt| should allow the user to select an user-defined prompt. Otherwise, the default should be “257sh> ”. I wrote my code to do this however no matter what it keeps moving into the else statement. After some experimenting I know that my argv[1] == "-p" line is what is causing the issue, because without it the code works. The thing is that when I print out argv[1], it prints "-p" (assuming thats what I input). Here is my shell function.
void shellLoop(char *n)
{
char *line;
char **args;
int status;
char name = n;
do{
printf("%s>", n);
line = sysReadLine();
args = splitLine(line);
status = execute(args);
free(line);
free(args);
}while(status);
}
And here is my main function
int main(int argc, char *argv[])
{
if(argc == 3 && argv[1] == "-p"){
shellLoop(argv[2]);
}
else{
shellLoop("257sh");
}
return EXIT_SUCCESS;
}
When you do argv[1] == "-p" you compare two pointers, and two pointers that will never be the same.
To compare strings in C you use the strcmp function: strcmp(argv[1], "-p") == 0.
You can also use strncmp(char *str1,char *str2,int n) to compare the first n bytes of two strings.

Unexpected output in if & switch statements in C code

I cant figure out why either of the following code fails to operate as expected.
There both compiled into execution files.
Outputs:
a.out , prints 1, expected "no value"
a.out 1, prints 2, expected 1
a.out 2, prints 2, expected 2
Using a case:
void main(int in)
{
int a = in ;
printf("In function if\n");
if ( in == 1 )
printf("1\n");
else
if ( in == 2)
printf("2\n");
else
printf("wrong value\n");
}
Using a switch:
void main(int in)
{
switch( in )
{
case 1: printf("1\n"); break;
case 2: printf("2\n"); break;
default: printf("wrong value\n"); break;
}
};
I'm trying to get the following LISP functionality in C code:
(cond ((= in 1) 1)
((= in 2) 2)
(t nil))
Thank you for your assistance.
main doesn't accept the input from the command line as direct arguments, you are getting the argument count in there which is 1 if there are no arguments, and 2 if there is one argument, which causes the strange behavior.
main should be defined as int main( int argc, char *argv[] ) or something similar. To get the input, you need to first check if it exists by testing argc (the argument count, plus one for the executable path), and then converting argv[1] to an integer. atoi can be used to convert a string to an integer.
Note that the first parameter to main is argc, the total count of app name + parameters given on the command line. There is a second argument on main, char *argv[] for receiving the command line parameters.
The reason you get the behaviour described is because your parameter in replaces the purpose of argc. i.e. when you execute the App with no command line params, the argc count is 1, with one param, it will be 2, etc - this is the value passed to in. Since you don't have a second main parameter for the command line parameters (argv), you won't receive the actual parameters at all.
To fix this, you'll need to parse the second args array for your in integer parameter:
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 2)
return EXIT_FAILURE; // ... print out the correct command line usage to user
char *endPointer = NULL;
long in;
in = strtol(argv[1], &endPointer, 10);
if (endPointer != NULL) {
switch( in ) {
case 1:
// ... same code as above
}
return EXIT_SUCCESS;
}
return EXIT_FAILURE; // User hasn't provided a number for 1st param
}
Ide One Sample Here

How to valid 2 sticked argc in C

I'm making a very simple program code.
First, it has the option "-num" as 2nd argc. If you input anything in the 3rd argc, the program will simply say that the 3rd argc is entered.
Here are the examples of the inputs and outputs.
Input command line 1:
./test -num
Output 1
-num
Input command line 2:
./test -num AnythingHere
Output 2
-num 3rdArgcEntered
I also want the following command line with sticked argc (-num and AnythingHere are sticked together) to give the same output as Output 2:
./test -numAnythingHere
The output I wish to get is:
-num 3rdArgcEntered
But I obtained:
None
This is the source code I'm currently working on:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
if (!strcmp(argv[1], "-num"))
{
printf("-num ");
if(argc==3){
printf("3rdArgcEntered");
}
}
else
{
printf("None");
}
printf("\n");
return 0;
}
a little trash..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
/* doesnt check when args are not entered */
char *tmp = argv[1];
char buff[5];
/* copy -num, doesnt check */
memcpy(buff, tmp, 4);
buff[4] = '\0';
if (!strcmp(buff, "-num"))
{
printf("-num ");
/* larger than -num */
if(argc==3 || strlen(tmp) > 4 ){
printf("3rdArgcEntered");
}
}
else
{
printf("None");
}
printf("\n");
return 0;
}
Your program can't affect how the arguments are passed; obviously main has already been called at the beginning of main. You need to parse each argument yourself, or use a library that does it for you. For parsing them yourself, you could look at strtok or sscanf, or iterate over the characters. But a more specific library, such as getopt, is generally preferable, since it makes it easy to get your program to behave in a manner consistent with other command-line utilities.

Resources