The initial release of C++ had few support classes, and specifically lacked a string class. The ANSI C++98 standard formally added the string class. Before the addition, implementing a string class was a common exercise/assignment used to teach and learn C++ and object-oriented programming. While class developers can implement strings in many ways, some with obvious advantages or disadvantages, there isn't a single "right" implementation. This section and the following examples use the string concept to demonstrate object-oriented programming in C++ and to illustrate how drawing a figure can help to solve a problem. The examples, drawn from early non-object-oriented string implementations, focus on problem-solving and object-oriented programming rather than on producing the "best" string classes.
Problem Solving
search for a pattern
draw a figure
formulate an equivalent problem
modify the problem
choose effective notation
exploit symmetry
divide into cases
work backward
argue by contradiction
pursue parity
consider extreme cases
generalize
Problem-solving heuristics.
Larson1 lists a dozen general problem-solving heuristics (p. 1). A heuristic is "an aid to learning, discovery, or problem-solving by experimental and especially trial-and-error methods." Although Larson presented the heuristics in the context of solving mathematical problems, they are domain-independent, meaning that they are applicable across many technical fields. Computer scientists also use them for advanced theoretical problems (e.g., "formulate an equivalent problem") and in day-to-day programming. This discussion and the following examples focus on "draw a figure."
Most people need some way to think about or "see" a problem. Jonassen2 explains that "problem solving requires the mental representation of the situation in the world. That is, human problem solvers construct a mental representation (or mental model) of the problem, known as the problem space. Problem solving requires manipulation of the problem space, be it an internal mental representation or an external physical representation" (p. 65). A mathematical problem expressed as an equation is a familiar example. The symbols represent the known and unknown elements of the problem, and the operators represent the relationships between them. Following algebraic rules, the problem-solver manipulates the symbols and operators until a solution emerges.
Figures or pictures can serve as "representations" in an astounding number of situations, helping us identify what we know about a problem, what we need to find, and the relationships between the parts. For example, in the pouring puzzle problem, a picture helped us identify the three pertinent glass characteristics, and to develop an algorithm for pouring water between two glasses. We "manipulate the problem space" by changing the picture to reflect each step of the problem-solving process. We frequently use this technique to help design algorithms for operating on dynamic data structures that link nodes with pointers.
Drawing a picture to help solve a problem is a surprisingly powerful technique. Unfortunately, there are too many problems and variations to allow us to create a general drawing algorithm or recipe. Drawing and using a picture to help solve a problem is a learned skill, but without a recipe, we must learn it through extended practice. Fortunately, there is a process, admittedly general, to guide us:
Study how an experienced problem solver draws and uses pictures to solve a problem
Draw pictures for a similar problem and use them to solve it
Compare your pictures and solution to those of the experienced problem solver
To practice our drawing and problem-solving skills, we need a set of practice problems. We can view strings as an abstract data type, which we can implement in a variety of different ways. Although each implementation is a different problem, we can leverage their similarities to reduce the time needed to understand the basic problem. To this end, we outline a general string and illustrate it with three examples. The examples provide practice in drawing and using pictures to help solve problems, giving us more experience with arrays and further demonstrating how to create and use classes in C++ programs.
Modern operating systems and applications strive to accommodate a worldwide audience. However, detecting and utilizing an appropriate natural or human language occurs at a high level within a software system. Implementing a string type and its supporting operations takes place at a much lower level. Once the software system identifies an appropriate natural language, it selects and uses an appropriate low-level string implementation. The textbook is written and predominantly used in an English-speaking country. For simplicity, the following description and implementations assume a natural language that reads left-to-right.
Developing A String Data Type
Although early high-level programming languages like FORTRAN and ALGOL didn't include a string type when first introduced, today all general-purpose programming languages do. Independent of how we represent strings, they consist of multiple related but distinct data elements. In an object-oriented language, we can easily group the elements in a class, but they present an authentic challenge for non-object-oriented languages.
String elements. We can characterize a dynamic, general-purpose string with three data elements:
sequence of characters. The textual data, represented as a sequence of characters, is the most obvious string element. There is only one efficient way to store the sequence: as an array of characters. How we define and maintain the array depends on the string's implementation.
length / size. The string's length or size is the number of characters in it.
capacity. If a string's length is not fixed (i.e., a program can change the number of characters in the sequence), it may have unused space at the end of the array. It's more efficient (requires less computation) to maintain the array's overall capacity than the number of "empty" spaces at the end.
Most string operations - the services a string object provides to client programs - are independent of the string's implementation. They describe what the string functions do, but not how they do it. The following list of proposed string functions is not exhaustive but is sufficient to practice drawing and problem solving and to review arrays, classes, and their associated notations.
Access Operations
int length(): Returns "this" string's current length or size
int capacity(): Returns "this" string's capacity
char& at(int index): Returns a reference to the indexed character in "this" string
I/O Operations
static void print(char* line): prints line to the console (prints string literals or constants)
void print(): Prints "this" string's text to the console but leaves the cursor at the end of the line
void println(): Prints "this" string's text to the console and moves the cursor to the beginning of the next line
void readln(): Reads a line of text from the console into "this" string
General Operations
void append(string s): Appends string s to the end of "this" string
string concat(string s): concatenates "this" string and s to form and return a new string
void clear(): removes the text from "this" string
string copy(): copies "this" this string to a new returned string
bool equals(string s): returns true if "this" and s save the same textual data; otherwise it returns false
int order(string s): orders "this" and s: returns
void insert(string s, int index): insert string s into "this" string at location index
string substring(int index, int length): extracts a sub-sequence of characters (i.e., a sub-string) length characters long from "this" string beginning at location index
String abstract data type. A list of common string operations implemented as string member functions. Most object-oriented implementations require one or more constructors; some also require a destructor.
Larson, L. C. (1983). Problem-Solving Through Problems. New York: Springer-Verlag.
Jonassen, D. H. (2000). Toward a design theory of problem solving. Educational Technology, Research and Development, 48(4), 63-85.