Class 8 Slides The apstring class APString Constructors/Destructor APString accessor methods APString indexing APString assignment operators APString relational operators APString concatenation APString input/output operators Program: generating acronyms A more robust version of the acronym function Lab: Palindrome check File Input/Output Performing input and output on opened files Checking for errors and end-of-file Silly sample program that doesn't do anything particularly useful Lab: Concatenate files -------------------------------------------------------------------------------- The apstring class Allows storage and manipulation of character strings Allows index subscripting and range checking Not a template class, since it only contains characters, not values of other types As with built-in arrays, an apstring starts subscripts from 0 Defines several useful methods and overloaded operators How to use in a program You must include the header file apstring.h in any source file that uses apstring. Then you're free to declare variables of type apstring. You must also include (using Add Node) the file apstring.cpp in your project. You can find it in the C:\Bc45\include directory on the lab machines. -------------------------------------------------------------------------------- APString Constructors/Destructor Constructor/destructor prototypes: apstring(); // default constructor apstring(const char* s); // construct from string literal apstring(const apstring& str); // copy constructor ~apstring(); // destructor Examples of use: apstring aName; // Default constructor sets string to empty (zero-length) string "". apstring myName("Jennifer"); apstring myName = "Jennifer"; // Equivalent. Both call string literal constructor. apstring myNameAgain(myName); apstring myNameAgain = myName; // Equivalent. Both call copy constructor. -------------------------------------------------------------------------------- APString accessor methods Accessor method prototypes: // accessors int length() const; // number of characters in string int find(const apstring& str) const; // index of first occurrence of str int find(char ch) const; // index of first occurrence of ch apstring substr(int pos, int len) const; // substring of len chars, starting at pos const char* c_str() const; // explicit conversion to C string Examples of use: int len = myName.length(); // sets len to 8 int pos1 = myName.find('n'); // sets pos1 to 2 int pos2 = myName.find('q'); // sets pos2 to npos if (pos2 == npos) cout << "No q's in my name." << endl; int pos3 = myName.find("if"); // sets pos3 to 4 apstring nickname = myName.substring(0, 4); // sets nickname to "Jenn" apstring lastThree = myName.substring(myName.length() - 3, 3); // sets lastThree to "fer" -------------------------------------------------------------------------------- APString indexing You can use subscripts to retrieve/change individual characters from the string. As with apvector, subscripts start from 0. The overloaded subscript operator also provides range checking, so an out-of-range subscript will cause your program to abort running. // indexing char operator[](int k) const; // indexing with range checking char& operator[](int k); // indexing with range checking Examples of use: apstring a = "C++ is fun!"; apstring b = a; int n = a.length(); for (int i = 0; i < n; i++) b[n - i - 1] = a[i]; for (i = 0; i < n; i++) a[i] = toupper(a[i]); // toupper is in the ctype.h library -------------------------------------------------------------------------------- APString assignment operators The assignment operators are defined as members of the apstring class (because they are required to be). // assignment const apstring& operator=(const apstring& str); // assign apstring object const apstring& operator=(const char* s); // assign C string literal const apstring& operator=(char ch); // assign single character Examples of use: apstring aStr, anotherStr; aStr = "hello"; anotherStr = 'x'; aStr = anotherStr; -------------------------------------------------------------------------------- APString relational operators The relational operators do ASCII character string comparison. Remember that in ASCII, the upper case characters come before all the lower case characters. // comparison operators bool operator ==(const apstring& lhs, const apstring& rhs); bool operator !=(const apstring& lhs, const apstring& rhs); bool operator <(const apstring& lhs, const apstring& rhs); bool operator <=(const apstring& lhs, const apstring& rhs); bool operator >(const apstring& lhs, const apstring& rhs); bool operator >=(const apstring& lhs, const apstring& rhs); Examples of use: apstring str1 = "fred"; apstring str2 = "joe"; apstring str3 = "freddie"; apstring str4 = "FRED"; apstring str5 = "fred"; str1 < str3 // TRUE str1 < str2 // TRUE str1 < str4 // FALSE str1 > str4 // TRUE str1 != str2 // TRUE str1 == str4 // FALSE str1 == str5 // TRUE -------------------------------------------------------------------------------- APString concatenation You can "add" two strings together to produce one longer string. // modifiers const apstring& operator +=(const apstring& str); // append str const apstring& operator +=(char ch); // append char // concatenation operator + apstring operator +(const apstring& lhs, const apstring& rhs); apstring operator +(char ch, const apstring& str); apstring operator +(const apstring& str, char ch); Examples of use: apstring word1 = "cat"; apstring word2 = "nap"; apstring word3; word3 = word1 + "cher"; // word3 is "catcher" word3 = word1 + word2; // word3 is "catnap" word2 += 'e'; // word2 is "nape" word1 = 's' + word1 + ", " + word1 + '!'; // word1 is "scat, cat!" -------------------------------------------------------------------------------- APString input/output operators The standard input and output operators are overloaded. The input operator >>> reads one word from input; a space, tab, or carriage return marks the end of a word. There is also an input method getline for reading an entire line, up to, but not including, the carriage return. // I/O functions ostream& operator <<(ostream& os, const apstring& str); istream& operator>>(istream& is, apstring& str); istream& getline(istream& is, apstring& str); Examples of use: apstring greeting = "Hi, there!"; apstring word1, word2, word3; cout << greeting << endl; cin >> word1 >> word2 >> word3; Input line: one two three word1 = "one", word2 = "two", word3 = "three" apstring aLine; getline(cin, aLine); Input line: That's all, folks! aLine = "That's all, folks!" -------------------------------------------------------------------------------- Program: generating acronyms int main() { apstring str; cout << "This program generates acronyms." << endl; cout << "End the program by entering a blank line" << endl; while (true) { cout << "Enter string: "; getline(cin, str); if (str == "") break; cout << "The acronym is " << Acronym(str) << "." << endl; } return 0; } apstring Acronym(apstring str) // Precondition: str is non-empty, with no spaces at the beginning or end // Postcondition: Returns string containing first character of each word in str { int i, n = str.length(); apstring acronym; acronym = str[0]; for (i = 0; i < n; i++) { if (str[i] == ' ') acronym += str[i + 1]; } return acronym; } -------------------------------------------------------------------------------- A more robust version of the acronym function This version allows for there being spaces at the beginning or end of the string, and makes sure the acronym includes only letters, no numbers or other non-alphabetic characters. It uses another function from ctype.h, isalpha, which returns true if a character is a lower or upper case letter. apstring Acronym(apstring str) // Precondition: str is non-empty // Postcondition: Returns string containing first alphabetic character // of each word in str { int i, n = str.length(); char c; bool seeking_first_letter = true; apstring acronym = ""; for (i = 0; i < n; i++) { c = str[i]; if (seeking_first_letter && isalpha(c)) { acronym += str[i]; seeking_first_letter = false; } else if (!seeking_first_letter && (c == ' ' || c == '-') { seeking_first_letter = true; } } return acronym; } -------------------------------------------------------------------------------- Lab: (a) Write a function with the prototype bool IsPalindrome(const apstring& str) that returns true if the string reads the same forwards and backwards (for instance, "madam" or "noon"). Write a looping main program like that for the Acronym program to test operation. (b) Adjust your program so that it can determine if the alphabetic characters in a string which may also contain non-alphabetic characters are palindromic. For instance, "A man, a plan, a canal - Panama!" is palindromic. To do so, write two additional functions which can be called in IsPalindrome: apstring ConvertToLowerCase(apstring str); // Precondition: str is any apstring // Postcondition: returns a copy of str in which all of the // upper case letters have been converted to lower case apstring AlphaChars(apstring str); // Precondition: str is any apstring // Postcondition: returns a copy of str containing only the // alphabetic characters You will want to use functions from ctype.h. -------------------------------------------------------------------------------- File Input/Output You can read from and write to files in a very similar manner to reading from the keyboard and writing to the screen. However, the classes used for file I/O are different from those used for console I/O. The console I/O classes are istream and ostream. The file I/O classes are ifstream and ofstream. To use them, you must include fstream.h. You can then declare class instance variables of type ifstream and ofstream. To "attach" a stream to an actual file, you use the open method, as follows. ifstream inputFile; ofstream outputFile; inputFile.open("Infile.txt"); outputFile.open("C:\\temp\\Outfile.txt"); Opening a file for output that already exists will overwrite the file, so be careful! When you are done using a particular file, you should always close the file explicitly, like so: inputFile.close(); outputFile.close(); Note: Borland 4.5 expects DOS 8.3 short file names, not Windows long file names. -------------------------------------------------------------------------------- Performing input and output on opened files Once you have your file open, you can perform input or output using the << and >> operators, just as you would with cin and cout. int n; apstring str; inputFile >> n >> str; outputFile << str << n; You can also use the output formatting methods (precision, setw, setf) on an ofstream. double f = 123.4567; outputFile.precision(1); outputFile.setf(ios::fixed); outputFile.setf(ios::showpoint); outputFile << setw(10) << f; If "infile.txt" contains: Then "C:\temp\Outfile.txt" will contain: 23 Hello! Hello! 23 123.5 -------------------------------------------------------------------------------- Checking for errors and end-of-file To make sure that your open operation was successful, use the fail method, which returns true if the operation failed. An input file open will fail if the file doesn't exist or can't be read. An output file open might fail if you don't have write permission for a directory or if there is not enough drive space available. You should call the fail method immediately after the call to open. inputFile.open("nofile.txt"); if (inputFile.fail()) cout << "File not opened successfully." << endl; To tell when you have reached the end of an input file you are reading, use the method eof, which returns true if the end of the file has been reached. char c; while (!inputFile.eof()) inputFile >> c; -------------------------------------------------------------------------------- Silly sample program that doesn't do anything particularly useful int main() { ifstream inputFile; ofstream outputFile; inputFile.open("A:\\temp\\Poem.txt"); outputFile.open("A:\\temp\\Outfile.txt"); apstring word1, word2; while (!inputFile.eof()) { inputFile >> word1 >> word2; if (word1 < word2) outputFile << word1 << " " << word2 << endl; else outputFile << word2 << " " << word1 << endl; } inputFile.close(); outputFile.close(); return 0; } -------------------------------------------------------------------------------- Lab: Write a program that allows the user to enter the names of two input files to be found in A:\temp or C:\temp, then writes an output file containing all the words in the first file (separated by line feeds) followed by all the words in the second file.