printing using argv and argc - c

here is a program which printing some information about my self
in this program if the user scanning /n its printing the name and
etc. but when i'm running this program using gcc its printing nothing at all.
i need to scan the parameters using argv and argc.
how can i solve that?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
int main(int argc, char** argv)
{
for (int i = 1; i < SIZE; i++)
{
if (argv[i] == ' ')
{
break;
}
if (argv[i] == 'n' || argv[i] == 'b' || argv[i] == 'f' || argv[i] == '?' && argv[i - 1] == '/')
{
switch (i)
{
case 'n':
printf("my name is : Daniel Zingerman \n");
break;
case 'b':
printf("my birth date is: 2/11 \n");
break;
case 'f':
printf("my favorite food is: ice cream \n");
break;
case '?':
printf("the instruction of the program:");
printf("There is a lot of parameters you can scan into the program:");
printf("1. /n - printing the name");
printf("2. /b - printing the birth date");
printf("3. /n - printing the favorite food");
printf("4. /? - printing the instructions");
break;
}
}
}
system("pause");
return(0);
}

You should use argc value to know what is last argument. Or you should test argv[i] == NULL. You seem not to understand argv is char **, so argv[i] is a char *, not a char.
Also learn to use getopt(), or getopt_long().

The argv[] array is created from the program name in argv[0] and then the command line arguments separated by spaces
/n /b /f will be returned in argv[1], argv[2] & argv[3], not as a single 'string' in argv[1]
Use argc to limit how many elements of argv[] you test, so that you do not go out of bounds:
for (int i = 1; i < argc; i++) {
Now you need to check that you have valid command line arguments:
if ((strcmp(argv[i], "/n") == 0) || ...
As you need an integer value for the case tests, use the second element of the argv[i]:
switch (argv[i][1]) {

Related

Check for specific command line arguments and then assign them to variables

Obligatory total noob here.
I am making a simple C program that reads some variables from a file from a simple function.
What I'm trying to accomplish, however, is to allow whoever calls the program to override the values read from the file if hey so specify in the command line arguments.
I would like to have something like this:
char* filename;
int number;
...
readConfig(filename, number, ...);
if (argc > 1) {
// Check if the variables were in the args here, in some way
strcpy(filename, args[??]);
number = atoi(args[??]);
}
I would like the program to be called as
program -filename="path/to/file.txt" -number=3
I figured out I could just tokenize each argument and match it to every assignable variable and discard the others, but I'm pretty sure that there's a more elegant way to do this (perhaps with getopts?)
Thank you so much for your help.
I found this on geeksforgeeks:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int opt;
// put ':' in the starting of the
// string so that program can
//distinguish between '?' and ':'
while((opt = getopt(argc, argv, ":if:lrx")) != -1)
{
switch(opt)
{
case 'i':
case 'l':
case 'r':
printf("option: %c\n", opt);
break;
case 'f':
printf("filename: %s\n", optarg);
break;
case ':':
printf("option needs a value\n");
break;
case '?':
printf("unknown option: %c\n", optopt);
break;
}
}
// optind is for the extra arguments
// which are not parsed
for(; optind < argc; optind++){
printf("extra arguments: %s\n", argv[optind]);
}
return 0;
}
So, when you pass -f, you need to also pass filename, like: ./args -f filename it will say:
$ ./a.out -f file.txt
filename: file.txt
When you pass -i, -l, or -r, or -ilr, it will say:
$ ./a.out -ilr
option: i
option: l
option: r
If you pass -f but without a filename, it will say option needs argument. Anything else will be printed to extra arguments
So, with it, you can add options to getopts, add new case, do a thing, like:
getopts(argc, argv, ":fn:")
-f filename, -n number, pretty easy

Segmentation fault in atoi command

I have the following code:
int main(int argc, char *argv[])
{
int value,direction=0;
char c;
printf ("go\n");
while((c = getopt(argc, argv, "wr:")) != -1) {
printf ("go\n");
printf("%c\n",c);
switch(c) {
case 'w':
printf ("go\n");
value=atoi(optarg);
printf ("go\n");
printf("The input value is %x",value);
direction=1; //1 for write
break;
case 'r':
direction=0; // 0 for read
break;
default:
printf("invalid option: %c\n", (char)c);
usage();
return -1;
}
}
}
Now when i run the program by writing
./spicode.out -w 25
I need to pick the 25 after w using optarg, but its producing a segmentation fault.
What am i doing wrong?
You should put colon between commandline options.
c = getopt(argc, argv, "w:r")
From gnu.org :
An option character in this string can be followed by a colon (‘:’) to
indicate that it takes a required argument
Therefore wr: becomes w:r

the C program does not execute the function outside the main

If I execute the exec() function in another C program as a main function it works perfectly, while if I put it as a function called in the main menu it gives me some warning and the function does not run.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int exec (void) {
char array[100];
char character;
int i = 0;
char* point;
int j = 0;
printf ("Digita una stringa");
printf ("\n");
do {
character = getchar();
array[i] = character;
i++;
}
while (character != '\n');
array[i-1] = '\0';
i = 0;
char* string[100];
char *word = strtok(array, " .");
j = 0;
while (word != NULL) {
printf("%s\n", word);
string[j++] = word; // Increment j
word = strtok(NULL, " .");
}
string[j] = NULL; // Make sure the array is NULL term
printf ("\n");
pid_t pid;
pid = fork();
int status;
if (pid == -1) {
perror("");
}else if (pid == 0) {
execvp(string[0], string); /* execute the command */
fprintf(stderr, "Failed to exec");
exit(1);
}
else {
//.. wait until the child ends
waitpid(-1, &status, 0);
}
return;
}
int read_input (void) {
int choice;
printf("Seleziona una voce dal menu");
do {
printf("\n");
scanf ("%i", &choice);
if (choice > 8 || choice < 1)
printf ("Attenzione, inserisci un valore contemplato dal menu");
}
while ( choice > 8 || choice < 1);
return choice;
}
void main (int argc, char *argv[]) {
printf ("------------------------\n");
printf (" MENU \n");
printf ("------------------------\n");
printf (" \n");
printf ("1) Esecuzione in foreground di un processo\n");
printf ("2) Ctrl -C\n");
printf ("3) Exit\n");
printf ("4) Background\n");
printf ("5) Pipe\n");
printf ("6) Jobs\n");
printf ("7) fg\n");
printf ("8) kill\n");
int menu = read_input();
switch (menu) {
case '1' :
exec ();
break;
case '2' :
//ctrl();
break;
case '3' :
//exit_();
break;
case '4' :
//background();
break;
case '5' :
//pipe();
break;
case '6' :
//jobs();
break;
case '7' :
//fg();
break;
case '8' :
//kill();
break;
}
}
this is the warning:
elaborato.c:31:16: warning: initialization makes pointer from integer without a cast [enabled by default] char *word = strtok(array, " .");
Regarding the problem related to input,
do {
printf("\n");
scanf ("%i", &choice);
if (choice > 8 || choice < 1)
printf ("Attenzione, inserisci un valore contemplato dal menu");
}
while ( choice > 8 || choice < 1);
Once you type an integer and press enter, the scanf() consumes the number and a newline is left in stdin. Next time the loop goes around (assuming input <1 or >8 or something else) scanf gets that newline and it goes on.
add a getchar() after the scanf().
The answer is in the warnings, you should move them from the comment into the question.
elaborato.c:31:16: warning: initialization makes pointer from integer without a cast [enabled by default] char *word = strtok(array, " .");
That means that word, which is a char pointer is being initialized from an integer. Therefore, it seems strtok() is returning an integer... that doesn't sound right.
From the strtok() man page:
#include <string.h>
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
That seems right, it returns a char *.... but it also says it's declared in <string.h>... which you aren't including. Since it's not defined, the compiler assumes it as int strtok().
Fix: add the #include <string.h> line.
The problem you are seeing is that of scanf getting skipped.
For more details you can refer here
The call to scanf() after the printf consumes the new-line character and continues without the user having to enter anything.
It reads the very next character from standard in, which is probably a newline character and thus not prompting you for any input.
I'm too tired to comment on the entire code (it is really bad), so I'll just write about the issue in question and how trivially it could be debugged.
First thing to do is to check if we get the number and return to main, hence:
int menu = read_input();
printf("got [%d]\n", menu);
Running this:
[snip]
1
got [1]
So we indeed get to this point.
As such now we check what is this compared to.
int menu = read_input();
printf("got [%d] '1'=[%d]\n", menu, '1');
Let's run:
1
got [1] '1'=[49]
So, menu stores an integer 1, while '1' is a character code for 1 in ascii, which, well, is not an integer 1.
In general I don't see what was the problem with narrowing it down.

Using getopt with no arguments

By default I want the program will read input from stdin and send it's output to stdout.
The -f option will cause the
program to read the input from a text file and the -o option will cause the program to write the
output to a file instead of stdout.
The –c if specified will display the output in a CSV format (either in stdout or to a file depending if -o is specified).
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
int main(int argc, char * argv[]){
char opt;
char *filename_in, *filename_out;
int i, flagC=0,flagF=0,flagO=0;
while((opt = getopt(argc,argv,"cf:o:")) != -1){
switch(opt){
case 'c':
flagC=1;
break;
case 'o':
flagO=1;
filename_out = optarg;
break;
case 'f':
flagF=1;
filename_in = optarg;
openFile(filename_in);
break;
case '?':
printf("Opt ?");
return 0;
default:
printf("Opt Default");
return 0;
}
}
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
}
for (i = optind; i < argc; i++)
printf("%s ", argv[i]); //prints anything without argument and space between
return 0;
}
Is there a better way to read input from stdin aside from checking each flag I created is set to 0?
char input[100];
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
// scanf("%s", &input);
}

Build a char converter program with argv[]

I am supposed to build a program that takes argv[1] and according to it transforms the characters into lower case or upper case.However I am stuck cuz C cant compare a pointer with a string.Any ideas on how to compare a pointer and a string,i dont want to compare them character by character.
Here is the code
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main (int argc,char *argv[])
{
char c;
if(argc!=2)
printf("Wrong use of program \n");
printf("The Format is Lower or Upper \n");
return -1;
if ((strcmp(argv[1],"Lower"))==0)
{
while((c=getchar())!=EOF)
{
printf("-");
putchar(tolower(c));
printf("\n");
}
}
if ((strcmp(argv[1],"Upper"))==0)
{
while((c=getchar())!=EOF)
{
printf("-");
putchar(toupper(c));
printf("\n");
}
}
if ((strcmp(argv[1],"Lower"))!=0 && ((strcmp(argv[1],"Upper"))!=0))
{
printf("Wrong use of program \n");
printf("The Format is Lower or Upper \n");
return -1;
}
return 0;
}
What you want to do is use the function strcmp or stricmp (for case insensitive).
Firstly, use strcmp which will return 0 if the char arrays match.
if (!strcmp(argv[1], "Lower"))
{
Secondly if more than one statement applies to an if condition, the statements must be encased in {}.
if (argc != 2)
{
printf("Wrong use of program \n");
printf("The Format is Lower or Upper \n");
return -1;
}

Resources