I am reading the book Windows System Programming. In the second chapter, there is a program Cat.c , It implements the cat command of linux. The code is http://pastebin.com/wwQFp599
On the 20th line, a function is called
iFirstFile = Options (argc, argv, _T("s"), &dashS, NULL);
Code for Option is http://pastebin.com/QegxxFpn
Now, the parameters for option is
(int argc, LPCTSTR argv [], LPCTSTR OptStr, ...)
1) What is this "..."? Do it mean we can supply it unlimited number of arguments of type LPCTSTR ?
2)If I execute the program as cat -s a.txt
a) What will be the argc and why?
b) What will be the argv and why?
c) What is _T("s")? Why _T is used here?
d) Why &dashS is used? It is address of a boolean most probably. But I can't understand the logic behind use of this.
e) Why they have passed NULL as last parameter?
I have Basic knowledge of C programming and these things are really confusing. So kindly explain.
You have two different kinds of "variable" lists of arguments here.
First, you have the arguments passed to the program on the command line, clearly a person could invoke the program from the command line with many arguments
cat file1 file2 file3
and so on. The main() of C programs have since the early days of C given access to the command line arguments in the variables argc and argv, argc is the count of how many arguments (3 + the name of the pogram itself in my example above) and argv is the array of the arguments (actually an array of pointers to strings) So in this case we can access argv[0], argv[1], arv[2] and argv[3], knowing to stop there because argc tells us there are four arguments.
So in your example argc will be 3, argv[0] will point to "cat", argv[1] to "-s" and argv[2] to "a.txt".
Next the function you are looking at itself takes an indefinate number of arguments as indicated by the elipses - the ...
You need to read about variable arguments. This is a language feature that was not in the earliest C language, and is considered to be a little bit advanced, hence some of your books either may not cover it, or leave until late in the book. The key point here though is that we interpretting the variable list we need to know when we have reached the end of the variable list, we don't have an "argc" equivalent. So we put a "this is the last one, stop here" value in the function call, that's the NULL you ask about.
1) "..." is a variable argument list as username Cornstalks pointed out. It allows functions like printf() to have a variable number of arguments but their type and number of arguments have to be specified in one of the arguments (like the formatting string for printf()). See *va_list.h* or stdarg.h.
2) a) argc is the number of arguments specified at the command line.
b) argv is the argument array, it's an array of strings.
c) The _T() is a macro, I know it as TEXT(). Basically it allows programmers to use either ASCII strings or Unicode strings at build time without having to modify the entire code. If the UNICODE macro is defined the string specified as argument to the _T() macro becomes L"string", else it becomes "string". That's why some functions have an A or a W as a last letter. For example, OutputDebugString defaults to OutputDebugStringW if UNICODE is defined and OutputDebugStringA if UNICODE is not defined. The functions that have A as a last letter in their name only accept ASCII strings while W only accepts Unicode strings. There's also a type defined for this purpose, TCHAR defaults either to CHAR or WCHAR, and there's also another entry point, i.e. _tmain().
d) &variable means the address of a variable. It is used to pass along to a function the location in the memory of the variable contents so that if the function modifies the value of the variable, the variable is modified everywhere else where it is used.
e) You'll have to look at the function prototype.
It seems to me that you have been misled to believe that starting Windows Programming is the way to go if you want to learn to program. The C and C++ programming languages are OS independent by default and you should learn the independent part first. I recommend "C Programming : A modern approach".
Related
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
I'm trying to input only one filename from command line. Then I want to use an If statement to compare the filename to 4 different names I'm expecting to see. If I don't get one of the 4 expected file names then I need to print it back to the user with what was inputted and then exit the program safely.
int main(int argc, char *argv[])
{
....
}
I've been trying a lot of different methods of getting this done, but I just can't figure it out. I was thinking maybe the way I take the input argument is wrong. Any help would be greatly appreciated.
-edit
I just want to be clear I don't want you to be a leech and solve the question I have for me. Just at least point me in the correct direction. I can't figure how to make a for loop work with the filename.
for(argv == "UnexpectedFile.csv"){
printf("this is an unexpected file: %c", argv[1]);
}
You could use strcmp() from string.h to compare strings like
strcmp(argv[1], "unexpectedfile.csv");
It returns 0 when the strings are equal.
If you have the 4 file names in as an array of strings, say expectedFile, do
for(i=0; i<4 && strcmp(argv[1], expectedFile[i])!=0; ++i);
If the value of i is the total number of file names (ie, 4) after this loop, argv[1] is an unexpected file.
Otherwise, value of i would be the index of the file name string in the expectedFile array.
The command line arguments are stored in the 2-dimensional char array argv.
argv[0] would be the name of the executed file. The arguments you give start only from argv[1] onwards.
argc will have the total number of command line arguments including the file name stored in argc. So if there are 'no' arguments, argc would be 1.
In your case the file name is the only argument, so argc would be 2.
You must check if argc is at least 2 before you access argv[1] to prevent the program from accessing argv[1] when it isn't there.
(You do not ask for complete code solution (and do not provide enough of your code for that). So here are the pointers in the right direction you want.)
The comparison you do with a simple pointer == pointer does not really compare the content of the strings. That is what e.g. strcmp () is for, as proposed by #user3629249.
And in order to print out what was given as commandline argument, you should use "%s\n".
And in order to set up a for loop, you will have to do the syntax right: for(init assignment; condition; step operation).
(If you need more help, you will have to provide more details on what behaviour you get and what you do not like about it. Currently your code looks more like compiler errors, which you did not quote, than a problem with the behaviour goal...)
I'm just started with a course for learning C, and am bumping in a problem with command line arguments. The assignment is this (there is more, but this is the part about the command line argument at the start):
- Your program must accept a single command-line argument, a non-negative integer.
- If your program is executed without any command-line arguments or with more than one command-line argument, your program should print an error message of your choice and return 1.
- You can assume that, if a user does provide a command-line argument, it will be a non-negative integer (e.g., 1). No need to check that it’s indeed numeric.
So I came up with this code:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(int key, string plain[]) {
if (key < 0 || plain[key] > 1)
{
printf("error\n");
return 1;
}
else
etc...code continues.
Now I've tried several things, but I'm running into a wall.The compiler doesn't want to accept the if-condition I came up with, saying there is an error with comparison between pointer and integer which refers to the bold condition on the list of the assignment. So I understood that the argv part of the command line argument is the array of strings that the user put in. So my thought was to tell the compiler that when the user gives more than one string it should give an error message, so I wrote "plain[key] > 1)". Or is my understanding of command line arguments completely off here? Thanks.
plain[key] access the key element of plain array of string pointers (argv).
The size of that array is expressed by key (argc).
So what you want is
if (key > 1)
{
//..
}
Moreover plain last element is key-1, 'cause is 0 based index.
You misunderstood the purpose of the arguments to main. The first int argument (usually named argc) is the number of items in the array argument.
And the array argument (usually called argv) contains all the arguments to your program (including the executable name) as text.
So if your executable is called foo, and you invoked it as foo 1 a bar, the arguments to main will be as follows:
int argc == 4
char **argv => {"foo", "1", "a", "bar"}
So if your program must accept a single argument, it must hold that argc == 2 and argv[1] is the argument, that you must convert to a number from a string.
int main(int argc,char* argv[]);
If there's a '\0' character in A, will it be split into 2 arguments ?
./programe "A"
I can't reproduce it easily as I can't put an '\0' into A,but there might be someone who can.
Parameters are passed into programs as C strings; in particular, the execve() syscall (lowest level visible to programs and generally ether very close to or identical to the kernel API) uses C strings, so it is not possible to pass \0 within a parameter. Note that, while the usual way the parameter vector is passed into the process's address space by the kernel is contiguous, so that an embedded \0 would indeed split a parameter, the low level exec() interface uses a list of (char *)s, so an embedded \0 would simply terminate the parameter early.
This question already has answers here:
Pass arguments into C program from command line
(6 answers)
Closed 6 years ago.
I don't know what to do! I have a great understanding of C basics. Structures, file IO, strings, etc. Everything but CLA. For some reason I cant grasp the concept. Any suggestions, help, or advice. PS I am a linux user
The signature of main is:
int main(int argc, char **argv);
argc refers to the number of command line arguments passed in, which includes the actual name of the program, as invoked by the user. argv contains the actual arguments, starting with index 1. Index 0 is the program name.
So, if you ran your program like this:
./program hello world
Then:
argc would be 3.
argv[0] would be "./program".
argv[1] would be "hello".
argv[2] would be "world".
Imagine it this way
*main() is also a function which is called by something else (like another FunctioN)
*the arguments to it is decided by the FunctioN
*the second argument is an array of strings
*the first argument is a number representing the number of strings
*do something with the strings
Maybe a example program woluld help.
int main(int argc,char *argv[])
{
printf("you entered in reverse order:\n");
while(argc--)
{
printf("%s\n",argv[argc]);
}
return 0;
}
it just prints everything you enter as args in reverse order but YOU should make new programs that do something more useful.
compile it (as say hello) run it from the terminal with the arguments like
./hello am i here
then try to modify it so that it tries to check if two strings are reverses of each other or not then you will need to check if argc parameter is exactly three if anything else print an error
if(argc!=3)/*3 because even the executables name string is on argc*/
{
printf("unexpected number of arguments\n");
return -1;
}
then check if argv[2] is the reverse of argv[1]
and print the result
./hello asdf fdsa
should output
they are exact reverses of each other
the best example is a file copy program try it it's like cp
cp file1 file2
cp is the first argument (argv[0] not argv[1]) and mostly you should ignore the first argument unless you need to reference or something
if you made the cp program you understood the main args really...
For parsing command line arguments on posix systems, the standard is to use the getopt() family of library routines to handle command line arguments.
A good reference is the GNU getopt manual
Siamore, I keep seeing everyone using the command line to compile programs. I use x11 terminal from ide via code::blocks, a gnu gcc compiler on my linux box. I have never compiled a program from command line. So Siamore, if I want the programs name to be cp, do I initialize argv[0]="cp"; Cp being a string literal. And anything going to stdout goes on the command line??? The example you gave me Siamore I understood! Even though the string you entered was a few words long, it was still only one arg. Because it was encased in double quotations. So arg[0], the prog name, is actually your string literal with a new line character?? So I understand why you use if(argc!=3) print error. Because the prog name = argv[0] and there are 2 more args after that, and anymore an error has occured. What other reason would I use that? I really think that my lack of understanding about how to compile from the command line or terminal is my reason for lack understanding in this area!! Siamore, you have helped me understand cla's much better! Still don't fully understand but I am not oblivious to the concept. I'm gonna learn to compile from the terminal then re-read what you wrote. I bet, then I will fully understand! With a little more help from you lol
<>
Code that I have not written myself, but from my book.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("The following arguments were passed to main(): ");
for(i=1; i<argc; i++) printf("%s ", argv[i]);
printf("\n");
return 0;
}
This is the output:
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hey man
The follow arguments were passed to main(): hey man
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hi how are you doing?
The follow arguments were passed to main(): hi how are you doing?
So argv is a table of string literals, and argc is the number of them. Now argv[0] is
the name of the program. So if I type ./CLA to run the program ./CLA is argv[0]. The above
program sets the command line to take an infinite amount of arguments. I can set them to
only take 3 or 4 if I wanted. Like one or your examples showed, Siamore... if(argc!=3) printf("Some error goes here");
Thank you Siamore, couldn't have done it without you! thanks to the rest of the post for their time and effort also!
PS in case there is a problem like this in the future...you never know lol the problem was because I was using the IDE
AKA Code::Blocks. If I were to run that program above it would print the path/directory of the program. Example: ~/Documents/C/CLA.c it has to be ran from the terminal and compiled using the command line. gcc -o CLA main.c and you must be in the directory of the file.
Main is just like any other function and argc and argv are just like any other function arguments, the difference is that main is called from C Runtime and it passes the argument to main, But C Runtime is defined in c library and you cannot modify it, So if we do execute program on shell or through some IDE, we need a mechanism to pass the argument to main function so that your main function can behave differently on the runtime depending on your parameters. The parameters are argc , which gives the number of arguments and argv which is pointer to array of pointers, which holds the value as strings, this way you can pass any number of arguments without restricting it, it's the other way of implementing var args.
Had made just a small change to #anthony code so we can get nicely formatted output with argument numbers and values. Somehow easier to read on output when you have multiple arguments:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("The following arguments were passed to main():\n");
printf("argnum \t value \n");
for (int i = 0; i<argc; i++) printf("%d \t %s \n", i, argv[i]);
printf("\n");
return 0;
}
And output is similar to:
The following arguments were passed to main():
0 D:\Projects\test\vcpp\bcppcomp1\Debug\bcppcomp.exe
1 -P
2 TestHostAttoshiba
3 _http._tcp
4 local
5 80
6 MyNewArgument
7 200.124.211.235
8 type=NewHost
9 test=yes
10 result=output