Please indicate the source: http://blog.csdn.net/gaoxiangnumber1
Welcome to my github: https://github.com/gaoxiangnumber1
namespace_name::
prefix. A using declaration has the form using namespace::name;
A Separate using Declaration Is Required for Each Name
#include <iostream>
// using declarations for names from the standard library
using std::cin;
using std::cout;
using std::endl;
int main()
{
cout << "Enter two numbers:" << endl;
int v1, v2;
cin >> v1 >> v2;
cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << endl;
return 0;
}
Headers Should Not Include using Declarations
Rewrite the exercises from §1.4.1 (p. 13) and §2.6.2 (p. 76) with appropriate using declarations.
/************************* 1.9 *************************/
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int num = 50, sum = 0;
while(num <= 100)
{
sum += num;
++num;
}
cout << "The sum from 50 to 100 is " << sum << endl;
return 0;
}
/************************* 1.10 *************************/
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int num = 10;
while(num >= 0)
{
cout << num << endl;
--num;
}
return 0;
}
/************************* 1.11 *************************/
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int small = 0, big = 0;
cout << "Please input 2 integers: ";
cin >> small >> big;
if(small > big)
{
int temp = small;
small = big;
big = small;
}
// Print integers in the range [num1, num2]:
while(small <= big)
{
cout << small << endl;
++small;
}
return 0;
}
/****************************** 1.5.1 ******************************/
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
struct Sale_data
{
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
int main()
{
Sale_data book;
double price;
cin >> book.bookNo >> book.units_sold >> price;
book.revenue = book.units_sold * price;
cout << book.bookNo << " " << book.units_sold << " " << book.revenue << " " << price;
return 0;
}
/****************************** 1.5.2 ******************************/
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
struct Sale_data
{
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
int main()
{
Sale_data book1, book2;
double price1, price2;
cin >> book1.bookNo >> book1.units_sold >> price1;
cin >> book2.bookNo >> book2.units_sold >> price2;
book1.revenue = book1.units_sold * price1;
book2.revenue = book2.units_sold * price2;
if(book1.bookNo == book2.bookNo)
{
unsigned totalCnt = book1.units_sold + book2.units_sold;
double totalRevenue = book1.revenue + book2.revenue;
cout << book1.bookNo << " " << totalCnt << " " << totalRevenue << " ";
if (totalCnt != 0)
{
cout << totalRevenue / totalCnt << endl;
}
else
{
cout << "(no sales)" << endl;
}
return 0;
}
else
{
cerr << "Data must refer to same ISBN" << endl;
return -1; // indicate failure
}
}
/****************************** 1.6 ******************************/
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
struct Sale_data
{
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
int main()
{
Sale_data total;
double totalPrice;
if (cin >> total.bookNo >> total.units_sold >> totalPrice)
{
total.revenue = total.units_sold * totalPrice;
Sale_data trans;
double transPrice;
while (cin >> trans.bookNo >> trans.units_sold >> transPrice)
{
trans.revenue = trans.units_sold * transPrice;
if (total.bookNo == trans.bookNo)
{
total.units_sold += trans.units_sold;
total.revenue += trans.revenue;
}
else
{
cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
{
cout << total.revenue / total.units_sold << endl;
}
else
{
cout << "(no sales)" << endl;
}
total.bookNo = trans.bookNo;
total.units_sold = trans.units_sold;
total.revenue = trans.revenue;
}
}
cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
{
cout << total.revenue / total.units_sold << endl;
}
else
{
cout << "(no sales)" << endl;
}
return 0;
}
else
{
cerr << "No data?!" << endl;
return -1; // indicate failure
}
}
Direct and Copy Forms of Initialization
string s1 = "hiya"; // copy initialization
string s2("hiya"); // direct initialization
string s3(10, 'c'); // direct initialization
string s4 = string(10, 'c'); // copy initialization; s4 is cccccccccc
Reading and Writing strings
Reading an Unknown Number of strings
int main()
{
string word;
while (cin >> word) // read until end-of-file
cout << word << endl; // write each word followed by a new line
return 0;
}
Using getline to Read an Entire Line
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::string;
int main()
{
string line;
while(getline(cin, line))
{
cout << line << '\n';
}
return 0;
}
The string empty and size Operations
// read input a line at a time and discard blank lines
while (getline(cin, line))
if (!line.empty())
cout << line << endl;
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::string;
int main()
{
string str = "gaoxiangnumber1";
if(str.size() < -1)
{
cout << "int -> unsigned";
}
return 0;
}
/* Output: int -> unsigned */
Comparing strings
"Hello" < "Hello World";
"Hiya" > "Hello"
"Hiya" > "Hello World"
Assignment for strings
string st1(10, 'c'), st2; // st1 is cccccccccc; st2 is an empty string
st1 = st2; // assignment: replace contents of st1 with a copy of st2
// both st1 and st2 are now the empty string
Adding Two strings
string s1 = "hello, ", s2 = "world\n";
string s3 = s1 + s2; // s3 is “hello, world\n”
s1 += s2; // equivalent to s1 = s1 + s2
Adding Literals and string s
string str1 = "gao";
string str2 = str1 + 'x'; // str2 = "gaox"
string str3 = str2 + "iang"; // str3 = "gaoxiang"
// error: invalid operands of types ‘const char [4]’ and ‘const char [6]’ to binary ‘operator+’
string str4 = "gao" + "xiang"; // Error
string str5 = str3 + "number" + "one"; // str5 = "gaoxiangnumberone"
//error: invalid operands of types ‘const char [7]’ and ‘const char [8]’ to binary ‘operator+’
string str6 = "Hello " + "World, " + str5; // Error
string str5 = (str3 + "number") + "one";
string tmp = str3 + "number"; // ok: + has a string operand
str5 = tmp + "one"; // ok: + has a string operand
string str6 = ("Hello " + "World, ") + str5;
Write a program to read the standard input a line at a time. Modify your program to read a word at a time.
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
// One line at a time:
string str;
while(getline(cin, str))
{
cout << str << endl;
}
return 0;
}
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
// One line at a time:
string str;
while(cin >> str)
{
cout << str << endl;
}
return 0;
}
Explain how whitespace characters are handled in the string input operator and in the getline function.
Write a program to read two strings and report whether the strings are equal. If not, report which of the two is larger. Now, change the program to report whether the strings have the same length, and if not, report which is longer.
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string str1, str2;
cin >> str1 >> str2;
if(str1 == str2)
{
cout << "Equal\n";
}
else
{
cout << "Not equal: " << ((str1 > str2) ? str1 : str2) << " is larger.\n";
}
return 0;
}
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string str1, str2;
cin >> str1 >> str2;
string::size_type length1 = str1.size(), length2 = str2.size();
if(length1 == length2)
{
cout << "Same length\n";
}
else
{
cout << ((length1 > length2) ? str1 : str2) << " is longer.\n";
}
return 0;
}
Write a program to read strings from the standard input, concatenating what is read into one large string. Print the concatenated string. Next, change the program to separate adjacent input strings by a space.
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string input, total;
while(cin >> input)
{
total += input;
}
cout << total;
return 0;
}
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string input, total;
while(cin >> input)
{
total = total + ' ' + input;
}
cout << total;
return 0;
}
Advice: Use the C++ Versions of C Library Headers
for (declaration : expression)
statement
string s("Hello World!!!");
// punct_cnt has the same type that s.size returns; see § 2.5.3 (p. 70)
decltype(s.size()) punct_cnt = 0;
// count the number of punctuation characters in s
for (auto c : s) // for every char in s
if (ispunct(c)) // if the character is punctuation
++punct_cnt; // increment the punctuation counter
cout << punct_cnt << " punctuation characters in " << s << endl;
Using a Range for to Change the Characters in a string
string s("Hello World!!!");
// convert s to uppercase
for (auto &c : s) // for every char in s (note: c is a reference)
c = toupper(c); // c is a reference, so the assignment changes the char in s
cout << s << endl;
Processing Only Some Characters?
Using a Subscript for Iteration
Caution: Subscripts are Unchecked
Using a Subscript for Random Access
Use a range for to change all the characters in a string to X.
#include <iostream>
#include <string>
using std::cout;
using std::string;
int main()
{
string str = "gaoxiangnumber1";
for(char &ch : str)
{
ch = 'X';
}
cout << str;
return 0;
}
/* Output: XXXXXXXXXXXXXXX */
What would happen if you define the loop control variable in the previous exercise as type char? Predict the results and then change your program to use a char to see if you were right.
#include <iostream>
#include <string>
using std::cout;
using std::string;
int main()
{
string str = "gaoxiangnumber1";
for(char ch : str)
{
ch = 'X';
}
cout << str;
return 0;
}
/* Output: gaoxiangnumber1 */
Rewrite the program in the first exercise, first using a while and again using a traditional for loop. Which of the three approaches do you prefer and why?
#include <iostream>
#include <string>
using std::cout;
using std::string;
int main()
{
string str1 = "gaoxiangnumber1";
string str2 = str1;
int length = str1.size();
// First: use while
int index1 = 0;
while(index1 < length)
{
str1[index1] = 'X';
++index1;
}
// Second, use traditional for
for(int index2 = 0; index2 < length; ++index2)
{
str2[index2] = 'X';
}
cout << str1 << '\t' << str2;
return 0;
}
/* Output: XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX */
What does the following program do? Is it valid? If not, why not?
string s;
cout << s[0] << endl;
Invalid: undefined behavior.
Write a program that reads a string of characters including punctuation and writes what was read but with the punctuation removed.
#include <iostream>
#include <string>
#include <cctype> // ispunct(c)
using std::cout;
using std::cin;
using std::string;
int main()
{
string str;
cin >> str;
int length = str.size();
for(int index = 0; index < length; ++index)
{
if(ispunct(str[index]))
{
continue;
}
cout << str[index];
}
return 0;
}
Is the following range for legal? If so, what is the type of c?
const string s = "Keep out!";
for (auto &c : s) { /* ... */ }
c = ‘X’;
error: assignment of read-only reference ‘c’. #include <vector>
using std::vector;
vector<int> ivec; // ivec holds objects of type int
vector<Sales_item> Sales_vec; // holds Sales_items
vector<vector<string>> file; // vector whose elements are vectors
List Initializing a vector
vector<int> vec1 {1, 2, 3, 4, 5};
// error: no matching function for call to ‘std::vector<int>::vector(int, int, int, int, int)’
vector<int> vec2 (1, 2, 3, 4, 5);
Value Initialization
vector<int> ivec(10); // ten elements, each initialized to 0
vector<string> svec(10); // ten elements, each an empty string
vector<int> vi = 10; // error: must use direct initialization to supply a size
List Initializer or Element Count?
vector<int> v1(10); // v1 has ten elements with value 0
vector<int> v2{10}; // v2 has one element with value 10
vector<int> v3(10, 1); // v3 has ten elements with value 1
vector<int> v4{10, 1}; // v4 has two elements with values 10 and 1
vector<string> v5{"hi"}; // list initialization: v5 has one element
vector<string> v6("hi"); // error: can't construct a vector from a string literal
vector<string> v7{10}; // v7 has ten default-initialized elements
vector<string> v8{10, "hi"}; // v8 has ten elements with value "hi"
Which, if any, of the following vector definitions are in error? For those that are legal, explain what the definition does. For those that are not legal, explain why they are illegal.
(a) vector
How many elements are there in each of the following vectors? What are the values of the elements?
(a) vector v1; empty
(b) vector v2(10); ten zero
(c) vector v3(10, 42); ten 42
(d) vector v4{10}; 10
(e) vector v5{10, 42}; 10, 42
(f) vector v6{10}; 10 “”
(g) vector v7{10, “hi”};
vector<int> v2; // empty vector
for (int i = 0; i != 100; ++i)
v2.push_back(i); // append sequential integers to v2
// at end of loop v2 has 100 elements, values 0 . . . 99
Key Concept: vectors Grow Efficiently
Implications of Adding Elements to a vector
Write a program to read a sequence of ints from cin and store those values in a vector.
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::vector;
void Print(vector<int> &vec)
{
int length = vec.size();
for(int index = 0; index < length; ++index)
{
cout << vec[index] << " ";
}
cout << '\n';
}
int main()
{
vector<int> vec;
for(int num = 0; cin >> num; )
{
vec.push_back(num);
}
Print(vec);
return 0;
}
Repeat the previous program but read strings this time.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
void Print(vector<string> &vec)
{
int length = vec.size();
for(int index = 0; index < length; ++index)
{
cout << vec[index] << " ";
}
cout << '\n';
}
int main()
{
vector<string> vec;
for(string str; cin >> str; )
{
vec.push_back(str);
}
Print(vec);
return 0;
}
vector<int>::size_type // ok
vector::size_type // error
Computing a vector Index
Subscripting Does Not Add Elements
vector<int> ivec; // empty vector
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec[ix] = ix; // Segmentation fault
Caution: Subscript Only Elements that are Known to Exist!
vector<int> ivec; // empty vector
cout << ivec[0]; // Segmentation fault! error: ivec has no elements!
vector<int> ivec2(10); // vector with ten elements
cout << ivec2[10]; // Segmentation fault! error: ivec2 has elements 0 . . . 9
Write a program to print the size and contents of the vectors from exercise 3.13. Check whether your answers to that exercise were correct. If not, restudy § 3.3.1 (p. 97) until you understand why you were wrong.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
template<typename T>
void Print(vector<T> &vec)
{
int length = vec.size();
for(int index = 0; index < length; ++index)
{
cout << vec[index] << " ";
}
cout << ((length == 0) ? "empty\n" : "\n");
}
int main()
{
vector<int> v1;
vector<int> v2(10);
vector<int> v3(10, 42);
vector<int> v4 {10};
vector<int> v5 {10, 42};
vector<string> v6 {10};
vector<string> v7 {10, "hi"};
cout << "v1:\t";
Print(v1);
cout << "v2:\t";
Print(v2);
cout << "v3:\t";
Print(v3);
cout << "v4:\t";
Print(v4);
cout << "v5:\t";
Print(v5);
cout << "v6:\t";
Print(v6);
cout << "v7:\t";
Print(v7);
return 0;
}
Read a sequence of words from cin and store the values a vector. After you’ve read all the words, process the vector and change each word to uppercase. Print the transformed elements, eight words to a line.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
template<typename T>
void Print(vector<T> &vec)
{
int length = vec.size();
int cnt = 0;
for(int index = 0; index < length; ++index)
{
cout << vec[index] << " ";
++cnt;
if(cnt % 8 == 0)
{
cout << '\n';
}
}
cout << '\n';
}
int main()
{
vector<string> vec;
for(string str1; cin >> str1; )
{
vec.push_back(str1);
}
int length1 = vec.size();
for(int index1 = 0; index1 < length1; ++index1)
{
string &str2 = vec[index1];
int length2 = str2.size();
for(int index2 = 0; index2 < length2; ++index2)
{
char &ch = str2[index2];
ch = (('a' <= ch && ch <= 'z') ? ch - 32 : ch);
}
}
Print(vec);
return 0;
}
Is the following program legal? If not, how might you fix it?
vector<int> ivec;
ivec[0] = 42;
ivec.push_back(42);
List three ways to define a vector and give it ten elements, each with the value 42. Indicate whether there is a preferred way to do so and why.
vector<int> vec1(10, 42);
vector<int> vec2 {42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector<int> vec3;
for (int index = 0; index != 10; ++index)
{
vec3.push_back(42);
}
Read a set of integers into a vector. Print the sum of each pair of adjacent elements. Change your program so that it prints the sum of the first and last elements, followed by the sum of the second and second-to-last, and so on.
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::vector;
int main()
{
vector<int> vec;
int input = 0, length = 1;
cin >> input;
vec.push_back(input);
// First print the sum of each pair of adjacent elements:
cout << "Sum of each pair of adjacent elements:\n";
int first = input;
while(cin >> input)
{
cout << first + input << ' ';
first = input;
vec.push_back(input);
++length;
}
// Second print the sum of the first and last elements, and so on.
cout << "\nSum of the first and last elements, and so on:\n";
for(int index = 0; index < length / 2; ++index)
{
cout << vec[index] + vec[length - 1 - index] << ' ';
}
return 0;
}
// the compiler determines the type of b and e; see § 2.5.2 (p. 68)
// b denotes the first element and e denotes one past the last element in v
auto b = v.begin(), e = v.end(); // b and e have the same type
Iterator Operations
string s("some string");
if (s.begin() != s.end()) // make sure s is not empty
{
auto it = s.begin(); // it denotes the first character in s
*it = toupper(*it); // make that character uppercase
}
// process characters in s until we run out of characters or we hit a whitespace
for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it)
*it = toupper(*it); // capitalize the current character
Iterator Types
vector<int> vec1(10, 618);
vector<int>::iterator it1 = vec1.begin();
*it1 = 6180;
vector<int>::const_iterator it2 = vec1.begin();
// error: assignment of read-only location ‘it2.operator*<const int*, std::vector<int>>()’
*it2 = 61800;
const vector<int> vec2(10, 71);
// error: conversion from ‘std::vector<int>::const_iterator ’ to ‘std::vector<int>::iterator’
vector<int>::iterator it3 = vec2.begin();
vector<int>::const_iterator it4 = vec2.begin();
// error: assignment of read-only location ‘it4.operator*<const int*, std::vector<int>>()’
*it4 = 618;
The begin and end Operations
vector<int> v;
const vector<int> cv;
auto it1 = v.begin(); // it1 has type vector<int>::iterator
auto it2 = cv.begin(); // it2 has type vector<int>::const_iterator
auto it3 = v.cbegin(); // it3 has type vector<int>::const_iterator
Combining Dereference and Member Access
vector<string> vec(10, "gaoxiang");
vector<string>::iterator it = vec.begin();
if((*it).empty()); // ok
// error: ‘std::vector<std::basic_string<char> >::iterator’ has no member named ‘empty’
if(*it.empty());
Some vector Operations Invalidate Iterators
Redo the first exercise from §3.3.3(p.105) using iterators.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
template<typename T>
void Print(vector<T> &vec)
{
typename vector<T>::const_iterator it1 = vec.cbegin(), it2 = vec.cend();
for(; it1 != it2; ++it1)
{
cout << *it1 << " ";
}
cout << ((vec.cbegin() == vec.cend()) ? "empty\n" : "\n");
}
int main()
{
vector<int> v1;
vector<int> v2(10);
vector<int> v3(10, 42);
vector<int> v4 {10};
vector<int> v5 {10, 42};
vector<string> v6 {10};
vector<string> v7 {10, "hi"};
cout << "v1:\t";
Print(v1);
cout << "v2:\t";
Print(v2);
cout << "v3:\t";
Print(v3);
cout << "v4:\t";
Print(v4);
cout << "v5:\t";
Print(v5);
cout << "v6:\t";
Print(v6);
cout << "v7:\t";
Print(v7);
return 0;
}
Revise the loop that printed the first paragraph in text to instead change the elements in text that correspond to the first paragraph to all uppercase. After you’ve updated text, print its contents.
#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
int main()
{
vector<string> text;
for(string line; getline(cin, line); )
{
text.push_back(line);
}
vector<string>::iterator it = text.begin();
for(; it != text.end() && !it->empty(); ++it)
{
for(char &ch : *it)
{
ch = (('a' <= ch && ch <= 'z') ? ch -32 : ch);
}
cout << *it << endl;
}
return 0;
}
Write a program to create a vector with ten int elements. Using an iterator, assign each element a value that is twice its current value. Test your program by printing the vector.
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::vector;
template<typename T>
void Double(vector<T> &vec)
{
typename vector<T>::iterator it1 = vec.begin(), it2 = vec.end();
for(; it1 != it2; ++it1)
{
*it1 *= 2;
}
}
template<typename T>
void Print(vector<T> &vec)
{
typename vector<T>::const_iterator it1 = vec.cbegin(), it2 = vec.cend();
for(; it1 != it2; ++it1)
{
cout << *it1 << " ";
}
cout << ((vec.cbegin() == vec.cend()) ? "empty\n" : "\n");
}
int main()
{
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Double(vec);
Print(vec);
return 0;
}
Arithmetic Operations on Iterators
Using Iterator Arithmetic
// text must be sorted
// beg and end will denote the range we're searching
auto beg = text.begin(), end = text.end();
auto mid = text.begin() + (end - beg)/2; // original midpoint
// while there are still elements to look at and we haven't yet found sought
while (mid != end && *mid != sought)
{
if (sought < *mid) // is the element we want in the first half?
{
end = mid; // if so, adjust the range to ignore the second half
}
else // the element we want is in the second half
{
beg = mid + 1; // start looking with the element just after mid
}
mid = beg + (end - beg)/2; // new midpoint
}
Redo the last exercise from § 3.3.3 (p. 105) using iterators.
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::vector;
int main()
{
vector<int> vec;
int input = 0, length = 1;
cin >> input;
vec.push_back(input);
// First print the sum of each pair of adjacent elements:
cout << "Sum of each pair of adjacent elements:\n";
int first = input;
while(cin >> input)
{
cout << first + input << ' ';
first = input;
vec.push_back(input);
++length;
}
// Second print the sum of the first and last elements, and so on.
cout << "\nSum of the first and last elements, and so on:\n";
vector<int>::const_iterator it1 = vec.cbegin(), it2 = it1 + length / 2, it3 = vec.cend() - 1;
for( ; it1 != it2; ++it1, --it3)
{
cout << *it1 + *it3 << ' ';
}
return 0;
}
Rewrite the grade clustering program from § 3.3.3 (p. 104) using iterators instead of subscripts.
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::vector;
int main()
{
vector<int> scores(11, 0);
int grade;
while (cin >> grade)
{
if(grade <= 100)
{
++(*(scores.begin() + grade / 10));
}
}
for(int score : scores)
{
cout << score << " ";
}
cout << '\n';
return 0;
}
In the binary search program on page 112, why did we write mid = beg + (end - beg) / 2; instead of mid = (beg + end) / 2?
unsigned cnt = 42; // not a constant expression
constexpr unsigned sz = 42; // constant expression
int arr[10]; // array of ten ints
int *parr[sz]; // array of 42 pointers to int
string bad[cnt]; // error: cnt is not a constant expression???
string strs[get_size()]; // ok if get_size is constexpr, error otherwise
int num1, num2 = 10;
cin >> num1;
int arr1[num1], arr2[num2]; // ok
Explicitly Initializing Array Elements
const unsigned sz = 3;
int ia1[sz] = {0,1,2}; // array of three ints with values 0, 1, 2
int a2[] = {0, 1, 2}; // an array of dimension 3
int a3[5] = {0, 1, 2}; // equivalent to a3[] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"}; // same as a4[] = {"hi", "bye", ""}
int a5[2] = {0,1,2}; // error: too many initializers
Character Arrays Are Special
char a1[] = {'C', '+', '+'}; // list initialization, no null. char a1[3]
char a2[] = {'C', '+', '+', '\0'}; // list initialization, explicit null. char a2[4]
char a3[] = "C++"; // null terminator added automatically. char a3[4]
// error: initializer-string for array of chars is too long
const char a4[6] = "Daniel"; // At least char[7]
No Copy or Assignment
int a[] = {0, 1, 2};
int a2[] = a; // error: cannot initialize one array with another
a2 = a; // error: cannot assign one array to another
Understanding Complicated Array Declarations
int *ptrs[10]; // ptrs is an array of ten pointers to int
int &refs[10]; // error: declaration of ‘refs’ as array of references
int (*Parray)[10] = &arr; // Parray points to an array of ten ints
int (&arrRef)[10] = arr; // arrRef refers to an array of ten ints
int *(&arry)[10] = ptrs; // arry is a reference to an array of ten pointers
Assuming txt_size is a function that takes no arguments and returns an int value, which of the following definitions are illegal? Explain why.
unsigned buf_size = 1024;
(a) int ia[buf_size]; ok
(b) int ia[4 * 7 - 14]; ok
(c) int ia[txt_size()]; ok
(d) char st[11] = “fundamental”; error
What are the values in the following arrays?
string sa[10];
int ia[10];
int main()
{
string sa2[10];
int ia2[10];
}
List some of the drawbacks of using an array instead of a vector.
Identify the indexing errors in the following code:
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
ia[ix] = ix;
Write a program to define an array of ten ints. Give each element the same value as its position in the array.
int arr1[10]
for(int index = 0; index < 10; ++index)
arr1[index] = index;
Copy the array you defined in the previous exercise into another array. Rewrite your program to use vectors.
int arr2[10];
for(int index = 0; index < 10; ++index)
arr2[index] = arr1[index];
What would happen if we did not initialize the scores array in the program on page 116?
string nums[] = {"one", "two", "three"};
string *p = &nums[0]; // p points to the first element in nums
string *p2 = nums; // equivalent to p2 = &nums[0], so: p = p2
int ia[] = {0,1,2,3,4,5,6,7,8,9}; // ia is an array of ten ints
auto ia2(ia); // ia2 is an int* that points to the first element in ia
ia2 = 42; // error: ia2 is a pointer, and we can't assign an int to a pointer
// ia3 is an array of ten ints
decltype(ia) ia3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
decltype(ia) ia4 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0};//error: too many initializers for ‘int [10]’
ia3 = p; // error: can't assign an int* to an array
ia3[4] = i; // ok: assigns the value of i to an element in ia3
Pointers Are Iterators
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *p = arr; // p points to the first element in arr
++p; // p points to arr[1]
int *e = &arr[10]; // pointer just past the last element in arr
The Library begin and end Functions
int ia[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = std::begin(ia); // pointer to the first element in ia
int *last = std::end(ia); // pointer one past the last element in ia
int *pbeg = begin(arr), *pend = end(arr);
// find the first negative element, stopping if we've seen all the elements
while (pbeg != pend && *pbeg >= 0)
++pbeg;
Pointer Arithmetic
// ok: arr is converted to a pointer to its first element; p points one past the end of arr
int *p = arr + sz; // use caution -- do not dereference!
int *p2 = arr + 10; // error: arr has only 5 elements; p2 has undefined value
auto n = end(arr) - begin(arr); // n is 5, the number of elements in arr
#include <iostream>
using std::cout;
using std::begin;
using std::end;
int main()
{
int arr1[] = {1, 2, 3, 4, 5};
int arr2[] = {7, 8, 9, 0, 10, 55};
int *ptr1 = begin(arr1), *ptr2 = end(arr1), *ptr3 = end(arr2);
while(ptr1 < ptr2)
{
cout << *ptr1 << ' ';
++ptr1;
}
cout << '\n';
ptr1 = begin(arr1);
while(ptr1 < ptr3)
{
cout << *ptr1 << ' ';
++ptr1;
}
return 0;
}
/* Output: 1 2 3 4 5 1 2 3 4 5 32767 0 0 7 8 9 0 10 55 */
Interaction between Dereference and Pointer Arithmetic
int ia[] = {0, 2, 4, 6, 8}; // array with 5 elements of type int
int last = *(ia + 4); // ok: initializes last to 8, the value of ia[4]
last = *ia + 4; // last = 4, equivalent to ia[0] + 4
Subscripts and Pointers
int arr[] = {1, 2, 3, 4, 5, 6, 7};
int num1 = arr[2]; // // arr is converted to a pointer to the first element in arr
int *ptr1 = arr; // ptr1 points to the first element in arr
int num2 = *(ptr1 + 2); // equivalent to num2 = arr[2]
int *ptr3 = &arr[3]; // ptr3 points to the element indexed by 3
int num3 = ptr3[1]; // equivalent to *(ptr3 + 1), the same element as arr[4]
int num4 = ptr3[-3]; // the same element as arr[0]
cout << num2 << ' ' << num3 << ' ' << num4; // 3 5 1
Given that p1 and p2 point to elements in the same array, what does the following code do? Are there values of p1 or p2 that make this code illegal?
p1 += p2 - p1;
- Make p1 = p2. Always legal.
Using pointers, write a program to set the elements in an array to zero.
int arr[10];
for(int *ptr1 = std::begin(arr), *ptr2 = std::end(arr); ptr1 != ptr2; ++ptr1)
{
*ptr1 = 0;
}
Write a program to compare two arrays for equality. Write a similar program to compare two vectors.
#include <iostream>
#include <vector>
using std::cout;
using std::begin;
using std::end;
using std::vector;
bool CompareArray(int *arr1_begin, int *arr1_end, int *arr2_begin, int *arr2_end)
{
int length1 = arr1_end - arr1_begin, length2 = arr2_end - arr2_begin;
if(length1 != length2)
{
return false;
}
for(int index = 0; index < length1; ++index)
{
if(*(arr1_begin + index) != *(arr2_begin + index))
{
return false;
}
}
return true;
}
bool CompareVector(vector<int> &vec1, vector<int> &vec2)
{
if(vec1 == vec2)
{
return true;
}
return false;
}
int main()
{
int arr1[] = {1, 2, 3, 4, 5}, arr2[] = {1, 2, 3, 4, 5};
cout << CompareArray(begin(arr1), end(arr1), begin(arr2), end(arr2)) << '\n';
vector<int> vec1(5, 6), vec2(5, 7);
cout << CompareVector(vec1, vec2);
return 0;
}
/* Output: 1 0 */
C Library String Functions
char str[] = { 'C', '+', '+' };
cout << strlen(str); // This output: 6
Comparing Strings
string str1 = "gao", str2 = "gaoxiang";
cout << "Larger: " << ((str1 > str2) ? str1 : str2) << '\n'; // gaoxiang
char arr1[] = "gao", arr2[] = "gaoxiang";
cout << "Larger: " << ((arr1 > arr2) ? arr1 : arr2) << '\n'; // Undefined.
if (strcmp(ca1, ca2) < 0) // same effect as string comparison s1 < s2
Caller Is Responsible for Size of a Destination String
// disastrous if we miscalculated the size of str
strcpy(str, ca1); // copies ca1 into str
strcat(str, " "); // adds a space at the end of str
strcat(str, ca2); // concatenates ca2 onto str
What does the following program do?
const char ca[] = {'h', 'e', 'l', 'l', 'o'};
const char *cp = ca;
while (*cp)
{
cout << *cp << endl;
++cp;
}
In this section, we noted that it was not only illegal but meaningless to try to add two pointers. Why would adding two pointers be meaningless?
Write a program to compare two strings. Now write a program to compare the values of two C-style character strings.
#include <iostream>
#include <string>
#include <cstring>
using std::cout;
using std::string;
int main()
{
string str1 = "gao", str2 = "gaoxiang";
cout << "Larger: " << ((str1 > str2) ? str1 : str2) << '\n'; // gaoxiang
char arr1[] = "gaoxiang", arr2[] = "gao";
cout << "Larger: " << (strcmp(arr1, arr2) > 0 ? arr1 : arr2) << '\n'; // gaoxiang
return 0;
}
Write a program to define two character arrays initialized from string literals. Now define a third character array to hold the concatenation of the two arrays. Use strcpy and strcat to copy the two arrays into the third.
#include <iostream>
#include <cstring>
using std::cout;
int main()
{
char arr1[] = "gao", arr2[] = "xiang", arr3[9];
strcat(arr1, arr2);
strcpy(arr3, arr1);
cout << arr3 << '\n';
return 0;
}
/* Output: gaoxiang */
Mixing Library strings and C-Style Strings
#include <iostream>
#include <string>
using std::cout;
using std::string;
int main()
{
char arr[] = "gaoxiangnumber1";
string str1 = arr;
string str2 = "hello ";
string str3 = str2 + arr;
str2 += arr;
cout << str1 << '\n' << str2 << '\n' << str3;
return 0;
}
/* Output: gaoxiangnumber1 hello gaoxiangnumber1 hello gaoxiangnumber1 */
string str = "gaoxiangnumber1";
// error: initializer fails to determine size of ‘arr1’, array must be initialized with a brace-enclosed initializer
char arr1[] = str;
// error: initializer fails to determine size of ‘arr2’, array must be initialized with a brace-enclosed initializer
char arr2[] = str.c_str();
// error: invalid conversion from ‘const char*’ to ‘char*’
char *arr3 = str.c_str();
const char *arr4 = str.c_str(); // ok
Using an Array to Initialize a vector
// copies three elements: arr[1], arr[2], arr[3]
vector<int> vec(arr + 1, arr + 4);
Write a program to initialize a vector from an array of ints.
#include <iostream>
#include <vector>
using std::cout;
using std::begin;
using std::end;
using std::vector;
template<typename T>
void Print(vector<T> &vec)
{
typename vector<T>::const_iterator it1 = vec.cbegin(), it2 = vec.cend();
for(; it1 != it2; ++it1)
{
cout << *it1 << " ";
}
cout << ((vec.cbegin() == vec.cend()) ? "empty\n" : "\n");
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
vector<int> vec(begin(arr), end(arr));
Print(vec);
return 0;
}
/* Output: 1 2 3 4 5 */
Write a program to copy a vector of ints into an array of ints.
#include <iostream>
#include <vector>
using std::vector;
int main()
{
vector<int> vec(10, 5);
int length = vec.size();
int arr[length];
for(int index = 0; index < length; ++index)
{
arr[index] = vec[index];
}
return 0;
}
Initializing the Elements of a Multidimensional Array
int ia[3][4] = // three elements; each element is an array of size 4
{
{0, 1, 2, 3}, // initializers for the row indexed by 0
{4, 5, 6, 7}, // initializers for the row indexed by 1
{8, 9, 10, 11} // initializers for the row indexed by 2
};
// equivalent initialization without the optional nested braces for each row
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
// initialize [0] in each row, remaining elements are value initialized(§3.5.1,p. 114).
int ia[3][4] = {{ 0 }, { 4 }, { 8 }};
// explicitly initialize row 0; the remaining elements are value initialized
int ix[3][4] = {0, 3, 6, 9};
Subscripting a Multidimensional Array
int arr1[10][20][30];
int arr2[3][4];
// Assign the first element of arr1 to the last element in the last row of arr2
arr2[2][3] = arr1[0][0][0];
int (&ref)[4] = arr2[1]; // Bind ref to the second four-element array in arr2
Using a Range for(C++11) with Multidimensional Arrays
int arr[3][4];
size_t cnt = 0;
for(int (&row)[4] : arr)
{
for(int &col : row)
{
col = cnt++;
}
}
for(const auto &row : arr)
{
for(auto col : row)
{
cout << col << '\n';
}
}
for(auto row : arr)
{
// error: no matching function for call to ‘begin(int*&)’
for(auto col : row)
{
cout << col << '\n';
}
}
Pointers and Multidimensional Arrays
int ia[3][4]; // array of size 3; each element is an array of ints of size 4
int (*p)[4] = ia; // p points to an array of four ints
p = &ia[2]; // p now points to the last element in ia
C++11: Using auto or decltype to Simplify Declarations
#include <iostream>
using std::cout;
using std::begin;
using std::end;
int main()
{
int arr[2][3] = {1, 2, 3, 4, 5, 6};
for (auto p = arr; p != arr + 2; ++p)
{
// q points to the first element of an array of four ints; that is, q points to an int
for (auto q = *p; q != *p + 3; ++q)
{
cout << *q << ' ';
}
cout << '\n';
}
for (auto p = begin(arr); p != end(arr); ++p)
{
// q points to the first element of an array of four ints; that is, q points to an int
for (auto q = begin(*p); q != end(*p); ++q)
{
cout << *q << ' ';
}
cout << '\n';
}
return 0;
}
/* 1 2 3 4 5 6 1 2 3 4 5 6 */
#include <iostream>
using std::cout;
int main()
{
int arr[2][3] = {1, 2, 3, 4, 5, 6};
// error: cannot convert ‘int (*)[3]’ to ‘int*’ in initialization
//int *ptr1 = arr;
int (*ptr1)[3] = arr;
cout << arr << '\t' << arr[0] << '\t' << &arr[0][0] << '\t' << arr[0][0] << '\n'
<< ptr1 << '\t' << *ptr1 << '\t' << **ptr1 << '\n';
cout << "\nWrong traverse because ptr1 is int(*)[3],"
"++ptr1 move from [0][0] to [1][0], not to [0][1]\n";
for(int index = 0; index < 6; ++index, ++ptr1)
{
cout << ptr1 << '\t' << *ptr1 << '\t' << **ptr1 << '\n';
}
cout << "\nRight traverse:\n";
for(ptr1 = arr; ptr1 != arr + 2; ++ptr1)
{
cout << "Row: " << ptr1 << " | ";
for(int *ptr2 = *ptr1; ptr2 != *ptr1 + 3; ++ptr2)
{
cout << ptr2 << ' ' << *ptr2 << ' ';
}
cout << '\n';
}
return 0;
}
/* Output: 0x7ffd15980030 0x7ffd15980030 0x7ffd15980030 1 0x7ffd15980030 0x7ffd15980030 1 Wrong traverse because ptr1 is int(*)[3],++ptr1 move from [0][0] to [1][0], not to [0][1] 0x7ffd15980030 0x7ffd15980030 1 0x7ffd1598003c 0x7ffd1598003c 4 0x7ffd15980048 0x7ffd15980048 4196256 0x7ffd15980054 0x7ffd15980054 0 0x7ffd15980060 0x7ffd15980060 0 0x7ffd1598006c 0x7ffd1598006c 32600 Right traverse: Row: 0x7ffd15980030 | 0x7ffd15980030 1 0x7ffd15980034 2 0x7ffd15980038 3 Row: 0x7ffd1598003c | 0x7ffd1598003c 4 0x7ffd15980040 5 0x7ffd15980044 6 */
Type Aliases Simplify Pointers to Multidimensional Arrays
#include <iostream>
using std::cout;
using int_array = int[3]; // Equivalent to: typedef int int_array[3]
int main()
{
int arr[2][3] = {1, 2, 3, 4, 5, 6};
for(int_array *ptr1 = arr; ptr1 != arr + 2; ++ptr1)
{
for(int *ptr2 = *ptr1; ptr2 != *ptr1 + 3; ++ptr2)
{
cout << *ptr2 << ' ';
}
cout << '\n';
}
return 0;
}
/* 1 2 3 4 5 6 */
Write three different versions of a program to print the elements of ia. One version should use a range for to manage the iteration, the other two should use an ordinary for loop in one case using subscripts and in the other using pointers. In all three programs write all the types directly. That is, do not use a type alias, auto, or decltype to simplify the code.
#include <iostream>
using std::cout;
int main()
{
int arr[3][4] = {{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }};
cout << "Version 1: Range for\n";
for(int (&row)[4] : arr)
{
for(int &col : row)
{
cout << col << ' ';
}
}
cout << "\nVersion 2: Ordinary for using subscripts\n";
for(int index1 = 0; index1 < 3; ++index1)
{
for(int index2 = 0; index2 < 4; ++index2)
{
cout << arr[index1][index2] << ' ';
}
}
cout << "\nVersion 3: Ordinary for using pointers\n";
for(int (*row)[4] = arr; row != arr + 3; ++row)
{
for(int *col = *row; col != *row + 4; ++col)
{
cout << *col << ' ';
}
}
return 0;
}
/* Version 1: Range for 0 1 2 3 4 5 6 7 8 9 10 11 Version 2: Ordinary for using subscripts 0 1 2 3 4 5 6 7 8 9 10 11 Version 3: Ordinary for using pointers 0 1 2 3 4 5 6 7 8 9 10 11 */
Rewrite the programs from the previous exercises using a type alias for the type of the loop control variables.
#include <iostream>
using std::cout;
using int_array = int[4];
int main()
{
int arr[3][4] = {{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }};
for(int_array *row = arr; row != arr + 3; ++row)
{
for(int *col = *row; col != *row + 4; ++col)
{
cout << *col << ' ';
}
}
return 0;
}
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
Rewrite the programs again, this time using auto.
#include <iostream>
using std::cout;
int main()
{
int arr[3][4] = {{ 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }};
for(auto &row : arr)
{
for(auto col : row)
{
cout << col << ' ';
}
}
return 0;
}
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
Chapter Summary
Please indicate the source: http://blog.csdn.net/gaoxiangnumber1
Welcome to my github: https://github.com/gaoxiangnumber1