Passing/Using Terminal Arguments with C - c

So the purpose of my program is to simulate a chat- one text file contains responses (call it r.txt) and I write my messages to another (call it m.txt). What I'm looking to do is write code for it in a c file using xcode, then call the program in my command terminal (I'm using Mac OSX). My question is- how does one pass multiple arguments to a C program using the terminal?
I see that in main theres 2 variables, int argc and const char* argv[]. So then does C use the array to account for multiple command line arguments? Cause essentially I'd do something like "$(name of the program), file_name_1, file_name_2." How would I reference these in my C file?

The main function is: int main(int argc, const char *argv[]).
The first one argc is the number of elements in the array argv. The first element argv[0] is the name of the program. After that you have the strings of each given parameters.
The command line (shell) separated the parameters (by default) with spaces. So myprog foo bar will result to argv[0]="myprog" argv[1]="foo" argv[2]="bar" (and here argc=3).
Several spaces are not taken in count. If you parameters contain spaces you have to use quotes (i.e. myprog "arg with spaces" other "many if wanted".

Related

Strange behavior of argv when passing string containing "!!!!"

I have written a small program that takes some input parameters from *argv[] and prints them. In almost all use cases my code works perfectly fine. A problem only arises when I use more than one exclamation mark at the end of the string I want to pass as an argument ...
This works:
./program -m "Hello, world!"
This does NOT work:
./program -m "Hello, world!!!!"
^^ If I do this, the program output is either twice that string, or the command I entered previous to ./program.
However, what I absolutely don't understand: The following, oddly enough, DOES work:
./program -m 'Hello, world!!!!'
^^ The output is exactly ...
Hello, world!!!!
... just as desired.
So, my questions are:
Why does this strange behavior occur when using multiple exclamation marks in a string?
As far as I know, in C you use "" for strings and '' for single chars. So why do I get the desired result when using '', but not when using "" as I should (in my understanding)?
Is there a mistake in my code or what do I need to change to be able to enter any string (no matter if, what, and how many punctuation marks are used) and get exactly that string printed?
The relevant parts of my code:
// this is a simplified example that, in essence, does the same
// as my (significantly longer) code
int main(int argc, char* argv[]) {
char *msg = (char *)calloc(1024, sizeof(char));
printf("%s", strcat(msg, argv[2])); // argv[1] is "-m"
free(msg);
}
I already tried copying the content of argv[2] into a char* buffer first and appending a '\0' to it, which didn't change anything.
This is not related to your code but to the shell that starts it.
In most shells, !! is shorthand for the last command that was run. When you use double quotes, the shell allows for history expansion (along with variable substitution, etc.) within the string, so when you put !! inside of a double-quoted string it substitutes the last command run.
What this means for your program is that all this happens before your program is executed, so there's not much the program can do except check if the string that is passed in is valid.
In contrast, when you use single quotes the shell does not do any substitutions and the string is passed to the program unmodified.
So you need to use single quotes to pass this string. Your users would need to know this if they don't want any substitution to happen. The alternative is to create a wrapper shell script that prompts the user for the string to pass in, then the script would subsequently call your program with the proper arguments.
The shell does expansion in double-quoted strings. And if you read the Bash manual page (assuming you use Bash, which is the default on most Linux distributions) then if you look at the History Expansion section you will see that !! means
Refer to the previous command.
So !!!! in your double-quoted string will expand to the previous command, twice.
Such expansion is not made for single-quoted strings.
So the problem is not within your program, it's due to the environment (the shell) calling your program.
In addition to the supplied answers, you should remember that echo is your shell friend. If you prefix your command with "echo ", you will see what shell is actually sending to your script.
echo ./program -m "Hello, world!!!!"
This would have showed you some strangeness and might have helped steer you in the right direction.

Trying to run a C program on Unix but a little confused with how input file is handled

I'm trying to run a C program in a Unix environment and I have an input file as well. The teacher said we can run it by typing in
gcc programName ./a.out inputFile
or
gcc programName ./a.out inputFile > viewFile
My question is: how is this handled within the C program? Like, is the input file being added as a parameter for main (or like its name or something) or is it acting like it's reading from system.in or something else?
I'm getting a message saying that there's an error opening the input file and I have int main(int argc, char* argv[]). If someone could explain what's going on and how the input file is handled, I'd really appreciate it.
Your professor mentions two ways of calling the file:
./a.out inputFile
./a.out inputFile > viewFile
For both forms:
argc would be 2.
argv[0] would be a string representing the program name,
argv[1] would be "inputFile".
POSIX shells interpret > filename to mean redirecting the program's output (specifically stdout) to the given filename.
Command redirections do not appear in the list of arguments from the program's perspective (although there are usually system-specific ways of finding the original command line out).
First off, gcc programName.c is a separate command.
./a.out inputFile calls your main function with argc = 2 and argv = { "./a.out", "inputFile", NULL }. (The shell splits the command line into words, then treats the first word as the name of a program and calls it with all arguments.)
./a.out inputFile > viewFile passes the same arguments to main as the example above. The difference is that > viewFile instructs the shell to open (and clobber/create) a viewFile file and redirect stdout to it before running the program. In other words, your program only sees ./a.out and inputFile as arguments, but everything written to stdout ends up in viewFile.

Trying to get an asterisk * as input to main from command line

I'm trying to send input from the command line to my main function. The input is then sent to the functions checkNum etc.
int main(int argc, char *argv[])
{
int x = checkNum(argv[1]);
int y = checkNum(argv[3]);
int o = checkOP(argv[2]);
…
}
It is supposed to be a calculator so for example in the command line when I write:
program.exe 4 + 2
and it will give me the answer 6 (code for this is not included).
The problem is when I want to multiply and I type for example
program.exe 3 * 4
It seems like it creates a pointer (or something, not quite sure) instead of giving me the char pointer to the char '*'.
The question is can I get the input '*' to behave the same way as when I type '+'?
Edit: Writing "*" in the command line works. Is there a way where I only need to type *?
The code is running on Windows, which seems to be part of the problem.
As #JohnBollinger wrote in the comments, you should use
/path/to/program 3 '*' 4
the way it's written at the moment.
But some explanation is clearly required. This is because the shell will parse the command line before passing it to your program. * will expand to any file in the directory (UNIX) or something similar (windows), space separated. This is not what you need. You cannot fix it within your program as it will be too late. (On UNIX you can ensure you are in an empty directory but that probably doesn't help).
Another way around this is to quote the entire argument (and rewrite you program appropriately), i.e.
/path/to/program '3 * 4'
in which case you would need to use strtok_r or strsep to step through the (single) argument passed, separating it on the space(s).
How the shell handles the command-line arguments is outside the scope and control of your program. There is nothing you can put in the program to tell the shell to avoid performing any of its normal command-handling behavior.
I suggest, however, that instead of relying on the shell for word splitting, you make your program expect the whole expression as a single argument, and for it to parse the expression. That will not relieve you of the need for quotes, but it will make the resulting commands look more natural:
program.exe 3+4
program.exe "3 + 4"
program.exe "4*5"
That will also help if you expand your program to handle more complex expressions, such as those containing parentheses (which are also significant to the shell).
You can turn off the shell globbing if you don't want to use single quote (') or double quote (").
Do
# set -o noglob
or
# set -f
(both are equivalent).
to turn off the shell globbing. Now, the shell won't expand any globs, including *.

Create Command to run and give an input to Windows Application

I want to make a Console Application for Windows Embedded Compact which will take an integer array input from User and that array will be passed as an argument to one of the function in the Application.SO,basically I want to make a Command to execute that application and also the command will contain the Integer array which the user want to pass to the Application. My Programming language is C.
I don't know how to make personalized command to be run from command prompt.
Any help or link for this will be greatly Appreciated.
Thank You.
This is where you start !!!!!!!!!!!!!!!!!
They're called Command Line Arguments
basically you pass it to main() like so:
int main(int argc, char *argv[]){
// argc is atleast 1 (contains the no. of arguments passed)
// argv[0] contains the image name and path
// argv[1] = first argument, argv[2] = second argument and so on..
}

how to check if there's a string in the command line

I have this command line:> write_strings "Hello World!" a.txt b.txt dir/a.txt.
all the elements (command, string, file names) go into an array of char pointer. how can I take an element and check if it's a string or a file name?
I don't mean the exact code lines, buts just need the idea. the program should return an error if there's no string.
You can use an API such as stat or access to check if the file pointed to by a path exists. There is no fundamental distinction between filepaths and regular strings when they are passed to your process.
If you're using the standard main(int argc, char *argv[]) convention, you can loop through argv, checking each one to see if it's a file via one of the previously-mentioned system calls.
Every string that can be passed on a command line is a potential pathname, since the only restriction in both cases is that there can't be any NULs.
A program with a command line syntax in which a specific argument might or might not be used as a pathname (depending on some vague definition of "filename-ish strings" or even a file existence test) is a bad design. Each argument should have a meaning defined by its order in the argument list, or by being associated with an option like -m msg or -o outputfile.
A well-behaved unix program will let the user create a file called Hello world! if he wants.
not regarding how meaningful the program might or might not be - you can compare the single characters of your char *argv[] by looping through them via argv[i][j]. If every string includes a ".txt" you do not have a string, which is not a filename in your context

Resources