Chapter 6
IN THIS CHAPTER
Working with functions
Writing your own great functions
Fun with strings
Manipulating main()
People generally agree that most projects throughout life are easier when you divide them into smaller, more manageable tasks. That’s also the case with computer programming — if you break your code into smaller pieces, it becomes more manageable.
C++ provides many ways to divide code into smaller portions. One way is through the use of what are called functions. A function is a set of lines of code that performs a particular job. In this chapter, you discover what functions are and how you can use them to make your programming job easier.
If you have a big job to do that doesn’t involve a computer, you can divide your work in many ways. Over the years of studying process management, people have pretty much narrowed the division of a job to two ways: using nouns and using verbs.
Yes, that’s right. Back to good old English class, where everyone learned about nouns and verbs. The idea is this: Suppose that you’re going to go out back and build a flying saucer. You can approach the designing of the flying saucer in two ways.
First, you could just draw up a plan of attack, listing all the steps to build the flying saucer from start to finish. That would, of course, be a lot of steps. But to simplify it, you could instead list all the major tasks without getting into the details. It might go something like this:
That’s it. Only two steps. But when you hire a couple dozen people to do the grunt work for you while you focus on your day trading, would that be enough for them to go on? No, probably not. Instead, you could divide these two tasks into smaller tasks. For example, Step 2 might look like this:
2a. Build the antigravity lifter.
2b. Build the thruster.
2c. Connect the lifter to the thruster to form the final engine.
2d. Attach the engine to the outer shell.
That’s a little better; it has more detail. But it still needs more. How do you do the “Build the antigravity lifter” part? That’s easy, but it requires more detail, as in the following steps:
2aa. Unearth the antigravity particles from the ground.
2ab. Compress them tightly into a superatomizing conductor.
2ac. Surround with coils.
2ad. Connect a 9-volt battery clip to the coils.
And, of course, each of these instructions requires even more detail. Eventually, after you have planned the whole thing, you will have many, many steps, but they will be organized into a hierarchy of sorts, as shown in Figure 6-1. In this drawing, the three dots represent places where other steps go — they were left off so that the diagram could fit on the page.
This type of design is a top-down design. The idea is that you start at the uppermost step of your design (in this case, “Build flying saucer”) and continue to break the steps into more and more detailed steps until you have something manageable. For many years, this was how computer programming was taught.
FIGURE 6-1: Dividing a process into a hierarchy.
Although this process works, people have found a slightly better way. First, before breaking the steps (which are the verbs), you divide the thing you’re building into parts (the nouns). In this case, you kind of do that already, in the first two steps. But instead of calling them steps, you can call them objects. One object is the outer shell, and one object is the engine. This way, two different factories can work on these in sort of a division of labor. Of course, the factories would have to coordinate their activities; otherwise, the two parts may not fit together when they’re ready to go. And before you figure out exactly how to build each of these objects, it would be a good idea to describe each object: what it does, its features, its dimensions, and so on. Then, when you finally have all that done, you can list the exact features and their details. And finally, you can divide the work with each person designing or building a different part.
As you can see, this second approach makes more sense. And that’s the way programmers divide their computer applications. But at the bottom of each method is something in common: The methods are made of several little processes. These processes are called functions. When you write a computer application, after you divide your job into smaller pieces called objects, you eventually start giving these objects behaviors. And to code these behaviors, you do just as you did in the first approach: You break them into manageable parts, again, called functions. In computer programming terms, a function is simply a small set of code that performs a specific task. But it’s more than that: Think of a function as a machine. You can put one or more things into the machine; it processes them, and then it spits out a single answer, if anything at all. One of the most valuable diagrams you can have draws a function in this manner, like a machine, as shown in Figure 6-2.
FIGURE 6-2: You can think of a function as a machine.
This machine (or function) has three main parts:
To make all this clear, try out the FirstFunction
code in Listing 6-1. (Don’t forget the second line, #include<math.h>
, which gives you some math capabilities.)
LISTING 6-1: Seeing a Function in Action
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
cout << fabs(-10.5) << endl;
cout << fabs(10.5) << endl;
return 0;
}
When you run this application, you see the following output:
10.5
10.5
In this code, you use a function or machine called fabs()
(usually pronounced “ef-abs,” for floating-point absolute). This function takes a number as input and returns as output the absolute value of the number.
So the first line inside main()
calls fabs()
for the value –10.5
. The cout
then takes the output of this function (that is, the result) and prints it to the console.
Then the second line does the same thing again, except that it takes the absolute value of the number 10.5
.
And where is the processor for this function? It’s not in your code; it’s in another file, and the following line ensures that your application can use this function:
#include <math.h>
You have seen functions in many places. If you use a calculator and enter a number and press the square root button, the calculator runs a function that calculates the square root.
But functions can be more sophisticated than just working with numbers. Consider this statement carefully: When you are using a word processor and you highlight a word and check the spelling of the word, the application calls a function that handles the spelling check. This function does something like the following:
This is a function to check the spelling of a single word.
Inputs: A single word.
Look up the word
If the word is not found
Find some suggestions.
Open a dialog box through which you (the user)
can change the word by either typing a new word
or picking one of the selections, or just leaving
it the same.
If you made a change,
Return the new spelling.
Otherwise
Return nothing.
Otherwise
Return nothing
Notice how the if
statements are grouped with indentations. The final otherwise
goes with the first if
statement because its indentation matches that of the if
statement.
So that’s a function that performs a spelling check. But consider this: When you do not highlight a word but run the spelling checker, the spelling checker runs for the whole document. That’s another function. Here it is.
This function checks the spelling of the entire document
For each word in the document
Check the spelling of the single word
How does the computer do the step inside the for
loop, “Check the spelling of the single word?” It calls the function described earlier. This process is called code reuse. You have no reason to rewrite the entire function again if you already have it somewhere else. And that’s the beauty of functions.
When you run the code in a function, computer people say that you are calling the function. And just like every good person, a good function has a name. When you call a function, you do so by name.
To call a function, you type its name and then a set of parentheses. Inside the parentheses, you list the items you want to send to the inputs of the function. The term used here is pass, as in “You pass the values to the function.”
For example, if you want to call the fabs()
function, you type the name, fabs
, an open parenthesis, the number you want to pass to it, and then a closed parenthesis, as in the following example:
fabs(-10.5)
But by itself, this line does not do anything with regard to the application as a whole. The fabs()
function returns a value — the absolute value of –10.5
, which comes out to be 10.5
— and you probably want to do something with that value. You could, for example, print it to the console:
cout << fabs(-10.5) << endl;
Or you could store it away in another variable. But there’s a catch. Before you can do that, you need to know the type that the function returns. Just as with a variable, a function return value has a type. In this case, the type is a special type called double
(which stands for double precision floating point). The double
type is a floating-point type that can hold many digits in a single number. To save the result of fabs()
, you need to have a variable of type double
. The Fabs2
example, shown in Listing 6-2, does this.
LISTING 6-2: Seeing Another Way to Use fabs()
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
double mynumber = fabs(-23.87);
cout << mynumber << endl;
return 0;
}
This code declares a double
variable called mynumber
. Then it calls fabs()
, passing it –23.87
and returning the value into mynumber
. Next, it prints the value in mynumber
to the console.
When you run this application, you see the following, which is the absolute value of –23.87
:
23.87
You can also pass the value of a variable into a function. The Fabs3
example in Listing 6-3 creates two variables: One is passed into the function, and the other receives the result of the function.
LISTING 6-3: Seeing Yet Another Way to Use fabs()
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
double start = -253.895;
double finish = fabs(start);
cout << finish << endl;
return 0;
}
This code creates two variables; the first is called start
, and the second is called finish
. It initializes start
with a value of -253.895
. Next, it calls fabs()
, passing it the value of start
. It saves the return value in finish
, and prints the value in finish
. When Fabs3
runs, you see the following appear on the console:
253.895
finish = -fabs(start);
Some functions like to have all sorts of goodies thrown their way, such as multiple parameters. As with functions that take a single value, you put the values inside a single set of parentheses. Because you have multiple values, you separate them with commas. The Pow1
example, shown in Listing 6-4, uses a function called pow()
to calculate the third power of 10. (That is, it calculates 10 times 10 times 10. Yes, POW!). Make sure that you include the math.h
line in the include
section so that you can use the pow()
function.
LISTING 6-4: Seeing Yet One More Function in Action
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
double number = 10.0;
double exponent = 3.0;
cout << pow(number, exponent) << endl;
return 0;
}
When you run the application, you see 10 to the third power, which is 1,000:
1000
You can also pass a mixture of variables and numbers, or just numbers. The following code snippet also calculates the third power of 10 but passes an actual number, 3.0, for the power:
double number = 10.0;
cout << pow(number, 3.0) << endl;
Or you can pass only numbers:
cout << pow(10.0, 3.0) << endl;
And now the fun begins! Calling functions is great, but you get real power (ooh!) when you write your own, specialized functions. Before writing a function, remember the parts: the inputs, the main code or processor, and the single output (or no output). The inputs, however, are called parameters, and the output is called a return value. The following sections fill you in on the details.
The AddOne
example, shown in Listing 6-5, provides both a custom function and code in main()
that calls the custom function. (The function is placed outside main()
— before it, in fact.)
LISTING 6-5: Writing Your Very Own Function
#include <iostream>
using namespace std;
int AddOne(int start)
{
int newnumber = start + 1;
return newnumber;
}
int main()
{
int testnumber = 20;
int result = AddOne(testnumber);
cout << result << endl;
return 0;
}
Using the downloadable source will save you time and ensure that the example runs the first time you try it. However, you might choose to type it manually. Because there’s a good bit of code, you may get some compiler errors at first; look carefully at the lines with the errors and find the difference between your code and what’s here in the book. After you run the example, you see:
21
You can start reviewing this code by seeing how to call AddOne()
. Look at these lines of main()
:
int testnumber = 20;
int result = AddOne(testnumber);
cout << result << endl;
You can probably put together some facts and determine what the function does. First, the example is called AddOne()
, which is a good indication in itself. Second, when you run the application, the number 21
appears on the console, which is one more than the value in testnumber
; it adds one. And that, in fact, is what the function does. It’s amazing what computers can do these days.
Now, look at the AddOne
function. Here are a few high-level observations about it:
main()
. Because of the way the compiler works, it must know about a function before you call it. And thus, you put it before main()
. (You can do this in another way that is discussed in the “Forward references and function prototypes” section, later in this chapter.)main()
. The code consists of these elements:
int newnumber = start + 1;
newnumber
. Then it initializes it to start
plus 1
. But what is start
? That’s one of the inputs.return newnumber;
return
and then indicate what you want to return. From the first line in the AddOne()
function, you can see that newnumber
is one more than the number passed into the function. So this line returns the newnumber
.AddOne()
takes just one parameter called start
, which comes from the first line of the function:
int AddOne(int start)
The entry in parentheses is the parameter. Notice it looks like a variable declaration; it’s the word int
(the type, or integer) followed by a variable name, start
. That’s the parameter — the input — to the function, and you can access this parameter throughout the function using a variable called start
. You can use the input to the function as a variable.
If you had written result = AddOne(25);
in main()
, then, throughout the function, the value of start
would be 25
. Likewise, if you had written
result = AddOne(152);
then, throughout the function, the value of start
would be 152
.
But here’s the outstanding thing about functions (or, at least, one of the loads of outstanding things about functions): You can call the function several times over. In the same main()
, you can have the following lines
cout << AddOne(100) << endl;
cout << AddOne(200) << endl;
cout << AddOne(300) << endl;
which would result in this output:
101
201
301
In the first call to AddOne
, the value of start
would be 100
. During the second call, the value would be 200
, and during the third call, it would be 300
.
Look at the AddOne()
header again:
int AddOne(int start)
The word AddOne
is the name of the function, as you’ve probably figured out already. And that leaves the thing at the beginning — the int
. That’s the type of the return value. The final line in the function before the closing brace is
return newnumber;
The variable newnumber
inside the function is an integer. And the return type is int
. That’s no accident: As programmers have all heard before, friends don’t let friends return something other than the type specified in the function header. The two must match in type. And further, examine this line from inside main()
:
int result = AddOne(testnumber);
The type of result
is also an integer. All three match. Again, no accident. You can copy one thing to another (in this case, the function’s return value to the variable called result
) only if they match in type. And here, they do — they’re both integers.
Notice one more thing about the function header: It has no semicolon after it. This is one of the places you do not put a semicolon. If you do, the compiler gets horribly confused. The Code::Blocks compiler shows an error that says, "error: expected unqualified-id before ’{’ token."
Finally, ponder this line of code for a moment:
testnumber = AddOne(testnumber);
This line takes the value stored inside testnumber
, passes it into AddOne()
, and gets back a new number. It then takes that new number and stores it back into testnumber
. Thus, testnumber
’s value changes based on the results of the function AddOne()
.
Not all functions work precisely the same way. You can create functions that have multiple parameters or no parameters. There is no law that says that a function must absolutely provide a return value. The following sections discuss variations on the basic function theme discussed in the previous section.
You don’t need to write your functions with only one parameter each. You can have several parameters, or you can have none. It may seem a little strange that you would want a function — a machine — that accepts no inputs. But you may run into lots of cases where this may be a good idea. Here are some ideas for functions:
"Monday"
or "Tuesday"
"Arial"
"Elisha"
All functions in this list have something in common: They look up information. Because no parameters are in the code, for the functions to process some information, they have to go out and get it themselves. It’s like sending people out into the woods to find food but not giving them any tools: It’s totally up to them to perform the required tasks, and all you can do is sit back and watch and wait for your yummy surprise.
If a function takes no parameters, you write the function header as you would for one that takes parameters, and you include the parentheses; you just don’t put anything in the parentheses, as the UserName
example in Listing 6-6 shows. So if nothing good is going in, there really can be something good coming back out, at least in the case of a function with no parameters.
LISTING 6-6: Taking No Parameters
#include <iostream>
using namespace std;
string Username()
{
return "Elisha";
}
int main()
{
cout << Username() << endl;
return 0;
}
When you run Listing 6-6, you see the following output:
Elisha
Your function can also take multiple parameters. The ConnectNames
example, shown in Listing 6-7, demonstrates the use of multiple parameters. Notice that the function, ConnectNames()
, takes the two strings as parameters and combines them, along with a space in the middle. Notice also that the function uses the two strings as variables.
LISTING 6-7: Taking Multiple Parameters
#include <iostream>
using namespace std;
string ConnectNames(string first, string last)
{
return first + " " + last;
}
int main()
{
cout << ConnectNames("Richard", "Nixon") << endl;
return 0;
}
In the function header in Listing 6-7, you see the type name string
for each parameter. Each parameter requires its own type entry or the compiler displays an error. Here are some points about this code:
main()
. Instead, you just typed them as string constants (that is, as actual strings surrounded by quotes).return
statement. That saves the extra work of creating a variable. In the function, you could create a return variable of type string
, set it to first + " " + last
, and then return that variable, as in the following code:
string result = first + " " + last;
return result;
But instead, the example shows how to do it all on one line, as in this line:
return first + " " + last;
Although you can save yourself the work of creating an extra variable and just put the whole expression in the return
statement, sometimes that’s a bad thing. If the expression is really long, like the following:
return (mynumber * 100 + somethingelse / 200) *
(yetanother + 400 / mynumber) / (mynumber + evenmore);
it can get just a tad complicated. Breaking it into variables, such as in this example, is best:
double a = mynumber * 100 + somethingelse / 200;
double b = yetanother + 400 / mynumber;
double c = mynumber + evenmore;
return a * b / c;
In the earlier section “Using multiple parameters or no parameters,” you see a list of functions that take no parameters; these functions go and bring back something, whether it’s a number, a string, or some other type of food.
One such example gets the username of the computer you’re logged in to. But what if you are the great computer guru, and you are writing the application that actually logs somebody in? In that case, your application doesn’t ask the computer what the username is — your application tells the computer what the username is, by golly!
In that case, your application would call a function, like SetUsername()
, and pass the new username
. The resulting function could do any of the following for a return value:
username
is not valid or something like thatLook at the case in which a function doesn’t return anything. In C++, the way you state that the function doesn’t return anything is by using the keyword void
as the return type in the function header. The SetUserName
example, shown in Listing 6-8, demonstrates this approach.
LISTING 6-8: Returning Nothing at All
#include <iostream>
using namespace std;
void SetUsername(string newname)
{
cout << "New user is " << newname << endl;
}
int main()
{
SetUsername("Harold");
return 0;
}
When you run the application, you see
New user is Harold
Notice the SetUsername()
function header: It starts with the word void
, which means that it returns nothing at all. It’s like outer space: There’s just a big void with nothing there, and nothing is returned, except for static from the alien airwaves, but we won’t go there. Also notice that, because this function does not return anything, there is no return
statement.
Now, of course, this function really doesn’t do a whole lot other than print the new username to the console, but that’s okay; it shows you how you can write a function that does not return anything.
Do not try to return something in a function that has a return type of void
. Void means that the function returns nothing at all. If you try to put a return
statement in your function, you get a compile error.
Everybody likes to have their own stuff, and functions are no exception. When you create a variable inside the code for a function, that variable will be known only to that particular function. When you create such variables, they are called local variables, and people say that they are local to that particular function. (Well, computer people say that, anyway.)
To see a local variable at work, consider the code in the PrintName
example:
#include <iostream>
using namespace std;
void PrintName(string first, string last)
{
string fullname = first + " " + last;
cout << fullname << endl;
}
int main()
{
PrintName("Thomas", "Jefferson");
return 0;
}
Notice in the PrintName()
function that you declare a variable called fullname
. You then use that variable in the second line in that function, the one starting with cout
. But you cannot use the variable inside main()
. If you try to, as in the following code, you get a compile error:
int main()
{
PrintName("Thomas", "Jefferson");
cout << fullname << endl;
return 0;
}
However, you can declare a variable called fullname
inside main()
, as in the PrintName2
example. But, if you do that, this fullname
is local only to main()
, whereas the other variable, also called fullname
, is local only to the PrintName()
function. In other words, each function has its own variable; they just happen to share the same name. But they are two separate variables:
#include <iostream>
using namespace std;
void PrintName(string first, string last)
{
string fullname = first + " " + last;
cout << fullname << endl;
}
int main()
{
string fullname = "Abraham Lincoln";
PrintName("Thomas", "Jefferson");
cout << fullname << endl;
return 0;
}
Thomas Jefferson
Abraham Lincoln
All examples in this chapter place the function code above the code for main()
. The reason is that the compiler scans the code from start to finish. If it has not yet encountered a function but sees a call to it, it doesn’t know what it’s seeing, and it issues a good old compile error.
Such an error can be especially frustrating and can cause you to spend hours yelling at your computer. Nothing is more frustrating than looking at your application and being told by the compiler that it’s wrong, yet knowing that it’s correct because you know that you wrote the function.
You can, however, place your functions after main()
; or you can even use function prototypes to put your functions in other source code files (a topic you find in Book 1, Chapter 7).
What you can do is include a function prototype. A function prototype is nothing more than a copy of the function header. But rather than follow it with an open brace and then the code for the function, you follow the function header with a semicolon and you are finished. A function prototype, for example, looks like this:
void PrintName(string first, string last);
Then you actually write the full function (header, code, and all) later. The full function can even be later than main()
or later than any place that makes calls to it.
Notice that this example looks just like the first line of a function. In fact, it’s possible to cheat! To write it, you simply copy the first line of the original function you write and add a semicolon. The PrintName3
example, shown in Listing 6-9, shows how to use this technique.
LISTING 6-9: Using a Function Prototype
#include <iostream>
using namespace std;
void PrintName(string first, string last);
int main()
{
PrintName("Thomas", "Jefferson");
return 0;
}
void PrintName(string first, string last)
{
string fullname = first + " " + last;
cout << fullname << endl;
}
Notice that the function header appears above main()
and ends with a semicolon. Next comes main()
. Finally, you see the PrintName()
function itself (again, with the header but no semicolon this time). Thus, the function comes after main()
.
“Whoop-de-do,” you say. “The function comes after.” But why bother when now you have to type the function header twice?
This step truly is useful. If you have a source code file with, say, 20 functions, and these functions all make various calls to each other, it could be difficult to carefully order them so that each function calls only functions that are above it in the source code file. Instead, most programmers put the functions in some logical order (or maybe not), and they don’t worry much about the calling order. Then they have all the function prototypes toward the top of the source code file, as shown previously in Listing 6-9.
Sometimes you may want to write two versions of the same function, with the only difference being that they take different parameter types. For example, you may want a function called Combine()
. One version takes two strings and puts the two strings together, but with a space in the middle. It then prints the resulting string to the console. Another version adds two numbers and writes all three numbers — the first two and the sum — to the console. The first version would look like this:
void Combine(string first, string second)
{
cout << first << " " << second << endl;
}
There’s nothing magical or particularly special about this function. It’s called Combine()
; it takes two strings as parameters; it doesn’t return anything. The code for the function prints the two strings with a space between them. Now the second version looks like this:
void Combine(int first, int second)
{
int sum = first + second;
cout << first << " " << second << " " << sum << endl;
}
Again, nothing spectacular here. The function name is Combine()
, and it doesn’t return anything. But this version takes two integers, not two strings, as parameters. The code is also different from the previous code in that it first computes the sum of the inputs and then prints the different numbers.
LISTING 6-10: Writing Two Versions of a Function
#include <iostream>
using namespace std;
void Combine(string first, string second)
{
cout << first << " " << second << endl;
}
void Combine(int first, int second)
{
int sum = first + second;
cout << first << " " << second << " " << sum << endl;
}
int main()
{
Combine("David","Letterman");
Combine(15,20);
return 0;
}
You see each function called in main()
. The compiler chooses which function to call based on the arguments you provide. For example, when viewing this call:
Combine("David","Letterman");
you see two strings. So, the compiler knows to use the first version, which takes two strings. Now look at the second function call:
Combine(15,20);
This call takes two integers, so the compiler knows to use the second version of the function.
To get the most out of strings, you need to make use of some special functions that cater to the strings. However, using these functions is a little different from the other functions used so far in this chapter. Rather than just call the function, you first type the variable name that holds the string, and then a period (or dot), and then the function name along with any arguments.
One function that you can use is insert()
. You can use this function if you want to insert more characters into another string. For example, if you have the string "Something interesting and bizarre"
and you insert the string "seriously "
(with a space at the end) into the middle of it starting at index 10, you get the string "Something seriously interesting and bizarre"
.
string words = "Something interesting and bizarre";
words.insert(10, "seriously ");
The first of these lines simply creates a string called words
and stuffs it full with the phrase "Something interesting and bizarre"
. The second line does the insert. Notice the strange way of calling the function: You first specify the variable name, words
, and then a dot, and then the function name, insert
. Next, you follow it with the parameters in parentheses, as usual. For this function, the first parameter is the index where you want to insert the string. The second parameter is the actual string you are going to insert. After these two lines run, the string variable called words
contains the string "Something seriously interesting and bizarre"
.
You can also erase parts of a string by using a similar function called erase()
. The following line of code erases 16
characters from the words
string starting at index 19
:
words.erase(19,16);
Consequently, if the variable called words
contains the string "Something seriously interesting and bizarre"
, after this line runs, it will contain "Something seriously bizarre"
.
Another useful function is replace()
. This function replaces a certain part of the string with another string. To use replace
, you specify where in the string you want to start the replacement and how many characters you want to replace. Then you specify the string with which you want to replace the old, worn-out parts.
For example, if your string is "Something seriously bizarre"
and you want to replace the word "thing"
with the string "body"
, you tell replace()
to start at index 4
and replace 5
characters with the word "body"
. To do this, you enter:
words.replace(4, 5, "body");
The OperatingOnStrings
example, shown in Listing 6-11, demonstrates all these functions working together.
LISTING 6-11: Operating on Strings
#include <iostream>
using namespace std;
int main()
{
string words = "Something interesting and bizarre";
cout << words << endl;
words.insert(10, "seriously ");
cout << words << endl;
words.erase(19,16);
cout << words << endl;
words.replace(4, 5, "body");
cout << words << endl;
return 0;
}
When you run this application, you see the following output:
Something interesting and bizarre
Something seriously interesting and bizarre
Something seriously bizarre
Somebody seriously bizarre
The first line is the original string. The second line is the result of the insert()
function. The third line is the result of the erase()
function. And the final line is the result of the replace()
function.
All applications so far in this chapter have had a main()
, which is a function. Notice its header, which is followed by code inside braces:
int main()
You can see that this is definitely a function header: It starts out with a return type and then the function name, main()
. This is just one form of the main()
function — the form that Code::Blocks uses by default. However, you may decide that you want to give users the ability to provide input when they type the name of your application at the console. In this case, you use this alternative form of the main()
function that includes two parameters:
int main(int argc, char *argv[])
Notice that the second form of main()
has two parameters:
int argc
: Tells you how many arguments appear on the command line.char *argv[]
: Provides a list of the command-line arguments in an array.A command-line argument is something you type in the Windows Command Prompt or at the Linux Terminal window after the name of the application (the command you want to execute). When you run an application, especially from the command prompt, you type the name of the application and press Enter. But before pressing Enter, you can follow the application name with other words that are generally separated by spaces.
Many of the commands you use in Terminal window and the Command Prompt have an application name and then various arguments. The command usually tells you about these arguments when you enter a special argument such as /?
or --h
. An argument preceded by a slash (/) or two dashes (--) is a switch because it affects how the command works. Figure 6-3 shows an example of the dir
(directory) command using the /?
switch to tell you about the other arguments (including other switches) available with dir
.
FIGURE 6-3: Command-line apps often have switches and arguments.
To make these switches and their associated arguments work, the main()
function must process the input. You determine how many command-line arguments the user supplied using argc
, and then access them using argv
. Book 2, Chapter 2 deals with the topic arrays. An array is a sequence of variables stored under one name. The argv
variable is one such animal. To access the individual variables stored under the single umbrella known as argv
, you do something like this:
cout << argv[0] << endl;
In this example, you use brackets as you did when accessing the individual characters in a string. When working with the /?
switch, you see /?
as the output. You can access the command-line parameters using a for
loop. The CommandLineParameters
example, shown in Listing 6-12, demonstrates this technique.
LISTING 6-12 Accessing the Command-Line Parameters
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(int argc, char *argv[])
{
for (int index=1; index < argc; index++)
{
cout << argv[index] << endl;
}
return 0;
}