Absolute C++ (phần 10) pot

40 436 0
Absolute C++ (phần 10) pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

360 Strings leaving the length the same as before. Assume this code fragment is embedded in an otherwise complete and correct program. Answer the questions following this code fragment. int index = 0; while (ourString[index] != ’\0’) { ourString[index] = ’X’; index++; } a. Explain how this code can destroy the contents of memory beyond the end of the array. b. Modify this loop to protect against inadvertently changing memory beyond the end of the array. 10. Write code using a library function to copy the string constant "Hello" into the string variable declared below. Be sure to #include the necessary header file to get the declara- tion of the function you use. char aString[10]; 11. What string will be output when this code is run? (Assume, as always, that this code is embedded in a complete, correct program.) char song[10] = "I did it "; char franksSong[20]; strcpy ( franksSong, song ); strcat ( franksSong, "my way!"); cout << franksSong << endl; 12. What is the problem (if any) with this code? char aString[20] = "How are you? "; strcat(aString, "Good, I hope."); ■ C-STRING INPUT AND OUTPUT C-strings can be output using the insertion operator, <<. In fact, we have already been doing so with quoted strings. You can use a C-string variable in the same way. For example, cout << news << " Wow.\n"; where news is a C-string variable. It is possible to fill a C-string variable using the input operator >>, but there is one thing to keep in mind. As for all other types of data, all whitespace (blanks, tabs, and 09_CH09.fm Page 360 Wednesday, August 13, 2003 1:04 PM An Array Type for Strings 361 line breaks) are skipped when C-strings are read this way. Moreover, each reading of input stops at the next space or line break. For example, consider the following code: char a[80], b[80]; cout << "Enter some input:\n"; cin >> a >> b; cout << a << b << "END OF OUTPUT\n"; When embedded in a complete program, this code produces a dialogue like the fol- lowing: Enter some input: Do be do to you! DobeEND OF OUTPUT The C-string variables a and b each receive only one word of the input: a receives the C-string value "Do" because the input character following Do is a blank; b receives "be" because the input character following be is a blank. If you want your program to read an entire line of input, you can use the extraction operator, >>, to read the line one word at a time. This can be tedious and it still will not read the blanks in the line. There is an easier way to read an entire line of input and place the resulting C-string into a C-string variable: Just use the predefined member function getline, which is a member function of every input stream (such as cin or a file input stream). The function getline has two arguments. The first argument is a C-string variable to receive the input and the second is an integer that typically is the declared size of the C-string variable. The second argument specifies the maximum number of array elements in the C-string variable that getline will be allowed to fill with characters. For example, consider the following code: char a[80]; cout << "Enter some input:\n"; cin.getline(a, 80); cout << a << "END OF OUTPUT\n"; When embedded in a complete program, this code produces a dialogue like the fol- lowing: Enter some input: Do be do to you! Do be do to you!END OF OUTPUT With the function cin.getline, the entire line is read. The reading ends when the line ends, even though the resulting C-string may be shorter than the maximum number of characters specified by the second argument. getline 09_CH09.fm Page 361 Wednesday, August 13, 2003 1:04 PM 362 Strings When getline is executed, the reading stops after the number of characters given by the second argument has been filled in the C-string array, even if the end of the line has not been reached. For example, consider the following code: char shortString[5]; cout << "Enter some input:\n"; cin.getline(shortString, 5); cout << shortString << "END OF OUTPUT\n"; When embedded in a complete program, this code produces a dialogue like the following: Enter some input: dobedowap dobeEND OF OUTPUT Notice that four, not five, characters are read into the C-string variable shortString, even though the second argument is 5. This is because the null character ’\0’ fills one array position. Every C-string is terminated with the null character when it is stored in a C-string variable, and this always consumes one array position. The C-string input and output techniques we illustrated for cout and cin work the same way for input and output with files. The input stream cin can be replaced by an input stream that is connected to a file. The output stream cout can be replaced by an output stream that is connected to a file. (File I/O is discussed in Chapter 12.). input/output with files getline The member function getline can be used to read a line of input and place the string of charac- ters on that line into a C-string variable. S YNTAX cin.getline( String_Var , Max_Characters + 1); One line of input is read from the stream Input_Stream and the resulting C-string is placed in String_Var . If the line is more than Max_Characters long, only the first Max_Characters on the line are read. (The +1 is needed because every C-string has the null character ’\0’ added to the end of the C-string and thus the string stored in String_Var is one longer than the number of charac- ters read in.) E XAMPLE char oneLine[80]; cin.getline(oneLine, 80); As you will see in Chapter 12, you can use an input stream connected to a text file in place of cin. 09_CH09.fm Page 362 Wednesday, August 13, 2003 1:04 PM Character Manipulation Tools 363 Self-Test Exercises 13. Consider the following code (and assume it is embedded in a complete and correct pro- gram and then run): char a[80], b[80]; cout << "Enter some input:\n"; cin >> a >> b; cout << a << ’-’ << b << "END OF OUTPUT\n"; If the dialogue begins as follows, what will be the next line of output? Enter some input: The time is now. 14. Consider the following code (and assume it is embedded in a complete and correct pro- gram and then run): char myString[80]; cout << "Enter a line of input:\n"; cin.getline(myString, 6); cout << myString << "<END OF OUTPUT"; If the dialogue begins as follows, what will be the next line of output? Enter a line of input: May the hair on your toes grow long and curly. Character Manipulation Tools They spell it Vinci and pronounce it Vinchy; foreigners always spell better than they pronounce. Mark Twain, The Innocents Abroad Any form of string is ultimately composed of individual characters. Thus, when doing string processing it is often helpful to have tools at your disposal to test and manipulate individual values of type char. This section is about such tools. ■ CHARACTER I/O All data is input and output as character data. When your program outputs the number 10, it is really the two characters ’1’ and ’0’ that are output. Similarly, when the user wants to type in the number 10, he or she types in the character ’1’ followed by the character ’0’. Whether the computer interprets this "10" as two characters or as the 9.2 09_CH09.fm Page 363 Wednesday, August 13, 2003 1:04 PM 364 Strings number 10 depends on how your program is written. But, however your program is written, the computer hardware is always reading the characters ’1’ and ’0’, not the number 10. This conversion between characters and numbers is usually done automat- ically so that you need not think about such details; however, sometimes all this auto- matic help gets in the way. Therefore, C++ provides some low-level facilities for input and output of character data. These low-level facilities include no automatic conver- sions. This allows you to bypass the automatic facilities and do input/output in abso- lutely any way you want. You could even write input and output functions that can read and write int values in Roman numeral notation, if you wanted to be so perverse. ■ THE MEMBER FUNCTIONS get AND put The function get allows your program to read in one character of input and store it in a variable of type char. Every input stream, whether it is an input-file stream or the stream cin, has get as a member function. We will describe get here as a member func- tion of the object cin. (When we discuss file I/O in Chapter 12 we will see that it behaves exactly the same for input-file streams as it does for cin). Before now, we have used cin with the extraction operator, >>, in order to read a character of input (or any other input, for that matter). When you use the extraction operator >>, some things are done for you automatically, such as skipping over whitespace. But sometimes you do not want to skip over whitespace. The member function cin.get reads the next input character no matter whether the character is whitespace or not. The member function get takes one argument, which should be a variable of type char. That argument receives the input character that is read from the input stream. For example, the following will read in the next input character from the keyboard and store it in the variable nextSymbol: char nextSymbol; cin.get(nextSymbol); It is important to note that your program can read any character in this way. If the next input character is a blank, this code will read the blank character. If the next character is the newline character ’\n’ (that is, if the program has just reached the end of an input line), then the above call to cin.get will set the value of nextSymbol equal to ’\n’. For example, suppose your program contains the following code: char c1, c2, c3; cin.get(c1); cin.get(c2); cin.get(c3); and suppose you type in the following two lines of input to be read by this code: AB CD cin.get reading blanks and ’\n’ 09_CH09.fm Page 364 Wednesday, August 13, 2003 1:04 PM Character Manipulation Tools 365 The value of c1 is set to ’A’, the value of c2 is set to ’B’, and the value of c3 is set to ’\n’. The variable c3 is not set equal to ’C’. One thing you can do with the member function get is to have your program detect the end of a line. The following loop will read a line of input and stop after passing the newline character ’\n’. Any subsequent input will be read from the beginning of the next line. For this first example, we have simply echoed the input, but the same tech- nique would allow you to do whatever you want with the input. cout << "Enter a line of input and I will echo it:\n"; char symbol; do { cin.get(symbol); cout << symbol; } while (symbol != ’\n’); cout << "That’s all for this demonstration.\n"; This loop will read any line of input and echo it exactly, including blanks. The follow- ing is a sample dialogue produced by this code: Enter a line of input and I will echo it: Do Be Do 1 2 34 Do Be Do 1 2 34 That’s all for this demonstration. Notice that the newline character ’\n’ is both read and output. Since ’\n’ is output, the string that begins with the word "That’s" is on a new line. The member function put is analogous to the member function get except that it is used for output rather than input. The function put allows your program to output one character. The member function cout.put takes one argument, which should be an expression of type char, such as a constant or a variable of type char. The value of the argument is output to the screen when the function is called. For example, the follow- ing will output the letter ’a’ to the screen: cout.put(’a’); '\n' AND "\n" ’\n’ and "\n" sometimes seem like the same thing. In a cout statement, they produce the same effect, but they cannot be used interchangeably in all situations. ’\n’ is a value of type char and can be stored in a variable of type char. On the other hand, "\n" is a string that happens to be made up of exactly one character. Thus, "\n" is not of type char and cannot be stored in a variable of type char. detecting the end of an input line put 09_CH09.fm Page 365 Wednesday, August 13, 2003 1:04 PM 366 Strings Example The function cout.put does not allow you to do anything you could not do with the insertion operator <<, but we include it for completeness. (When we discuss file I/O in Chapter 12, we will see that put can be used with an output stream connected to a text file and is not restricted to being used only with cout.) If your program uses cin.get or cout.put, then just as with other uses of cin and cout, your program should include one of the following (or something similar): #include <iostream> using namespace std; or #include <iostream> using std::cin; using std::cout; C HECKING I NPUT U SING A N EWLINE F UNCTION The function getInt in Display 9.2 asks the user if the input is correct and asks for a new value if the user says the input is incorrect. The program in Display 9.2 is just a driver program to test the function getInt, but the function, or one very similar to it, can be used in just about any kind of program that takes its input from the keyboard. Notice the call to the function newLine( ). The function newLine reads all the characters on the remainder of the current line but does nothing with them. This amounts to discarding the remain- der of the line. Thus, if the user types in No, then the program reads the first letter, which is N, and T HE M EMBER F UNCTION get The function get can be used to read one character of input. Unlike the extraction operator, >>, get reads the next input character, no matter what that character is. In particular, get will read a blank or the newline character, ’\n’, if either of these are the next input character. The function get takes one argument, which should be a variable of type char. When get is called, the next input character is read and the argument variable has its value set equal to this input character. E XAMPLE char nextSymbol; cin.get(nextSymbol); As we will see in Chapter 12, if you wish to use get to read from a file, you use an input-file stream in place of the stream cin. newLine( ) 09_CH09.fm Page 366 Wednesday, August 13, 2003 1:04 PM Character Manipulation Tools 367 then calls the function newLine, which discards the rest of the input line. This means that if the user types 75 on the next input line, as shown in the sample dialogue, the program will read the number 75 and will not attempt to read the letter o in the word No. If the program did not include a call to the function newLine, then the next item read would be the o in the line containing No instead of the number 75 on the following line. Display 9.2 Checking Input (part 1 of 2) 1 //Program to demonstrate the functions newLine and getInput 2 #include <iostream> 3 using namespace std; 4 void newLine( ); 5 //Discards all the input remaining on the current input line. 6 //Also discards the ’\n’ at the end of the line. 7 void getInt(int& number); 8 //Sets the variable number to a 9 //value that the user approves of. 10 int main( ) 11 { 12 int n; 13 getInt(n); 14 cout << "Final value read in = " << n << endl 15 << "End of demonstration.\n"; 16 return 0; 17 } 18 //Uses iostream: 19 void newLine( ) 20 { 21 char symbol; 22 do 23 { 24 cin.get(symbol); 25 } while (symbol != ’\n’); 26 } 27 //Uses iostream: 28 void getInt(int& number) 29 { 09_CH09.fm Page 367 Wednesday, August 13, 2003 1:04 PM 368 Strings Pitfall U NEXPECTED ’\n’ IN I NPUT When using the member function get you must account for every character of input, even the characters you do not think of as being symbols, such as blanks and the newline character, ’\n’. A common problem when using get is forgetting to dispose of the ’\n’ that ends every input line. If there is a newline character in the input stream that is not read (and usually discarded), then when your program next expects to read a “real” symbol using the member function get, it will instead read the character ’\n’. To clear the input stream of any leftover ’\n’, you can use the function newLine, which we defined in Display 9.2 (or you can use the function ignore, which we discuss in the next subsection). Let’s look at a concrete example. It is legal to mix the different forms of cin. For example, the following is legal: cout << "Enter a number:\n"; int number; cin >> number; cout << "Now enter a letter:\n"; char symbol; cin.get(symbol); Display 9.2 Checking Input (part 2 of 2) 30 char ans; 31 do 32 { 33 cout << "Enter input number: "; 34 cin >> number; 35 cout << "You entered " << number 36 << " Is that correct? (yes/no): "; 37 cin >> ans; 38 newLine( ); 39 } while ((ans == ’N’) || (ans == ’n’)); 40 } S AMPLE D IALOGUE Enter input number: 57 You entered 57 Is that correct? (yes/no): No No No! Enter input number: 75 You entered 75 Is that correct? (yes/no): yes Final value read in = 75 End of demonstration. 09_CH09.fm Page 368 Wednesday, August 13, 2003 1:04 PM Character Manipulation Tools 369 However, this can produce problems, as illustrated by the following dialogue: Enter a number: 21 Now enter a letter: A With this dialogue, the value of number will be 21 as you expect. However, if you expect the value of the variable symbol to be ’A’, you will be disappointed. The value given to symbol is ’\n’. After reading the number 21, the next character in the input stream is the newline character, ’\n’, and so that is read next. Remember, get does not skip over line breaks and spaces. (In fact, depending on what is in the rest of the program, you may not even get a chance to type in the A. Once the variable symbol is filled with the character ’\n’, the program proceeds to what- ever statement is next in the program. If the next statement sends output to the screen, the screen will be filled with output before you get a chance to type in the A.) The following rewriting of the above code will cause the above dialogue to fill the variable num- ber with 21 and fill the variable symbol with ’A’: cout << "Enter a number:\n"; int number; cin >> number; cout << "Now enter a letter:\n"; char symbol; cin >> symbol; Alternatively, you can use the function newLine, defined in Display 9.2, as follows: cout << "Enter a number:\n"; int number; cin >> number; newLine( ); cout << "Now enter a letter:\n"; char symbol; cin.get(symbol); As this second rewrite indicates, you can mix the two forms of cin and have your program work correctly, but it does require some extra care. As a third alternative, you could use the function ignore, which we discuss in the next subsection. ■ THE putback , peek , AND ignore MEMBER FUNCTIONS Sometimes your program needs to know the next character in the input stream. How- ever, after reading the next character, it might turn out that you do not want to process 09_CH09.fm Page 369 Wednesday, August 13, 2003 1:04 PM [...]... following output: Ahh -do-be-do Pitfall toupper AND tolower RETURN int VALUES In many ways C++ considers characters to be whole numbers, similar to the numbers of type int Each character is assigned a number When the character is stored in a variable of type char, it is this number that is placed in the computer’s memory In C++ you can use a value of type char as a number, for example, by placing it in a variable... that you the programmer keep track of all the low-level details of how the C-strings are stored in memory This is a lot of extra work and a source of programmer errors The ANSI/ISO standard for C++ specified that C++ must now also have a class string that allows the programmer to treat strings as a basic data type without needing to worry about implementation details This section introduces you to this... 378 converting C-string constants to the type string Strings C++ must do a lot of work to allow you to concatenate strings in this simple and natural fashion The string constant "I love " is not an object of type string A string constant like "I love " is stored as a C-string (in other words, as a null-terminated array of characters) When C++ sees "I love " as an argument to +, it finds the definition... + and produces a string object as the value returned Of course, there is also the overloading you expect, with the type string for both operands C++ did not really need to provide all those overloading cases for + If these overloadings were not provided, C++ would look for a constructor that can perform a type conversion to convert the C-string "I love " to a value for which + did apply In this case,... (! isdigit(next)) && (next != ’\n’) ); cout > s2; This kind of use of getline seems to have been designed for use in a C++ quiz show rather than to meet any actual programming need, but it can come in handy sometimes Pitfall MIXING cin >> variable; AND getline Take care in mixing input using cin >> variable; with input... 384 Wednesday, August 13, 2003 1:04 PM 384 Strings Other baffling problems can appear with programs that use cin with both >> and getline Moreover, these problems can come and go as you move from one C++ compiler to another When all else fails, or if you want to be certain of portability, you can resort to character-by-character input using cin.get These problems can occur with any of the versions... position pos 387 09_CH09.fm Page 388 Wednesday, August 13, 2003 1:04 PM 388 Strings = AND == ARE DIFFERENT FOR strings AND C-STRINGS The operators =, ==, !=, , =, when used with the standard C++ type string, produce results that correspond to our intuitive notion of how strings compare They do not misbehave as they do with C-strings, as we discussed in Section 9.1 Example PALINDROME TESTING . This is a lot of extra work and a source of programmer errors. The ANSI/ISO standard for C++ specified that C++ must now also have a class string that allows the programmer to treat strings as a. with the type string for both operands. C++ did not really need to provide all those overloading cases for +. If these over- loadings were not provided, C++ would look for a constructor that can. stored in a variable of type char, it is this number that is placed in the computer’s memory. In C++ you can use a value of type char as a number, for example, by placing it in a variable of

Ngày đăng: 07/07/2014, 05:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan