Thus far in this book the primary data types have been char, int, float, and bool, which are good as long as you want to manipulate numbers. But none of them alone allow sections of text to be represented. By this, I mean words, paragraphs, and so on. There is no data type to store a name, for example. In short, this kind of textual data can be seen as an array of chars, where each char is a letter. Because of this, words and other text blocks are said to be a string of chars, usually abbreviated to string.
In the "old days" of C++, most programmers represented strings using an array of chars, such as:
A problem immediately arose about the size of the array, which needed to be declared in advance (e.g., 100 chars long). This meant either the length of strings needed to be known in advance to create an array of appropriate size, or the arrays needed to be sized to some maximum length that would accommodate most strings. The problem with the latter option, of course, was most strings would be shorter than this length and so memory space would be wasted on arrays larger than they typically needed to be.
In response to this, programmers used dynamic memory allocations to create arrays on the fly, sized exactly to hold a string, like so:
char *name = new char[size_of_string];
This was better; however, further problems then arose. How would a string be assigned to this array of chars? How, for example, could you say something like name = “john”? We know from existing arrays that to set array elements you must use the subscript operator (), like number=5. You cannot simply assign values to the whole array like name = “john”. Instead, you need to access each element. But surely, the following code would prove tedious:
char *name = new char[size_of_string]; name = 'a'; name = 'l'; name = 'a'; name = 'n';
All these lines of code are necessary to simply store the word "alan"! So in response, programmers created a number of functions, and these now come shipped with C++. The functions accept different arguments with the aim of making it easier to use strings. For example, the strlen function returns the length (in characters) of a string.
char str  = "hello"; int length = strlen(str);
In addition to strlen, there are all kinds of other string functions such as strcpy, which copies the contents of one string into another; strcmp, a function to compare two strings for their similarity; and strstr, which searches one string to see whether it contains the contents of another string, and so on.
But quite apart from the usefulness of these functions, a new problem arises, namely variable strings. What could be done to hold a string that may change size throughout its lifetime? Arrays that are of a known size and arrays that are created dynamically share something in common: Both have their size determined as the array is created. However, what can be said of variable arrays? What if letters need to be added to or subtracted from the string? In this case, creating a variable of an initial size was no good because it could never account for how much the string might change from its original state.
The eventual solution to these problems came in the form of a class data type called std::string.