SECTION 2 - STRINGS

Introduction

-Strings are objects which contain more than one character ("in a string")

-We've used string constants: filenames, error messages

-Now, we'll introduce string variable objects, which allow us to change the value of what is stored

-Unfortunately, there is no ANSI standard C++ string package, and the VC++ string package is huge and unwieldy, so the book provides a library (Strings.h and Strings.cpp, on disk in Appendix file) which simplify string handling, while still providing the major functionality expected w/strings

Basic String Terminology

-length - the number of characters in the string

-elements - each individual character in the string is an element
-elements are numbered, beginning at 0, so that a string of length N, has elements numbered from 0 to N-1:

0 1 2 3 4
h e l l o
-this string has a length of 5 (5 elements numbered 0 to 4)

-empty - a string with no elements (length 0)

-position - the numeric location of a particular element is its position, ie, in the above string, 'o' is in position 4

-subscript/index - similar to position - "the character at index 4 is 'o'", "'e' has a subscript of 1"

Declaring Strings

-must #include "Strings.h", (and have Strings.cpp compiled - can be in project)

-Then:

Strings

MyString;

-Can initialize:

Strings

MyString = "Hello world!";

-In the first example, MyString is empty

-In the second, it has a length of 12 (element #0 is 'H', element #11 is '!')

-Note that a string object can vary in length throughout its lifetime, depending on the length of the string it is currently storing - they can "shrink" and "grow" as required

String I/O

-The I/O operators >> and << are overloaded in the Strings Class - their operation is consistent w/prior use

input:

cin >> MyString;

-This will read characters from the input stream and place them into MyString

-Remember that the >> operator will STOP at whitespace! Any other characters will be left in the istream, and processed when the next read occurs!

-To get all the characters on a line, use the GetLine() member function:

MyString.GetLine(cin);

-This reads all characters until <CR>

-can specify more parameters:

SomeString.GetLine(SomeStream, Max#Chars, UntilChar);
-SomeString: an object of type Strings
-SomeStream: an istream object, or fstream object opened for input
-Max#Chars: optional integer bound on how many chars to read (Default is 1024 characters, (MaxLength))
-UntilChar: optional character that, if read, stops the input process (Default is '\n') - This character is NOT stored in the string

-Useful example - reading in filename from user:

#include <fstream.h>

#include "Strings.h"

#include <iostream.n>

int main(void)

{

Strings

InFileName, OutFileName;

fstream

InStream, OutStream;

cout << "Enter name of intput file\n";

InFileName.GetLine(cin);

cout << "Enter name of the output file\n";

OutFileName.GetLine(cin);

InStream.open(InFileName, ios::in | ios::nocreate);

OutStream.open(OutFileName, ios::out);

//etc.

}

output:

-Use of << is just as expected - can use with ostream objects (cout, cerr) or fstream objects opened for output

example:

/* This program uses class Strings to copy a file.

Output(screen): Prompts for input

Input(keyboard): The name of an input file, stored in

InputFileName; and the name of an output

file, stored in OutputFileName

Input(InputFileName): Characters in the file, line by line

Output(OutputFileName): All the input characters

------------------------------------------------------------------*/

#include <iostream.h> // cin, cout, <<, >>

#include <fstream.h> // fstream, <<, >>

#include <stdlib.h> // exit()

#include "Strings.h" // class Strings

int main(void)

{

Strings

Line, // holds a line of input

InputFileName, // user-entered input file

OutputFileName; // user-entered output file

fstream

InStream, //input file stream

OutStream; //output file stream

// introductory message

cout << "\nThis program prompts for the name of an input file"

<< "\n\tand the name of an output file and makes a"

<< "\n\tcopy of the input file in the output file.\n";

cout << "\nPlease enter the name of the input file: ";

InputFileName.GetLine(cin); // get name of input file

InStream(InputFileName, ios::in); // open it for input

if (InStream.fail()) // check that it worked

{

cerr << "\n*** Unable to open file '"

<< InputFileName << "' !\n";

exit (1);

}

cout << "\nPlease enter the name of the output file: ";

OutputFileName.GetLine(cin); // get name of output file

OutStream(OutputFileName, ios::out); // open it for output...

if (OutStream.fail()) // checking, as always

{

cerr << "\n*** Unable to open file '"

<< OutputFileName << "' !\n";

exit (1);

}

Line.GetLine(InStream); // read the first line

while (!InStream.eof()) // while not end-of-file

{

OutStream << Line << endl; // write the line

Line.GetLine(InStream); // read the next line

} // end while

InStream.close(); // close input and output files

OutStream.close();

cout << "\nCopy completed.\n"; // user feedback

return 0; // successful termination

}

-Why do we have to write 'endl'?

exercises:

-count # of lines in a file, using strings/string functions

-count # of words in a file, where a word is any string terminated by any whitespace, using strings/string functions

More String operations/functions

-String Length -
-
member function Length() returns number of elements in the string:
x=MyString.Length();
-note that to find the position (element number) of the last element, use MyString.Length()-1

-Subscript operator -
- Previous variable data objects (int, double, etc) are called scalar, to indicate they store single values
-Objects of the Strings class can be thought of as containing a series of scalar values
-Each element in the string is a separate scalar entity, and can be accessed and manipulated like any other character variable
-To access any particular element, use the subscript operator [ ]
-e.g.:
MyString = "Buzz Lightyear";
cout << MyString[0]; //prints 'B'
MyString[0] = 'F'; //makes "Fuzz Lightyear"
MyString[1] = MyString[6]; //makes "Fizz Lightyear"

-e.g. (what does this do?)
for (x=MyString.Length()-1; x >= 0; x--)
cout << MyString[x];

-Note that the subscript operator performs range checking, so that an attempt to access a string with an invalid index value will generate a run-time error (OTHER STRING PACKAGES MAY NOT DO THIS!!)

- Assignment operator -
-The C++ assignment operator '=' is overloaded to work with string objects
-e.g.,
MyString = "Marvin the Martian";
YourString = MyString;
MyString = "This is easy!";
HerString = HisString = MyString;

-Relational operators
-The standard relational operators (==, !=, <, >, <=, >=) are overloaded to work with string objects
-e.g.,
given:

Name1 = "Jane";
Name2 = "James";
then:
Name1 < Name2 false (m < n)
Name1 > Name2 true
Name1 != Name2 true

Name1 == Name2 false

Name1 <= Name2 false

Name1 >= Name2 true

what if Name2 = "Janeway"?

then Name1 < Name2 is true (shorter)

-Concatenation
-the act of joining two strings into one (attaching one to the end of the other, i.e. appending)
-it makes a longer string from two shorter ones
-the ampersand operator & is overloaded to perform this
-e.g.,
First = "Buzz ";
Last = "Lightyear";
Whole = First & Last; //"Buzz Lightyear" (note space in "Buzz "
Whole = First & "Q. " & Last; //"Buzz Q. Lightyear"

-Substring operation
-used to "extract" a portion of the string (substring)
-provide two indices: first and last, and the elements from first to last are extracted
-produces another object of type Strings
-performs range checking to ensure that first and last are valid indices and that first <= last
-DOES NOT CHANGE ORIGINIAL STRING
-e.g.,
Str1 = "Buzz Lightyear";
Str2 = Str1(6,10); //str2 = "Light"

-Substring replacement operation
-The member function replace() is used to alter the contents of a string, by replacing a given set of elements by a new one
-Can replace a substring by a longer or shorter one, so that the length of the original string may change after a replace operation
-This function returns true (1) if the replacement was successful, false (0) otherwise
-Takes 3 parameters: first index, last index (substring to be replaced), new substring (to replace old substring)
-range checking is performed
e.g.,
Name1 = "Marvin the Martian"; //length =18
Name1.Replace(0,5,"Marty"); //"Marty the Martian", length=17
Name1.Replace(11,17,"Marvelous"); //"Marty the Marvelous", length = 19
Name1.Replace(0,0,"P"); //"Party the Marvelous", length = 19

Substring Deletion operation
-The member function Delete() cuts a substring from the given string, making it shorter
-Takes two parameters, first and last (the indices of the substring to delete)
-performs range checking
-returns true if successful, false if not
-e.g.,
Name = "Marvin the Martian";
Name.Delete(7,10); //"Marvin Martian" (deleted extra space)

Substring Insertion operation
-The member function Insert() performs the inverse of Delete(), by inserting a substring at a particular location, thereby making original string longer
-Takes two parameters: the substring and the index of insertion point
-Range checking is performed on the insertion index value
-Returns true if successful, false otherwise
-e.g.,
String1 = "World Web"; //length = 9
String1.Insert("Wide ",5); //"World Wide Web", length=14

Substring Pattern Matching
-A "find" operation - finds location of substring in original string
-"matches" the exact "pattern" of characters (case, etc.)
-Finds first occurrence of the substring
-returns -1 if substring not in original
-e.g.,
MyString = "First comes practice, then comes the game.";

cout << "Location of 'First' : " << MyString.Position("First")<<endl;

//location = 0

cout << "Location of 'first' : " << MyString.Position("first")<<endl;

//location = -1

cout << "Location of 'the' : " << MyString.Position("the")<<endl;

//location = 22

cout << "Location of 'then' : " << MyString.Position("then")<<endl;

//location = 22

cout << "Location of 'the ' : " << MyString.Position("the ")<<endl;

//location = 33

cout << "Location of '.' : " << MyString.Position(".")<<endl;

//location = 41

-Note that to be safe, you should check that the location was found, before using the index returned, else you could get a possible run-time error:
Location = MyString.Position(something);
cout << MyString[Location]; //possible run-time error, if location = -1

-Do this instead:
Location = MyString.Position(something);
if (Location < 0)
cout << something << " was not found in string" << endl;
else

process using valid location

Numeric conversion operations
-Three member functions to convert strings of digits into valid numeric objects
-Double()- to convert a string of digits into a double
-Long()- to convert a string of digits into a long (int)
-Unsigned()-to convert a string of digits into an unsigned int
-All three will skip leading whitespace in the string, searching for a digit or sign character
-All three stop when encountering a valid stop character for their type (as >> operator does)
-All three return 0 if conversion was impossible (i.e, encountered a non-digit before a digit, or, in the case of unsigned, encountered a minus sign)
-e.g.,
MyString = "3.14159";
x = MyString.Double(); //x = 3.14159 (x is type double)
y = MyString.Long(); //y=3 (y is type long)
z = MyString.Unsigned(); //z=3 (y is type unsigned)
-if MyString = "-3.14159"
x = MyString.Double(); //x = -3.14159 (x is type double)
y = MyString.Long(); //y=-3 (y is type long)
z = MyString.Unsigned(); //z=0 (y is type unsigned)

Passing strings as parameters


-if a string is very long, you may want to pass it as a reference parameter, (with &), even if you're not going to change it in that function

-to protect such a string from accidentally being changed, you can pass it as a constant reference parameter, which will produce a compile-time error if a modification is attempted:

void PrintString(const Strings& LongString)

etc.