#include <iostream>
#include <string>
using namespace std;
void Concat1(void)
{
char s1[20];
strcpy(s1, "The quick");
strcat(s1, " brown fox");
cout << s1 << endl;
char s2[25];
strcpy(s2, "jumped over");
strcat(s2, " the lazy");
strcat(s2, " dog");
cout << s2 << endl;
char s3[45];
strcpy(s3, s1);
strcat(s3, " ");
strcat(s3, s2);
cout << s3 << endl;
}
Output:
Using C-style (NULL-terminated) strings (dynamic arrays):The quick brown fox jumped over the lazy dog The quick brown fox jumped over the lazy dog
#include <iostream>
#include <string>
using namespace std;
void Concat2(void)
{
char *s1 = new char[20];
strcpy(s1, "The quick");
strcat(s1, " brown fox");
cout << s1 << endl;
char *s2 = new char[25];
strcpy(s2, "jumped over");
strcat(s2, " the lazy");
strcat(s2, " dog");
cout << s2 << endl;
char *s3 = new char[45];
strcpy(s3, s1);
strcat(s3, " ");
strcat(s3, s2);
cout << s3 << endl;
delete[] s1;
delete[] s2;
delete[] s3;
}
Output:
Using the string class:The quick brown fox jumped over the lazy dog The quick brown fox jumped over the lazy dog
#include <iostream>
#include <string>
using namespace std;
void Concat3(void)
{
string s1 = "The quick";
s1 += " brown fox";
cout << s1 << endl;
string s2;
s2 = s2 + "jumped over" + " the lazy" + " dog";
cout << s2 << endl;
string s3 = s1 + " " + s2;
cout << s3 << endl;
}
Output:
The quick brown fox jumped over the lazy dog The quick brown fox jumped over the lazy dog
void Construct(void)
{
// Create an empty string
string s0;
cout << s0 << endl;
// Create a string from a const char *
string s1("This is a string");
cout << s1 << endl;
// Create a string of chars
string s2(10, '#');
cout << s2 << endl;
// Create a string from another string (copy constructor)
string s3(s1);
cout << s3 << endl;
// Create a string from a char * and a count
const char *p = "The quick brown fox";
string s4(p, 9);
cout << s4 << endl;
// Create a string from a char * and a count
string s5(p + 4, 5);
cout << s5 << endl;
// Create a string from two pointers (between)
string s6(p + 10, p + 15);
cout << "|" << s6 << "|" << endl;
}
Output:
This is a string ########## This is a string The quick quick |brown|
void Input(void)
{
string s1;
cout << "Enter a word: ";
// Read one "word"
cin >> s1;
cout << s1 << endl;
// Ignore the rest of the line
while (cin.get() != '\n')
continue;
string s2;
cout << "Enter several words: ";
// Read up to the new line
getline(cin, s2);
cout << s2 << endl;
}
Output:
Enter a word: Hello Hello Enter several words: One two three four. One two three four.
Fixing the bug in Visual C++
On line 165 of the file ..\VC98\Include\STRING you need to change :
to_I.rdbuf()->snextc();
Here's a web page that has info on the getline fix._I.rdbuf()->sbumpc();
void Test1(void)
{
string s1 = "DigiPen";
// Reading the length of a string
cout << "Length of " << s1 << " is " << s1.length() << endl;
// You can access the internal NULL terminated string
cout << "Length of " << s1.c_str() << " is " << strlen(s1.c_str()) << endl;
// Getting at individual characters
cout << "The second char is: " << s1.at(1) << endl;
cout << "The second char is: " << s1[1] << endl;
// Finding substrings
int position = s1.find("Pen");
if (position != string::npos)
cout << s1.substr(position) << endl;
}
Output:
Length of DigiPen is 7 Length of DigiPen is 7 The second char is: i The second char is: i Pen
template <class CharType, class Attr = char_traits<CharType>, class Allocator = allocator<CharType> >
class basic_string
{
// ...
};
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
Here's the MSDN help page on basic_string.
void VecStuff(void)
{
int SIZE = 5;
vector<int> numbers(SIZE); // create a vector of integers (5)
for (int i = 0; i < SIZE; i++) // assign values to each element
numbers[i] = i * 10;
numbers.resize(numbers.size() * 2); // "grow" the vector twice as big (10)
for (i = SIZE; i < SIZE * 2; i++) // assign values to the new elements
numbers[i] = i * 100;
for (i = 0; i < SIZE * 2; i++) // print out all elements
cout << numbers[i] << endl;
}
Output:
Creating a vector of strings:0 10 20 30 40 500 600 700 800 900
void Vector2(void)
{
int SIZE = 6;
vector<string> speeds(SIZE); // create a vector of strings (6)
speeds[0] = "Snail (slowest)"; // assign values to each element
speeds[1] = "Turtle (slower)";
speeds[2] = "Penguin (slow)";
speeds[3] = "Rabbit (fast)";
speeds[4] = "Lion (faster)";
speeds[5] = "Cheetah (fastest)";
// Display each speed that contains the substring "fast"
for (int i = 0; i < SIZE; i++)
if (speeds[i].find("fast") != string::npos)
cout << speeds[i] << endl;
}
Output:
Here's the MSDN help page on vector.Rabbit (fast) Lion (faster) Cheetah (fastest)
Current implementation:
#include "Shape.h"
class Polygon : public Shape
{
private:
Point *m_Vertices; // array of Points
int m_NumVertices; // number of Points
public:
// public methods
};
Proposed implementation:
#include "Shape.h"
#include <vector>
class Polygon : public Shape
{
private:
vector<Point> m_Vertices; // vector of Points
public:
// public methods
};
Polygon using vectors.
An old constructor:
Polygon::Polygon(const Point *Vertices, int NumVertices)
{
m_NumVertices = NumVertices;
m_Vertices = new Point[m_NumVertices];
for (int i = 0; i < m_NumVertices; i++)
m_Vertices[i] = Vertices[i];
}
A new constructor:
Polygon::Polygon(const Point *Vertices, int NumVertices)
{
m_Vertices.resize(NumVertices);
for (int i = 0; i < m_Vertices.size(); i++)
m_Vertices[i] = Vertices[i];
}
The old Move method:
void Polygon::Move(const Point &position)
{
for (int i = 0; i < m_NumVertices; i++)
m_Vertices[i] = m_Vertices[i] + position;
}
The new Move method:
void Polygon::Move(const Point &position)
{
for (int i = 0; i < m_Vertices.size(); i++)
m_Vertices[i] = m_Vertices[i] + position;
}
Using an iterator instead of a for loop:
ostream & operator<<(ostream & os, const Polygon &polygon)
{
os << "NumVertices: " << polygon.m_Vertices.size();
vector<Point>::const_iterator it;
for (it = polygon.m_Vertices.begin(); it != polygon.m_Vertices.end(); it++)
os << ", " << *it;
return os;
}
void Polygon::Move(const Point &position)
{
vector<Point>::iterator it;
for (it = m_Vertices.begin(); it != m_Vertices.end(); it++)
*it = *it + position;
}
Using push_back:
void Polygon::SetVertices(const Point vertices[], int NumVertices)
{
m_Vertices.clear();
m_Vertices.resize(NumVertices);
for (int i = 0; i < NumVertices; i++)
m_Vertices[i] = vertices[i];
}
void Polygon::SetVertices(const Point vertices[], int NumVertices)
{
m_Vertices.clear();
for (int i = 0; i < NumVertices; i++)
m_Vertices.push_back(vertices[i]);
}
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void Print(int value)
{
cout << value << " ";
}
void PrintVec(vector<int> vec)
{
vector<int>::const_iterator iter;
for (iter = vec.begin(); iter != vec.end(); iter++)
Print(*iter);
cout << endl;
}
void main(void)
{
// Create an empty vector of integers
vector<int> nums;
// Put 10 random integers in the vector
for (int i = 0; i < 10; i++)
nums.push_back(rand() % 100);
// Pass the vector to a function to print
PrintVec(nums);
// Sort the vector
sort(nums.begin(), nums.end());
// Pass each element of the vector to a function to print
for_each(nums.begin(), nums.end(), Print);
}
Output:
41 67 34 0 69 24 78 58 62 64
0 24 34 41 58 62 64 67 69 78
include <iostream>
include <vector>
include <algorithm>
using namespace std;
template <typename T>
void Print(T value)
{
cout << value << " ";
}
template <typename T>
void PrintVec(vector<T> vec)
{
vector<T>::const_iterator iter;
for (iter = vec.begin(); iter != vec.end(); iter++)
Print(*iter);
cout << endl;
}
void main(void)
{
// Create an empty vector of integers
vector<int> nums;
// Put 10 random integers in the vector
for (int i = 0; i < 10; i++)
nums.push_back(rand() % 100);
// Pass the vector to a template function to print
PrintVec(nums);
// Sort the vector
sort(nums.begin(), nums.end());
// Pass each element of the vector to a template function to print
for_each(nums.begin(), nums.end(), Print<int>);
}
Output:
41 67 34 0 69 24 78 58 62 64
0 24 34 41 58 62 64 67 69 78
Since the PrintVec function is redundant (due to the for_each function) we can just remove it. However,
the following code won't compile:
template <typename T>
void Print(T value)
{
cout << value << " ";
}
void main(void)
{
// Create an empty vector of integers
vector<int> nums;
// Put 10 random integers in the vector
for (int i = 0; i < 10; i++)
nums.push_back(rand() % 100);
// Pass each element of the vector to a template function to print
for_each(nums.begin(), nums.end(), Print<int>);
cout << endl;
// Sort the vector
sort(nums.begin(), nums.end());
// Pass each element of the vector to a template function to print
for_each(nums.begin(), nums.end(), Print<int>);
cout << endl;
}
We need to explicitly instantiate the version of the template we need:
template <typename T>
void Print(T value)
{
cout << value << " ";
}
template void Print<int>(int); // explicit instantiation
void main(void)
{
...
}
Why did it work with the PrintVec function?
Client code using a vector of string:
template void Print<string>(string);
void main(void)
{
// Create an empty vector of integers
vector<string> critters;
critters.push_back("Snail");
critters.push_back("Turtle");
critters.push_back("Penguin");
critters.push_back("Rabbit");
critters.push_back("Lion");
critters.push_back("Cheetah");
// Pass each element of the vector to a template function to print
for_each(critters.begin(), critters.end(), Print<string>);
cout << endl;
// Sort the vector
sort(critters.begin(), critters.end());
// Pass each element of the vector to a template function to print
for_each(critters.begin(), critters.end(), Print<string>);
cout << endl;
}
Output:
Snail Turtle Penguin Rabbit Lion Cheetah Cheetah Lion Penguin Rabbit Snail Turtle