The main operational difference is that the string versions automatically size the target string object to hold the input characters:
char fname[10];
string lname;
cin >> fname; // could be a problem if input size > 9 characters
cin >> lname; // can read a very, very long word
cin.getline(fname, 10); // may truncate input
getline(cin, fname); // no truncation
The automatic sizing feature allows the string version of getline() to dispense with the numeric parameter that limits the number of input characters to be read.
A design difference is that the C-style string input facilities are methods of the istream class, whereas the string versions are standalone functions. That’s why cin is an invoking object for C-style string input and a function argument for string object input. This applies to the >> form, too, which is evident if the code is written in function form:
cin.operator>>(fname); // ostream class method
operator>>(cin, lname); // regular function
Let’s examine the string input functions a bit more closely. Both, as mentioned, size the target string to fit the input. There are limits. The first limiting factor is the maximum allowable size for a string, represented by the constant string::npos. This, typically, is the maximum value of an unsigned int, so it doesn’t pose a practical limit for ordinary, interactive input. It could be a factor, however, if you attempt to read the contents of an entire file into a single string object. The second limiting factor is the amount of memory available to a program.
The getline() function for the string class reads characters from the input and stores them in a string object until one of three things occurs:
• The end-of-file is encountered, in which case eofbit of the input stream is set, implying that both the fail() and eof() methods will return true.
• The delimiting character (\n, by default) is reached, in which case it is removed from the input stream but not stored.
• The maximum possible number of characters (the lesser of string::npos and the number of bytes in memory available for allocation) is read, in which case failbit of the input stream is set, implying that the fail() method will return true.
(An input stream object has an accounting system to keep track of the error state of the stream. In this system, setting eofbit registers detecting the end-of-file; setting failbit registers detecting an input error; setting badbit registers some unrecognized failure, such as a hardware failure; and setting goodbit indicates that all is well. Chapter 17, “Input, Output, and Files,” discusses this further.)
The operator>>() function for the string class behaves similarly, except that instead of reading to and discarding a delimiting character, it reads up to a white space character and leaves that character in the input queue. A white space character is a space, newline, or tab character or more generally, any character for which isspace() returns true.
So far in this book, you’ve seen several examples of console string input. Because the input functions for string objects work with streams and recognize the end-of-file, you can also use them for file input. Listing 16.2 shows a short example that reads strings from the file. It assumes that the file contains strings separated by the colon character and uses the getline() method of specifying a delimiter. It then numbers and displays the strings, one string to an output line.
Listing 16.2. strfile.cpp
// strfile.cpp -- read strings from a file
#include
#include
#include
#include
int main()
{
using namespace std;
ifstream fin;
fin.open("tobuy.txt");
if (fin.is_open() == false)
{
cerr << "Can't open file. Bye.\n";
exit(EXIT_FAILURE);
}
string item;
int count = 0;
getline(fin, item, ':');
while (fin) // while input is good
{
++count;
cout << count <<": " << item << endl;
getline(fin, item,':');
}
cout << "Done\n";
fin.close();
return 0;
}
Here is a sample tobuy.txt file:
sardines:chocolate ice cream:pop corn:leeks:
cottage cheese:olive oil:butter:tofu:
Typically, for the program to find the text file, the text file should be in the same directory as the executable program or sometimes in the same directory as the project file. Or you can provide the full path name. On a Windows system, keep in mind that in a C-style string the escape sequence \\ represents a single backslash:
fin.open("C:\\CPP\\Progs\\tobuy.txt"); // file = C:\CPP\Progs\tobuy.txt
Here is the output of the program in Listing 16.2:
1: sardines
2: chocolate ice cream
3: pop corn
4: leeks
5:
cottage cheese
6: olive oil
7: butter
8: tofu
9:
Done
Note that with : specified as the delimiting character, the newline character becomes just another regular character. Thus, the newline character at the end of the first line of the file becomes the first character of the string that continues as "cottage cheese". Similarly, the newline character at the end of the second input line, if present, becomes the sole content of the ninth input string.