![]()       Blog     Consulting     Seminars     Calendar     Books     CD-ROMS     Newsletter     About     FAQ      Search |
Modify Hello.cpp so that it prints out your name and
age (or shoe size, or your dog’s age, if that makes you feel better).
Compile and run the program.
Solution:
The original Hello.cpp appeared in the text as
follws:
// Saying Hello with C++
#include <iostream> // Stream declarations
using namespace std;
int main() {
cout << "Hello, World! I am "
<< 8 << " Today!" << endl;
}
Here’s my rewrite:
//: S02:Hello2.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World! I am Chuck Allison." << endl;
cout << "I have two dogs:" << endl;
cout << "Sheba, who is " << 5 << ", and" << endl;
cout << "Muffy, who is 8." << endl;
cout << "(I feel much better!)" << endl;
}
/* Output:
Hello, World! I am Chuck Allison.
I have two dogs:
Sheba, who is 5, and
Muffy, who is 8.
(I feel much better!)
*/ ///:~
I chose to have separate statements that send output to
cout, but I could have printed everything in a single statement if I had
wanted, like the example in the text does. Note that in the case of
Sheba’s age, I printed 5 as an integer, but for Muffy I included the
numeral in the literal text. In this case it makes no difference, but when you
print floating-point numbers that have decimals, you get 6 decimals by default.
Bruce discusses later in the text how to control output of floating-point
numbers.
Starting with Stream2.cpp and Numconv.cpp,
create a program that asks for the radius of a circle and prints the area of
that circle. You can just use the ‘*’ operator to square the
radius.
Solution:
The two programs mentioned above show how to do numeric input
and output. The following solution to this exercise likewise uses the left-shift
and right-shift operators for input and output, respectively.
//: S02:Area.cpp
//{-T} @echo run Area by hand!
#include <iostream>
using namespace std;
int main() {
const float pi = 3.141592654;
cout << "Enter the radius: ";
float radius;
cin >> radius;
cout << "The area is " << pi * radius * radius << endl;
}
/* Sample Execution:
c:>area
Enter the radius: 12
The area is 452.389
*/ ///:~
The const keyword declares that the float
variable pi will not be changed during the execution of the program. Note
that it is not necessary to insert a newline (via endl, say) after
printing the prompt. That’s because cin is tied to
cout, which means that cout always gets flushed right before you
read from cin.
Create a program that opens a file and counts the
whitespace-separated words in that file.
Solution:
The first version opens its own source file:
//: S02:Words.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream f("Words.cpp");
int nwords = 0;
string word;
while (f >> word)
++nwords;
cout << "Number of words = " << nwords << endl;
}
/* Output:
Number of words = 42
*/ ///:~
The <fstream> header defines classes for file IO,
including ifstream, whose constructor takes a file name an argument. The
expression f >> word extracts the next non-whitespace token from
the file and returns the stream. When a stream appears in a boolean context,
such as the while statement above, it evaluates to true until end-of-file
reached or an error occurs.
It turns out that on many operating systems you can take
advantage of i/o redirection, which allows you to map standard input or
output to a file on the command line. If you rewrite Words.cpp to read
from cin, then you can read any file you want, as the following
illustrates.
//: S02:Words2.cpp
//{T} < Area.cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
int nwords = 0;
string word;
while (cin >> word) {
++nwords;
}
cout << "Number of words = " << nwords << endl;
}
/* Sample Execution:
c:>words < Area.cpp
Number of words = 41
*/ ///:~
The less-than symbol redirects standard input to come from the
file Area.cpp, so that when you run the program, cin is hooked to
that file. The greater-than symbol does the same for cout.
Create a program that counts the occurrence of a particular
word in a file (use the string class’ operator
‘==’ to find the word).
Solution:
//: S02:WordCount.cpp
// Counts the occurrences of a word
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char* argv[]) {
using namespace std;
// Process command-line arguments:
if (argc < 3) {
cerr << "usage: WordCount word file\n";
return -1;
}
string word(argv[1]);
ifstream file(argv[2]);
// Count occurrences:
long wcount = 0;
string token;
while (file >> token)
if (word == token)
++wcount;
// Print result:
cout << '"' << word << "\" appeared "
<< wcount << " times\n";
} ///:~
This program uses the argc and argv arguments to
main, which represent the argument count and array of pointers to the
arguments, respectively. If you don’t provide a word to search for and a
file to search in, you get an error message and the program quits. The
extraction operator for input streams skips whitespace when filling a string
object, so token takes on each such “word” in the file in
succession. When run on its own text you get the following output:
"word" appeared 3 times
Notice that in this example I chose to put the using
directive in main, instead of at file scope. In these simple examples it
really doesn’t matter where you put it, but in examples where you have
many functions, it’s sometimes important to only put the directive inside
the functions that need it, to minimize the possibility of name clashes. Bruce
discusses this in more detail in Chapter 4.
Change Fillvector.cpp so it prints the lines
(backwards) from last to first.
Solution:
This modification to FillVector.cpp from the book
requires only that you change the index to the vector from i to
v.size()-i-1.
//: S02:Fillvector.cpp
// Copy an entire file into a vector of string
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main() {
vector<string> v;
ifstream in("Fillvector.cpp");
string line;
while(getline(in, line))
v.push_back(line);
// Print backwards:
int nlines = v.size();
for(int i = 0; i < nlines; i++) {
int lineno = nlines-i-1;
cout << lineno << ": " << v[lineno] << endl;
}
} ///:~
Change Fillvector.cpp so it concatenates all the
elements in the vector into a single string before printing it out, but
don’t try to add line numbering.
Solution:
Following the example of FillString.cpp, the program
below appends each string in the vector to a string variable (lines),
following each with a newline.
//: S02:Fillvector2.cpp
// Copy an entire file into a vector of string
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main() {
vector<string> v;
ifstream in("Fillvector2.cpp");
string line;
while(getline(in, line))
v.push_back(line);
// Put lines into a single string:
string lines;
for(int i = 0; i < v.size(); i++)
lines += v[i] + "\n";
cout << lines;
} ///:~Display a file a line at a time, waiting for the user to press
the “Enter” key after each line.
Solution:
To make this program work as advertised, it’s important
to not follow each display of a line with a newline character, otherwise
the output will appear double-spaced.
//: S02:FileView.cpp
// Displays a file a line at a time
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream in("FileView.cpp");
string line;
while(getline(in, line)) {
cout << line; // No endl!
cin.get();
}
} ///:~
The call to cin.get( ) waits for you to press
Enter and consumes a single character (the newline that results from pressing
Enter).
Create a vector<float> and put 25 floating-point
numbers into it using a for loop. Display the vector.
Solution:
//: S02:FloatVector.cpp
// Fills a vector of floats
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Fill vector:
vector<float> v;
for (int i = 0; i < 25; ++i)
v.push_back(i + 0.5);
// Display
for (int i = 0; i < v.size(); ++i) {
if (i > 0)
cout << ' ';
cout << v[i];
}
cout << endl;
}
/* Output:
0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 10.5 11.5
12.5 13.5 14.5 15.5 16.5 17.5 18.5 19.5 20.5 21.5
22.5 23.5 24.5
*/ ///:~
In this solution I decided to separate the numbers by spaces,
to take up fewer lines in the output. I could have used 25 as the limit of the
second for loop, but it’s better to use
vector::size( ), since that works no matter how many elements you
process.
Create three vector<float> objects and fill the
first two as in the previous exercise. Write a for loop that adds each
corresponding element in the first two vectors and puts the result in the
corresponding element of the third vector. Display all three
vectors.
Solution:
//: S02:FloatVector2.cpp
// Adds vectors
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<float> v1, v2;
for (int i = 0; i < 25; ++i) {
v1.push_back(i);
v2.push_back(25-i-1);
}
// Form sum:
vector<float> v3;
for (int i = 0; i < v1.size(); ++i)
v3.push_back(v1[i] + v2[i]);
// Display:
for (int i = 0; i < v1.size(); ++i) {
cout << v1[i] << " + " << v2[i]
<< " = " << v3[i] << endl;
}
}
/* Output:
0 + 24 = 24
1 + 23 = 24
2 + 22 = 24
3 + 21 = 24
4 + 20 = 24
5 + 19 = 24
6 + 18 = 24
7 + 17 = 24
8 + 16 = 24
9 + 15 = 24
10 + 14 = 24
11 + 13 = 24
12 + 12 = 24
13 + 11 = 24
14 + 10 = 24
15 + 9 = 24
16 + 8 = 24
17 + 7 = 24
18 + 6 = 24
19 + 5 = 24
20 + 4 = 24
21 + 3 = 24
22 + 2 = 24
23 + 1 = 24
24 + 0 = 24
*/ ///:~
It is crucial, of course, that you use push_back to
fill v3. Mathematically we think of the operation as:
v3[i] = v1[i] + v2[i]; // wrong!
but v3[i] does not exist unless you make space for it,
which is exactly what push_back does. If you want to use the above
expression instead, you can “size” the vector with the resize
method, as follows:
// Form sum:
vector<float> v3;
v3.resize(v1.size()); // pre-allocate space
for (int i = 0; i < v1.size(); ++i)
v3[i] = v1[i] + v2[i];
When you call resize on a vector, it truncates the
sequence if the new size is smaller, or it appends “zeroes”, if the
number is larger, where “zero” means the appropriate value for the
type of contained element. You can even resize vectors of strings and get empty
strings added. Try it!
Create a vector<float> and put 25 numbers into it
as in the previous exercises. Now square each number and put the result back
into the same location in the vector. Display the vector before
and after the multiplication.
Solution:
//: S02:FloatVector3.cpp
// Squares a vector of floats
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Fill and print:
vector<float> v;
for (int i = 0; i < 25; ++i)
v.push_back(i);
for (int i = 0; i < v.size(); ++i) {
if (i > 0)
cout << ' ';
cout << v[i];
}
// Square and print:
for (int i = 0; i < v.size(); ++i)
v[i] = v[i] * v[i];
for (int i = 0; i < v.size(); ++i) {
if (i > 0)
cout << ' ';
cout << v[i];
}
} ///:~
This might be a good time to mention a work-around for
compilers that don’t support reusing for-loop variables, like I did
with i above. If you have such a compiler, simple define the following
macro:
#define for if(0); else for
This puts all for statements in the else-part of
an if-else, where the if-part is empty. As long as you compiler
does proper scoping for if-else statements, this will allow you to reuse
loop indices until your compiler comes up with a standards-compliant
version.
|
Search
    Home
    WebLog
    Consulting
    Seminars
    Calendar
    Books
    CD-ROMS
    Newsletter
    About
    Contact
    Site Design
    Server Maintenance
    Powered by Zope ©2007 MindView, Inc. |