Search

7.13 — Command line arguments

The need for command line arguments

As you learned lesson 0.4 -- introduction to development, when you compile and link your program, the compiler produces an executable file. When a program is run, execution starts at the top of the function called main(). Up to this point, we’ve declared main like this:

Notice that this version of main() takes no parameters. However, many programs need some kind of input to work with. For example, let’s say you were writing a program called Thumbnail that read in an image file, and then produced a thumbnail (a smaller version of the image). How would Thumbnail know which image to read and process? The user has to have some way of telling the program which file to open. To do this, you might take this approach:

However, there is a potential problem with this approach. Every time the program is run, the program will wait for the user to enter input. This may not be a problem if you’re manually running this program once from the command line. But it is problematic in other cases, such as when you want to run this program on many files, or have this program run by another program.

Let’s look into these cases further.

Consider the case where you want to create thumbnails for all the image files in a given directory. How would you do that? You could run this program as many times as there are images in the directory, typing out each filename by hand. However, if there were hundreds of images, this could take all day! A good solution here would be to write a program that loops through each filename in the directory, calling Thumbnail once for each file.

Now consider the case where you’re running a website, and you want to have your website create a Thumbnail every time a user uploads an image to your website. This program isn’t set up to accept input from the web, so how would the uploader enter a filename in this case? A good solution here would be to have your web server call Thumbnail automatically after upload.

In both of these cases, we really need a way for an external program to pass in the filename as input to our Thumbnail program when Thumbnail is launched, rather than having Thumbnail wait for the user to enter the filename after it has started.

Command line arguments are optional string arguments that are passed by the operating system to the program when it is launched. The program can then use them as input (or ignore them). Much like function parameters provide a way for a function to provide inputs to another function, command line arguments provide a way for people or programs to provide inputs to a program.

Passing command line arguments

Executable programs can be run on the command line by invoking them by name. For example, to run the executable file “WordCount” that is located in the root directory of the C: drive on a Windows machine, you could type:

C:\>WordCount

In order to pass command line arguments to WordCount, we simply list the command line arguments after the executable name:

C:\>WordCount Myfile.txt

Now when WordCount is executed, Myfile.txt will be provided as a command line argument. A program can have multiple command line arguments, separated by spaces:

C:\>WordCount Myfile.txt Myotherfile.txt

This also works for other command line operating systems, such as Linux (although your prompt and directory structure will undoubtedly vary).

If you are running your program from an IDE, the IDE should provide a way to enter command line arguments.

In Microsoft Visual Studio, right click on your project in the solution explorer, then choose properties. Open the “Configuration Properties” tree element, and choose “Debugging”. In the right pane, there is a line called “Command Arguments”. You can enter your command line arguments there for testing, and they will be automatically passed to your program when you run it.

In Code::Blocks, choose “Project -> Set program’s arguments”.

Using command line arguments

Now that you know how to provide command line arguments to a program, the next step is to access them from within our C++ program. To do that, we use a different form of main() than we’ve seen before. This new form of main() takes two arguments (named argc and argv by convention) as follows:

You will sometimes also see it written as:

Even though these are treated identically, we prefer the first representation because it’s intuitively easier to understand.

argc is an integer parameter containing a count of the number of arguments passed to the program (think: argc = argument count). argc will always be at least 1, because the first argument is always the name of the program itself. Each command line argument the user provides will cause argc to increase by 1.

argv is where the actual argument values are stored (think: argv = argument values, though the proper name is “argument vectors”). Although the declaration of argv looks intimidating, argv is really just an array of C-style strings. The length of this array is argc.

Let’s write a short program named “MyArgs” to print the value of all the command line parameters:

Now, when we invoke this program (MyArgs) with the command line arguments “Myfile.txt” and “100”, the output will be as follows:

There are 3 arguments:
0 C:\MyArgs
1 Myfile.txt
2 100

Argument 0 is the path and name of the current program being run. Argument 1 and 2 in this case are the two command line parameters we passed in.

Dealing with numeric arguments

Command line arguments are always passed as strings, even if the value provided is numeric in nature. To use a command line argument as a number, you must convert it from a string to a number. Unfortunately, C++ makes this a little more difficult than it should be.

The C++ way to do this follows:

When run with input “567”, this program prints:

Got integer: 567

std::stringstream works much like std::cin. In this case, we’re initializing it with the value of argv[1], so that we can use operator>> to extract the value to an integer variable (the same as we would with std::cin).

We’ll talk more about std::stringstream in a future chapter.

The OS parses command line arguments first

When you type something at the command line (or run your program from the IDE), it is the operating system’s responsibility to translate and route that request as appropriate. This not only involves running the executable, it also involves parsing any arguments to determine how they should be handled and passed to the application.

Generally, operating systems have special rules about how special characters like double quotes and backslashes are handled.

For example:

MyArgs Hello world!

prints:

There are 3 arguments:
0 C:\MyArgs
1 Hello
2 world!

Typically, strings passed in double quotes are considered to be part of the same string:

MyArgs "Hello world!"

prints:

There are 2 arguments:
0 C:\MyArgs
1 Hello world!

If you want to include a literal double quote, you have to backslash the double quote:

MyArgs \"Hello world!\"

prints:

There are 3 arguments:
0 C:\MyArgs
1 "Hello
2 world!"

Conclusion

Command line arguments provide a great way for users or other programs to pass input data into a program at startup. Consider making any input data that a program requires at startup to operate a command line parameter. If the command line isn’t passed in, you can always detect that and ask the user for input. That way, your program can operate either way.

7.14 -- Ellipsis (and why to avoid them)
Index
7.12 -- Handling errors (assert, cerr, exit, and exceptions)

66 comments to 7.13 — Command line arguments

  • kingyo

    Really nice job, helped me a lot…
    Thank you!

  • Doug

    You have a GREAT site! I am using Visual Studio 2008 and it has been working great up until now. If I use the built in “_tmain” declaration, I get 4 addresses printed. But when I use your declaration, it works perfect. What is the difference in the declarations?

    • I think this has something to do with the way your program is doing character encoding. TCHAR is a macro that can resolve to either char or wchar_t depending on whether or not you are using wide characters. If you are using wide characters (wchar_t), then trying to use cout to print them will print addresses instead of values because it doesn’t know how to handle them. My guess is that _tmain() is converting your command line parameters to wide character strings, but main() isn’t.

    • baldo

      In Visual Studio, _tmain is a macro that expands to wmain according and _TCHAR expands to wchar_t.
      The problem is that you are using ‘cout’ (which works with single wide strings) with a double wide string.

  • Astro

    Should "char *pFilename = argv[1];" in the example above be "char *pFilename = &argv[1];" ????

    Am I confusing myself here?

    • argv is of type char *argv[], which is essentially a pointer to a pointer.

      When we use the array index operator [] on a pointer/array, there is an implicit dereference that happens. If argv is of type char *argv[], then argv[1] is of type char*, which is what we’ve declared pFilename as.

      • Ben

        “char *argv” is a pointer to a char.
        But what is “char *argv[]”? Pointer to a pointer? Or do you mean pointer to C-style string?

        I assumed that in the case of a “Command line arguments”, the size of “*argv[]” was dynamically defined by the argument “argc”.

        However this program compiles but crashes when executed:

        I feel I’m getting confused.

        • dogthinker

          Ben, your program is crashing when you are trying to use a non-constant variable to define the size of an array, which is not allowed.

          I think the size of the arrays here are being implicitly defined by the input (the command line parameters.) The argc parameter is simply passing us the size of the array of C-style strings - not defining them.

          If you want code to help you imagine what is happening, running a program with the following input:

          Would give us a value for *argv[] analgous to if you used the following code:

        • char *argv[] is indeed a pointer to a pointer. However, thinking about it like that will only lead to confusion. Instead, think of it as an array of strings.

          Now, consider what an “array of strings” really is. A string is an array of characters, so an “array of strings” is really an “array of (array of characters)”. An array is really just a pointer, so an “array of (array of characters)” is really just a “pointer to a pointer to characters”. And that’s exactly how argv is defined.

          Now, the thing to note here is that argv comes prepopulated -- that is, each string in argv[] is already pointing to its appropriate command line argument. The size of the argv array is argc, as you state.

          Now, to your program. You declare an array of 4 strings called pchTest, which is fine. However, like all C++ basic data types, pchTest is not initialized by default. So while pchTest points to an array of 4 strings, each of the strings is pointing to garbage memory.

          This is why your program crashes when you try and write a value into them -- you’re dereferencing a garbage address.

          Probably the best way to fix this is to dynamically allocate the strings when you need them:

          However, that said, I think you’re best off avoiding trying to create your own arrays of strings using this method altogether. There are much cleaner, safer, and understandable ways of doing the same thing using classes, which will be covered shortly.

  • isn’t it easier to put inputs in a file and then read then from the file instead of using command line argumens?

    • It depends on what your program is doing and how it’s run. If your program is a standalone program that does lots of text processing, then sure, a file input would be perfect for that.

      However, consider the case where you’re writing a program you expect to be called by other programs. Are you going to make them all write files before they call you? What if two programs call you at the same time?

      Generally, my feeling is that you should use command line parameters if you can, and file inputs only when necessary.

  • Mohamad

    I am confused as to how to pass command line arguments to main using CODE::BLOCKS any instructions?

    • Mohamad

      Nevermind I figured it out… all I had to do was go to the command line in Vista Start mean (which looks like a search instead of the run box you get in Windows XP) and type in the path to the file and the argument. Thanks for all the good lessons.

      • Quinn

        You can set arguments automatically in Code::Blocks using the Project -> Set programs’ arguments menu option. Then when you build/run or just run it the program will always run with your selected arguments.

        • Len

          With version 13.12 of CodeBlocks you cannot set command line arguments unless the cpp file is part of a project. It took me several minutes to figure this out.

          Often with CodeBlocks, if the option does not work or is greyed out, try creating a project (new project/console application), add your cpp file to the project.  This usually "fixes" the problem. imo it would be better if Codeblocks presented an error that said i.e. "this option can only be used with projects", but I guess that is "obvious"…

  • Kurt

    In the last example isn’t there a off by 1 error?

    When there is a command line argument, argc = 1 then (argc <= 1) is the same as 1 <=1 what translates to true so the program exits.
    It should be like this no?

    • Quinn

      Actually, argc always evaluates to at least one, even without any other command-line arguments. If it were just (argc < 1) then you’d end up with that if statement never evaluating to true, and the program most likely crashing due to trying to load up something that wasn’t there if the user tried not giving any arguments.

  • AUASP

    Double quotes(“) are not taken as command line arguments.
    Only way to inclde double quotes is preceeding quotes with ‘\’.Eg. \”

  • Claudio Teles

    Hi i’m using Microsoft Visual Studio 2013 and I don’t see any options to use "Command Arguments" under “Configuration Properties” only "debug" and "release".

    • alan

      I also use VS 2013 so had a look for you, what you need to do is rightclick on the Project Name in Solution Explorer, select Properties at the bottom of the window, then select Configuration Properties, then Debugging. You get a display of various stuff including "Command Arguments", which you can enter.

      I actually find it easier to open a Command Prompt, cd to the relevant directory, and run the command with any command line arguments from there. The Up and Down cursors allow you to recall earlier commands so its easy to try several variations.

      Alan

  • -KHUN-

    Hi! I’m using Code::Blocks, I need to know how to do the C:\>WordCount part because the above example is using Visual Studio.

  • Ben

    Hello,
    I have a filename.txt and each line within this file consist of a Unix system command. I am reading the file, one line at a time, and trying to pass that command which is in the file, as a command to Unix system (you can say in Automation way) using VS2013.
    My problem is, when I parse the line that is stored under string testline, the system think as if the testline is a command and not the content of the testline.

    Any idea as how I can solve this issue?

    Thanks in advance,

  • Shivam Tripathi

    Hii Alex…once again need ur help…

    Here OS is the caller and main() is called by passing the .txt file as an argument from CMD…Now m curious about the ‘char* argv[]’…I mean it’s a simple typical array of strings and it is storing such a large file as it’s argument…must it have a standard size or Can it accept any big text file as it’s argument?? Is it different from normal strings that we declare in our program…I mean, Is it dynamic??..Does it get stored on "stack" or "heap"???

    And my next confusion is regarding ur this statement:

    "Now, when WordCount is run, it will not require any user interaction. This means we can have a batch file, script, or even another program run WordCount many times in a row (with different command line arguments) in an automated manner."

    Plzz clear my BOTH confusions…Your prompt reply is solicited..:)

    • Alex

      How argv is implemented is compiler specific.

      What’s part of the statement you quoted are you finding confusing?

      • Shivam Tripathi

        M confused about this batch file stuffs…how can it run WordCount???
        And here one more confusion :-

        I got that whatever i am typing in CMD as argument (a file name)…the program is considering the "name" of "file" as the string…it’s not making the program to read the content inside that file…

        for eg: i defined a file "Shivam.txt" and passed in CMD…but instead of taking the content inside of that text file, it’s taking "Shivam.txt" as the string and returning that this file has 11 words..(i hv designed a program that returns number of words in a string)…

        I think it’s a concept of stream file I/O ( fstream & ifstream etc.) …Sorry but wondering how u missed here to mention that in this chapter..:-P

        • Alex

          Batch files are simple interpreted programs run by the OS (vs C++ programs, which are compiled). They can do things like run other programs, simple if statements, etc… How batch files work is OS-dependent, and outside the scope of this tutorial.

          I think you may be talking about the difference between calling a program like this:

          myprogram shivam.txt

          and

          myprogram < shivam.txt The former passes "shivam.txt" as a string to argv. You can then use C++ file IO to open and read the file content (covered in chapter 13.6). The latter passes the contents of shivam.txt to the program via the input stream. You can read the file content via cin.

          • Shivam Tripathi

            Thnk you so much Alex for your prompt replies…M very happy to understand this concept and seems that I also hv got a pre-dose of C++ I/O too…:-D..

            One last thing..(sorry to disturb u again ‘n’ again)…:-)

            Although argv[] is totally compiler dependent yet there must be some explanation of the "storage" of this array…i mean lyk my previous comments say.."Is this array dynamic??"…"where this array get stored???"..Coz main() is a function which is designated to be the start of the program so it also gets a position in memory (stack-frame)…but in this case when u pass CMD arguments "Where this argv[] get stored and where this main() gets its position too..????

            • Alex

              Because it’s a function parameter, argv is on the stack. But the memory it points to could be on the stack or the heap, depending on what the compiler wants to do.

  • Pablo

    So I have to admit that I have struggled with this one! I played around with a little program trying to pin down what I did and did not understand. Now that I think I’ve more or less got it, I wanted to share it, in case someone finds it helpful.

    Most of my confusion came from char *argv[], which I thought was an array of char values, and it is not. It is an array of char pointers (as Alex said above but I apparently failed to grasp). The fist thing my code shows is exactly this.

    But, to make things worse, chars are a bit evil when used in std::cout (as seen earlier in this tutorial) and a char pointer will print its value and not an address.

    Also, if you try to convert the command line argument (7 in my case), this will produce 55, which is the value for the ASCII ‘7’.

    Now I have two humble doubts for Alex:

    First: In a previous comment you mention how command line arguments are good so that you don’t need to read from a file. But how can you input a different type this way? A float, for instance. I tried changing the type of *argv[] and it compiled, but did not quite work (and this would not allow for input of several types).

    And lastly: at the end of my code you can see what I believe is an integer pointer to a pointer. Maybe? Is that correct? Would something like that ever be useful?

    I would also be most grateful is you could point out any mistakes on my interpretation of the code… I really did my best here! :S

    • Alex

      There are various ways to convert strings into to integers or floats. I always forget how, so I just ask Google when I need to do that and copy the code.

      Yes, you’ve declared a pointer to a pointer to an integer. Pointers to pointers are most often used for things such as dynamically allocating two-dimensional arrays, or a one-dimensional array of pointers, or passing a pointer by address. I’m intending to write an article on pointers to pointers soon.

      • Pablo

        It was a bit of a headache with chars printing funny, * meaning different things in different places and so on… but I am coming to terms with the whole thing now. I hope.

        I will be eagerly waiting for new articles! In the meantime, still a long way to go.

        As always, thanks a lot! You really have a great thing going on here! 😀

  • May

    Doesn’t argv stand for argument vectors, not values?

    • Alex

      Yes, the proper name is argument vectors. I’ve added a note to the article about that. However, it’s more common to call it as “argument values”.

  • Matt

    Found a typo: "In this case, we’re initializing it with the value of argv[0] …"

    "argv[0]" should be "argv[1]".

  • Mekacher Anis

    Hi Alex , amazing posts , and I just wanna ask , I study at high-school , and I study in night also , and I take programming as hobby and sometimes I forget couple of things that I’ve studied here , ist that okay ? and is there any way to ensure that I don’t forget them

    • Alex

      I forget things all the time. It’s less important to remember the specifics of how to do something (e.g. the syntax). It’s more important to remember the high-level concepts, so as you tackle problems, you can say, “Oh, I should use this concept to solve this problem”, and then you can look up the details of how to actually do that on a website somewhere. 🙂

  • Osman Zakir

    Mine keeps thinking that there are no arguments even when I go and enter them (I’m using Visual Studio Community 2015).  What do I do?

    • Alex

      Try running your program from the command line and see if the arguments are working. If so, then you’re doing something wrong in Visual Studio. If not, then you’re doing something wrong in your code.

  • nick

    Hi Alex.
    for Convert :
    this method is wrong ؟(atoi or atof)

  • Soul

    Hi, I tried inputting your code:

    I wanted to test it out, but got ‘exit’ was not declared in this scope.

  • Rob G.

    Alex I am new to command-line arguments, although I got the code to work:

    There are 3 arguments:
    0 C:\Users\Technologist\workspace\7.13_command_line_arguments\Debug\7.13_command_line_arguments.exe
    1 world.txt
    2 100

    world.txt does not exist; why is there no error with this?

    • Alex

      Because “world.txt” is just a string. The string “world.txt” doesn’t care whether the file world.txt exists or not. That’s for the code inside the function to determine.

  • Vlad

    I’m sorry to bombard you with questions these days, but in trying your example from "Dealing with numeric arguments", when run with no arguments, it exits like this:

    Is this supposed to happen? Should this error have been handled, somehow, as explained in the previous lesson?

    • Alex

      No, that’s not supposed to happen. It sounds like on your environment, argv[0] is coming out as a null string. I’ve updated the example to catch this.

  • Chris

    Alex,

    i little bit doesn’t understand at conclusion section, "If the command line isn’t passed in, you can always detect that and ask the user for input.". it is mean ask the user for input to argv[]? like ask the user for input to variable with std::cin? how to do that(detect and ask)?

    Thank you.

    • Alex

      Typically, in this case, you’d do three things:
      * Detect that the user has entered no command line input
      * Have the program output instructions on how to properly use it (e.g. what command line parameters the user should be passing in)
      * Exit

      That way, the user can then run the program again with the appropriate parameters.

  • Kattencrack Kledge

    I don’t understand how the strings below inform me about the usage of the executable. Can you explain them to me?

    • Alex

      “if (argc <= 1)" only executes if there is zero or one arguments to the program, which means you didn't pass in a number as a command line argument. So in that case, the program prints a string telling you how the program was meant to be run (from the command line, since these are console applications). If you're running these from an IDE, then you need to instead set your command line arguments through your IDE.

      • Kattencrack Kledge

        Sorry for incorrectly asking my question, but I meant "I don’t understand how the two strings below inform me about the usage of the program", like I don’t understand what <number> is suppose to mean.

        And:

  • DianYi Liu

    Alex, I read your tutorial from the start. It’s detailed and easy to understand.
    I have a problem here.

    The following codes work very well in the environment of IDE(Visual Studio 2015). But, if I build an executable, whether a debug version or a release version, the executable cannot identify those command line arguments I have input through:Configuration Properties->Debugging->Command Arguments. The executable can only recognize only 1 argument, which is the executable itself.

    But if I run those codes inside the IDE, it can recognize all the command line arguments.
    I don’t understand this. Do I miss something?
    Thanks!

    • Alex

      Yes, you’re missing something. The applications we’re building here are console applications, which means you can run them from a OS console. When you run them from the OS console, you can pass parameters to them on the same line you call the executable.

      For example, if the above program was named foo.exe, you could do this:

      > foo print 5

      (assume > is the console prompt, not part of the command you’ve typed)

      and the program would print:
      0 foo
      1 print
      2 5

      In Windows, you could also create a shortcut to the executable and add the command line parameters as part of the command being executed there.

  • Kattencrack Kledge

    I’m having a really weird problem.
    I want to compare an element of the argv[] array with a string. This is the section of my code that does this:

    However, even when argv[1] is "/r", the if condition returns false. Why?????

    • Kattencrack Kledge

      Just realised that typing argv[1] in my current case just returns the memory address.

      I fixed my problem by typing this:

      Or even though of it like this:

      But I'm sure there is another way that isn't redundant as this. Can you tell me the proper way to do it?

  • Will

    Hi Alex,
    I wonder why

    is different from

    My compiler won’t compile the second one.
    I interpreted the first one as "an array of (pointer to character)", the second one as "an pointer to (an array of characters)". Since array is essentially pointer, shouldn’t them be equivalent?

    • Alex

      Visual C++ accepts both char *(argv)[] and char (*argv)[], though it sometimes does things it shouldn’t.

      I’m not sure I see why your compiler would reject the latter. Does it compile if you put the * outside of the parenthesis?

      • Will

        It does compile *(argv)[].
        I guess it’s just the compiler’s fault. It even allows me to compile int arr[anIntVariable]. By the way, I’m using Xcode.

  • Tom

    Hi Alex,

    I think I may be missing something. Why is the second ‘if’ statement necessary in the below code?

    If argc <= 1, then wouldn’t argv always be equal to 0?

    Thanks!

    • Ben

      The second if statement is not checking to see whether argv is equal to 0. It is checking to see if there is something at location argv[0] or not.

    • Alex

      Normally argv[0] contains the executable’s name. However, for some operating systems, in certain cases, this doesn’t happen, and instead it comes through as a blank string. That blank string counts as a parameter, but we don’t want to print it. So the second if statement is testing for the case where argv[0] is blank, and conditionalizing the “usage” statement based on that.

      I’ve updated the code in the lesson with a comment indicating such, since this isn’t obvious.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter