Print This PagePrint This Page

 

Strings

C Strings | The String Type | File I/O

This week, we are going to take a look at the use of strings in a C++ program. There are many situations in which information from a problem is best captured in the form of a string. Thus far, we have been using the string data type for storing string values. C-style strings provide another way to store string data. We will be exploring the use of C-style strings, and we will take another look at the string type to discover some of its additional capabilities. We will also take a quick look at the use of strings in doing file input/output operations.

 

C Strings

Back To Top

C strings are simply character arrays with a special requirement; the null character ('\0') is used to designate the end of the string. C strings came from the C language, which was the predecessor of C++. Since C strings have been around for a very long time, they have found their way into many different places. Many libraries that provide functions for programmers to use were developed using C strings. This means that when you go to use a function from a library which takes a string argument, you will often be required to provide that string in the form of a C string!

Since C strings are character arrays, they must follow all rules for an array. This means that you cannot use any operators on C strings. You cannot add two C strings together using the "+" operator. You cannot compare C strings using relational operators. You cannot assign one C string to another. Once you have declared a C string, its size cannot be changed.

Luckily for us, someone has developed a library of functions that are specifically designed to operate on C strings. The cstring library contains functions for copying one C string to another, for getting the length of a C string, and for comparing two C strings. You can find a complete list of the functions in this library, as well as explanations by doing an Internet search on "C-string library."

The iostream data types were designed to work with C strings. This means that you can use cin and cout with C strings. The following illustrates this statement.

const int LEN = 100;    // Declare a constant for the length of the array
char input ;            // Declare a character array to contain input
cin >> input;           // cin reads characters into input until whitespace is found
cout << input << endl;  // cout outputs characters until the null character is found

When cin creates a C string, it will automatically add the null terminator to mark the end of the C string. The obvious problem of using a C string in this manner is that cin does not know the storage capacity of the input array! Therefore, if the input stream contains more non-whitespace characters than the length of the array, cin will continue writing characters past the end of the input array. This will lead to some kind of runtime error in your program!

Another way to use C strings with cin is to use the get or getline methods as shown below.

cin.get(input, LEN);      // Gets up to LEN – 1 characters, stops at end of line
cin.getline(input, LEN);  // Gets up to LEN – 1 characters, stops at end of line

Both of these functions will place all characters encountered, including white-space characters, into the input array. The length of the input array will not be exceeded. Both will provide null termination automatically. The only difference is that the get function leaves the end-of-line character in the input stream and the getline function throws the end-of-line character away.

 

The string Type

Back To Top

The string type is generally more flexible than the C string type. The string type can be used with many of the C++ operators. One string variable can be assigned to another using the assignment operator. Two string variables can be compared using the relational operators. Two string variables can be concatenated to form a new string using the "+" operator.

In addition to these conveniences, there are many functions supplied with the string type to operate on string variables. You can find a complete listing of operators and functions that are part of the string type by doing an Internet search on "C++ string type."

One significant difference between the string type and C strings is that string variables are not constrained to their initial size! This can be seen simply by using the push_back(someChar) function, which is used to add characters to the end of a string variable.

string str;
str.push_back('X');   // Add the character 'X' to the end of the str variable

While a large character array can be declared to hold any C string up to its size limit, a string variable effectively has no limit. This is accomplished using dynamic memory allocation, which you will be studying in your next programming class!

As was mentioned earlier, there are many functions that require a C string as a parameter. If you are using string variables, there is an easy way to extract a C string from a string variable. The c_str( ) function returns a C string containing the characters from the string variable.

string str = "Hello There";
str.c_str();                 
// Returns a C string containing "Hello There".

 

File I/O

Back To Top

Strings are often used in applications that involve storing information in a file or retrieving information from a file. C++ has made doing input and output to a file as easy as doing input from a keyboard and output to a console window. The file stream data types are designed to work the same way as the iostream data types to which cin and cout belong.

In order to use the file stream data types, you need to include the file stream library in your project. This is done by adding the following include statement to your program.

#include <fstream>

There are two basic operations that can be done on a file: reading and writing. If you are simply going to read data from a file, you can use the ifstream data type. If you are going to simply write data to a file, you can use the ofstream data type. To create an ifstream or ofstream variable, you need to specify the name of the file that you want to access. You typically must include the entire path name of the file. The following is an example.

char iname<> = "c:\\input.txt";
char oname<> = "c:\\output.txt";
ifstream input(iname);
ofstream output(oname);

The example code creates an ifstream variable input for reading the file c:\input.txt and an ofstream variable output for writing the file c:\output.txt. One important thing to notice is how the file paths are represented within the C-string variables. Notice that there are two backslashes together (\\) instead of just one. Within a string, the backslash character has special meaning. For instance, \n indicates end of line, and \t indicates tab. Any time that we want to use the backslash as a normal character in a string, we need to escape its special meaning. This is accomplished by putting two backslashes together.

Now we can use our input variable just like we use cin, and our output variable just like we use cout. If we want to read lines from the file, we will need to provide a character array to hold the line just like we would if we were reading a line from cin.

const int BLEN = 100;
char buffer ;
input.getline(buffer, BLEN);
output << buffer << endl;

This code creates a character buffer and uses the input variable to read the first line from the file up to a max of 99 characters. The line ends with a null terminator. Notice that after we have read a line from the file, we use the output variable and the insertion operator to send the contents of the buffer to the output file. We also send an end-of-line character to the output file.

The only trick remaining is to place this code in a loop that runs until the end of the file has been reached. We can detect that by using the eof( ) method of the ifstream data type.

This loop reads lines from the input file until the end of file is reached. After the loop completes and we are done using the files, we need to close the file streams. This is accomplished using the close( ) function as shown above.