Passing parameters in C with and without " " - c

How can i recognize if a parameter is passing with or without " ".
For example:
$ ./a.out "Hello I am chain of characters with spaces"
$ ./a.out Hello I am not a chain of characters with spaces

The quotes are parsed and handled by (in this case) the Linux shell.
In the first case, the shell is essentially doing this:
execl("./a.out","a.out","Hello I am chain of characters with spaces", NULL);
While in the second case, the shell is doing this:
execl("./a.out","a.out","Hello", "I", "am", "chain", "of", "characters", "with", "spaces", NULL);
Once your program gets called, the shell has already done the argument handling. All you can do at that point is to look at argc to see how many arguments you have, and to look at each inidividual argument to see if it contains spaces and handle them accordingly.

Look at argc (count of arguments). In the first case it'll be 2, in the second it'll be much higher. (2 because element 0 of argv will be a.out, element 1 will be the quoted string).

Related

Why does my bash script not work in my C program?

My program takes an arbitrary number of words from the user and stores them in a double pointer **stringArr. These values are then concatenated into a string which is then passed into a bash script I have.
The problem I have is that the bash script doesn't echo the command I want it to, and I am unsure why.
string = malloc(N * sizeof(char));
for (int j = 0; j < N; j++) {
strcat(string, stringArr[j]);
strcat(string, " ");
}
puts("\n\nYour input sorted in alphabetical order:");
if (fork() == 0) {
execl("./sortString.sh", "sortString.sh", string, NULL);
}
#!/bin/bash
for NAME in "$#"
do
VAR=$VAR" "$NAME
done
echo $VAR | tr ’ ’ ’\n’ | sort | tr ’\n’ ’ ’
Is there something I am missing?
Note: the bash script is in the same directory as the program; the program works in regards to taking user input and it putting into the string string.
If you want to try out the bash script, an example of string I have passed through is: "one two three " (there is a space after 'three').
You cannot use the exec() family of functions to execute a shell script directly; they require the name of a proper executable. If you check the return value of your execl() call, I'm sure you'll see an error (-1), and errno will probably have been set to ENOEXEC.
You could try using system() instead, but it is generally frowned upon because you'd need to build a full (single) command string, and making sure that everything is properly escaped and such is error-prone.
Instead, I'd recommend that you give "/bin/sh" or "/bin/bash" as the first argument to exec(). Then, the args to sh would need to be the path of your script, and then the args that your script will use.
(this is what your shell does automatically when you run a script; it reads the #! line, and executes "/bin/bash your-script your-args...")
Your string allocation is too small. You're allocating space for N chars, but you're strcating N spaces into it, plus whatever is in your stringArr (which I assume is not full of empty strings).
Even then, you will have just one big string of args, but exec() wants them separated. Think of it like if you point quotes around all the args in bash; you get just one big argument, which contains spaces.
After you fix that (so that you have an array of strings rather than just one big one), you will run into problems with execl(). It takes the arguments separately, but you're trying to send one big array of them. You'll want execv() instead, which accepts an array of strings for the argument list. Remember that the first string in that list must be your script path.
Are you sure this wouldn't be easier to do with qsort()?

command line arguments argv and argc

I understand that argc counts the number of arguments and argv takes in the argument, but is their a way I can determine if my argument from argv was inputted in a certain format like in parentheses and not in parenthesis. Such as ./a.out "Hello Word" and ./a.out Hello World?
Yes and no. Basically the only way to do this is to do a string comparison with a function like strcmp. However, one thing that complicates the matter is that the shell you are using might remove the quotes before your program has a chance to see them. To make things worse, how this is handled depends on the shell, so what works for one shell might fail for another one. Posix shells (sh, bash, ksh and so forth) handles quotes the same way and do not offer any way of detecting it.
This program:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Number of arguments: %d\n", argc);
for(int i=0; i<argc; i++)
printf("Argument %d: %s\n", i, argv[i]);
}
yields this output for an asterisk as argument when using the shell bash:
/tmp/test$ ./a.out *
Number of arguments: 3
Argument 0: ./a.out
Argument 1: a.out
Argument 2: main.c
This is because the * expands to all files in the current directory by the shell. Quotes usually group things that would otherwise be seen as two different arguments. If you want to pass quotes to bash you can escape them.
/tmp/test$ ./a.out "Hello world"
Number of arguments: 2
Argument 0: ./a.out
Argument 1: Hello world
/tmp/test$ ./a.out \"Hello world\"
Number of arguments: 3
Argument 0: ./a.out
Argument 1: "Hello
Argument 2: world"
So the answer is unfortunately no. There is no general method to do this. Some shells might provide tools to do this, but there is no guarantee for that, and even if they do, there is no standard way to do it.

What is the definition of an "argument in C"

I'm having some trouble reading a line of the code, and understanding what constitutes an argument in the context of this line of code. This is saved in a file called argv0.c
#include <cs50.h>
#include <stdio.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
printf("hello, %s\n", argv[1]);
}
else
{
printf("hello, world\n");
}
}
I compile the code as follows:
make argv0
./argv0
following which I am prompted for an input. Herein lies the issue:
if I type in "Dion Lim" in the terminal, is Dion Lim considered an argument? If so, is it two arguments?
Why is it that if I type in "Dion Lim" in the terminal, I get "Hello, World", but if I type in "Dion" i get "Hello,Dion"
Q1) Yes, they are two arguments.
Q2) Because argc consider the name of executable it's the first parameter. So:
./argv0 Dion Lim // argc == 3
./argv0 Diom // argc == 2
./argv0 // argc == 1
You can get more detail here.
if I type in "Dion Lim" in the terminal, is Dion Lim considered an
argument? If so, is it two arguments?
It depends on how your shell handles it of course, but usually "Dion Lim" would be one argument while Dion Lim (without the quotation marks) would be two arguments. The space delimits the arguments, and with the quotes you can work around that if you want space in your input (sometimes you can also escape the space, like Dion\ Lim).
Why is it that if I type in "Dion Lim" in the terminal, I get "Hello,
World", but if I type in "Dion" i get "Hello,Dion"
The argc parameter tells you how many arguments you have (I think of it as standing for "argument count"). The program's name also counts as an argument, so if you only pass Dion, then argc will be 2 already. If you pass Dion Lim, it will be 3.
To see the number of arguments check the value argc (arguments count). There is always at least one input argument, which is the program name.
So with./argv0 Dion Lim there are three input arguments.
If you are wondering make compiles the program using Makefile so if look in the directory you from which you are running make you will find a file named Makefile containing the compilation instructions.
According to the C Standard (5.1.2.2.1 Program startup)
— If the value of argc is greater than zero, the string pointed to
by argv[0] represents the program name; argv[0][0] shall be the null
character if the program name is not available from the host
environment. If the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent the program
parameters.
So if you "manually" supply the argument Dion then argc will be exactly equal to 2. The first program parameter will be the program name (as it is followed from the quote) and the second program parameter will be the word Dion.
If you will type Dion Lim then the host system considers them as two program parameters and together with the program name argc will be equal to 3.
However if you enclose the input Dion Lim in parentheses like "Dion Lim" then the system will consider the input as one parameter and your program will output
hello Dion Lim

C - argv[] passed in * as parameter, returns 1 when printed

I'm trying to see if * is passed in as a parameter in argv, but I'm not sure how to begin testing for it. When I did a
printf("%s\n", argv[1]);
The code prints out 1. I tested and ran
./a.out \*
To escape the input, which did work and printed "*", but I want t be able to pass in * without escaping from the user end and be able to see that * is passed. I can't just test for
if (strcmp(argv[1], "1") == 0)
Because that'd be testing if I passed in 1 like
./a.out 1
How should I do this??
This is nothing to do with c. Its your shell processing its line before running your program. You don't specify your os, but you will need to escape the arguments whatever
The shell is responsible for command line preprocessing before it runs a program. * is knowns as a wildcard. It is not the only wildcard, there are also ?, [, { and substitutons of $. You can escape preprocessing wildcards by prefixing them with \ or enclosing parameters in quotations '
./a.out '*'
I can't just test for
if (argv[1] == "1")
Because that'd be testing if I passed in 1 like
./a.out 1
You can not test it either. argv[1] == "1" does not compare strings, it compares pointers and the comparison always is false.

Process command line argument on windows

I need a hand in terms of processing command line argument (on Windows) in C.
Suppose I have the following situation
C:\Users\USER\Desktop> my_executable arg1 ' "A>200 && B<300 (just some conditions" '
In this case argc = 5
and
C:\Users\USER\Desktop> my_executable arg1 '"A>200 && B<300 (just some conditions"'
In this case argc = 3
Depending on users, the argv and argc will be different.
How can I write the code such that the condition and arg1 can be stored correctly :)
Required:
arg1 is stored into a char pointer
condition is also stored into a char pointer
Thanks
Don't use single quotes as argument quotes on Windows unless you want to implement your own argument parser. ^ can be used to escape " and itself and a few other things. To embed " in arguments use "".
If you really need to, call GetCommandLineW and parse yourself. GetCommandLineW returns a string that consists of the executable image name possibly enclosed in double quotes, followed by an optional space and the arguments exactly as given to CreateProcess (which means that ^ processing has already taken place).

Resources