Unexpected output in if & switch statements in C code - c

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

Related

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.

I'm have trouble deciding odd or even using the argument from command line

#include<stdio.h>
int main(int argc, char** argv){
if ( argc%2 == 0 ){
printf("even\n");}
else if( argc%2 == 1 ){
printf("odd\n");}
else{
printf("error\n");}
return 0;
}
The output is always even, but i dont know why.
argc is the number of arguments passed. The first argument for a main() function is the program name itself. So first check argc to see if there was an argument typed, then convert the argument to integer (it is passed as a string) and then make the odd/even test. Note you only need to do the even test, because if it is not even, it must be odd.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main(int argc, char** argv) {
if (argc < 2) // check number of arguments
printf("No argument entered\n");
else if (!isdigit(argv[1][0])) // check first char of user arg
printf("Not a number\n");
else if (atoi(argv[1]) % 2 == 0) // convert to int and test
printf("Even\n");
else
printf("Odd\n");
return 0;
}

C using getOpt to parse multiple arguments

I need to use getopt to parse the following command:
./center -n name –cp Anumber –i Anumber –t Anumber –s Anumber -fc nameOfaFile
All of them can be given out in any order.
So its clear i have to use getOpt.
So i have been investigation and this is what i have so far
void check_parameters (int argc, char** argv) {
int opt;
while((opt = getopt(argc, argv, "n:cp:i:c:fc:")) != -1) {
printf("give me opt %c \n", opt)
swicth(opt){
case 'n' :
//do something
case 'cp' :
//do something
case 'i' :
//do something
}
}
}
I do know for a fact that the 3 parameter: the OptString is where i tell getOpt what are the char of the options it should expect
Also in optarg is where the argument is
its not working!
when i printf( "give me opt %c", opt ) its giving me the numbers, not the char!
for this reason it does not work. it does not check the parameters correctly
Edit:
After doing man 3 getopt
the return value of getopt is: If an option was successfully found, then getopt() returns the option character. If all command-line options have been parsed, then getopt() returns -1.
it returns the option character? it always return integer 1. always! i don't understand how getopt works. how does the switch compare to characters?!
First of all, this:
case 'cp':
...makes no sense. You can't represent two characters with a char or int. Besides, if running your program with -cp 101, getopt will treat it as -c p 101, for a completely different result. If you want to use long options, use getopt_long instead and the appropriate calling syntax, per example: ./a.out -n 42 --cp 101.
Now, here's a working example of getopt() in action:
#include <stdio.h>
#include <getopt.h>
int main(int argc, char* argv[]) {
int opt;
while((opt = getopt(argc, argv, "n:cp:i:c:fc:")) != -1) {
switch (opt){
case 'n':
printf("n was %s\n", optarg);
break;
case 'i':
printf("i was %s\n", optarg);
break;
}
}
return 0;
}
getopt handles only single-character option names, not things like -cp or -fc (which it interprets as multiple option flags in a single string: -c -p, -f -c). If you want to stick to the syntax you defined, then it's easier to just roll your own:
// first check whether argc is odd, then:
for (i = 1; i < argc; i += 2) {
if (strcmp(argv[i], "n") == 0) {
name = argv[i+1];
} else if (strcmp(argv[i], "cp") == 0) {
// etc. etc.
}
}

C program with command line options

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.

Resources