C++ Tutorial - String II (stringstream etc.)
Unlike other built-in types (char, int, etc.), there is no native string data type in C++. However, the library <string> provides a string object which make string to behave the similar way the built-in data type does. The string object is part of C++ standard library, and it can be accessed by using std::string.
C++ string is much easier to deal with compared to the C-string (array of character). The following code shows how to create strings and how to concatenate those:
#include <string> #include <iostream> int main() { std::string s1 = "2"; std::string s2("56"); char ascii[] = {'A','S','C','I','I','\0'}; std::string s3 = ascii; std::string s4 = s1 + s2 + " " + s3 + " characters"; std::cout << s4 << std::endl; // "256 ASCII characters" return 0; }
We can use cin to assign a text to a string. However, the cin has a limitation because it stops reading the input at space, leaving other text in the buffer. So, if we want to get an input (a sentence) with spaces, we may want to use getline() instead. In other words, when the source is stdin (cin), and the target is str, we use the following function:
getline(cin,str);
The getline() function reads from an input stream until it encounters a \n.
#include <string> #include <iostream> int main() { std::string name; std::cout << "Type your full name: "; std::cin >> name; // stops at the first space std::cout << "Hello, " << name << std::endl; std::cout << "Re-type your full name: "; getline(std::cin, name); // read the rest to the end of the line std::cout << "Welcome to C++ string, " << name << "!"; }
Output:
Type your full name: Jane Austin Hello, Jane Re-type your full name: Welcome to C++ string, Austin!
As we see from the output the cin reads only up to the first space it encounters, leaving the last name in the buffer. Then the getline() reads the rest to the end of the line, and the name does not have a chance to get a new input. This is because the cin leaves out the new line character in the buffer, and the getline() function gets it.
So, we need to ignore the new line, \n, by putting a cin.ignore(256,'\n'); just before the getline() function. It instructs to discard 256 characters and stop when it encounters a newline character.
Here are a new code:
#include <string> #include <iostream> int main() { std::string name; std::cout << "Type your full name: "; std::cin >> name; // stops at the first space std::cout << "Hello, " << name << std::endl; std::cout << "Re-type your full name: "; std::cin.ignore(256,'\n'); getline(std::cin, name); // read the rest to the end of the line std::cout << "Welcome to C++ string, " << name << "!"; return 0; }
The new output:
Type your full name: Jane Austin Hello, Jane Re-type your full name: Jane Austin Welcome to C++ string, Jane Austin!
Summary of this section:
use the cin to get a numeric or a single word, but we need to use getline() for an input with spaces.
A string variable cannot be converted to other type of data by casting because it's not a built-in data type. To help this issue, C++ provides us a <sstream> library.
A value can be loaded into a stringstream object using output stream operator(<<) with cout, and then the content can be extracted from the stringstream object with input operator(>>) with cin.
If we want to re-use a stringstream object, it must be back in the original state. In other words, it should be set as empty string via str() method, and its status bit flag (good, bad, eof,or fail) needs to be cleared via clear() method of the stringstream class.
#include <sstream>; #include <string> #include <iostream> int main() { std::string number_s = "99"; int ss_to_number; std::stringstream ss; ss << number_s; // load a string to ss ss >> ss_to_number; // extract an integer from ss int n = ss_to_number / 3; std::cout << "The extracted integer is " << n << std::endl; // to re-use ss, we need to empty and clear ss.str(""); ss.clear(); int number_i = 99; std::string ss_to_string; std::string text_out = "We extracted a string by converting an int sstream"; ss << number_i; // load an integer ss >> ss_to_string; // extract a string from ss text_out += " from " + ss_to_string; std::cout << text_out << std::endl; return 0; }
Output is:
The extracted integer is 33 We extracted a string by converting an int sstream from 99
To join strings we can use either + or append(). To compare strings we can use either == or compare(). The == returns true(1) when two strings match, otherwise it returns false(0).
When we use compare(), the function returns 0 when two strings are equal, and returns -1 when either the value of the first character that does not match is lower in the compared string, or all compared characters match but the compared string is shorter. It returns 1 when either the value of the first character that does not match is greater in the compared string, or all compared characters match but the compared string is longer.
#include <string> #include <iostream> int main() { std::string abc = "abc"; std::string ff = "ff"; std::string fff = "fff"; std::string z = "zz"; std::cout << abc.compare(ff) << std::endl; // -1 std::cout << ff.compare(fff) << std::endl; // -1 std::cout << z.compare(abc) << std::endl; // 1 return 0; }
#include <string> #include <iostream> int main() { std::string front; std::string back; std::string title = "Pride and Prejudice"; front.assign(title); std::cout << front << std::endl; front.assign(title, 0, 4); // first 4 characters std::cout << front << std::endl; back.assign(title, 10, title.size()); std::cout << back << std::endl; front.swap(back); std::cout << "After swap" << std::endl; std::cout << front << std::endl; std::cout << back << std::endl; return 0; }
Note that the second argument is exclusive (not including the last character of the index).
Output:
Pride and Prejudice Prid Prejudice After swap Prejudice Prid
If we use find() function of the <string> library, we can check if a string contains a substring. The first parameter is the subtring to seek and the second parameter should specify the index at which to start searching.
There are other versions of find() functions:
- find_first_of(): seeks the first occurrence of any of the characters in a specified string.
- find_first_not_of(): seeks the first occurrence of a character that is not in a specified string.
- find_last_of() / find_last_not_of(): begin searching at the end of the string and move forwards.
#include <string> #include <iostream> int main() { std::string book = "Jane Austin's Pride and Prejudice"; int pos; pos = book.find("Austin", 0); std::cout << "Austin found at " << pos << std::endl; pos = book.find("Gone"); std::cout << "Gone " << pos << std::endl; pos = book.find_first_of("Jane"); std::cout << "Jane " << pos << std::endl; // first 'J' matches pos = book.find_first_of("Jones"); std::cout << "Jones" << pos << std::endl; // first 'J' matches pos = book.find_first_of("jane"); std::cout << "jane " << pos << std::endl; // case sensitive, 'a' matches pos = book.find_last_of("zzi"); std::cout << "zzi " << pos << std::endl; // 30th 'i' in Prejudice matches return 0; }
Output:
Austin found at 5 Gone -1 Jane 0 Jones0 jane 1 zzi 30
A substring can be copied from a string using the substr() function with its first argument is stating the index position at which is should start copying and the second argument specifying the number of characters to be copied.
We can get a character at any specified position within a string using at() function.
#include <string> #include <iostream> int main() { std::string book = "Jane Austin's Pride and Prejudice"; // starting from 29th, copy 9 character std::string sub = book.substr(24, 9); std::cout << sub << std::endl; // "Prejudice" // the last character std::cout << book.at(book.size()-1) << std::endl; //'e' return 0; }
Additional codes related to string manipulation samples which frequently appear at interviews are sources A and sources B
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization