In addition to using the >> and << operators a variety of other member functions are available in the istream and ostream classes. They are referred to as unformatted stream functions because they do not skip whitespaces, newlines etc. The following is only a small subset of member functions. For a comprehensive list of all member functions of the istream and ostream classes, refer to your text book or C++ reference
manual istream& get(char& c); // reads one character, without ignoring whitespace // terminates when '\n' is encountered int get(); // Extracts a character and returns it. Returns EOF if end of // file (^d) is encountered istream& get(char* ptr , int len, char delim='\n'); // Extracts characters until delim is found or // len-1 number of characters have been extracted // Leaves delim in the stream istream& getline(char* ptr , int len, char delim='\n'); // Extracts characters until delim is found or // len-1 number of characters have been extracted // Extracts delim from the stream but does not put in ptr istream& ignore(int num=1 , char delim=EOF); // Extracts and discards characters until delim // is read or num characters have been extracted istream& eof(); // returns TRUE (a non-negative integer) if stream has ended Show
C++, like C, has no built-in input or output statements. Instead, I/O facilities are provided by a library. The C++ compiler provides both the classic implementation and the ISO standard implementation of the iostream classes.
This chapter provides an introduction to the classic iostream library and provides examples of its use. This chapter does not provide a complete description of the iostream library. See the iostream library man pages for more details. To access the classic iostream man pages type: example% man -s 3CC4 name 14.1 Predefined iostreamsThere are four predefined iostreams:
The predefined iostreams are fully buffered, except for cerr. See Section 14.3.1, Output Using iostream and Section 14.3.2, Input Using iostream. 14.2 Basic Structure of iostream InteractionBy including the iostream library, a program can use any number of input or output streams. Each stream has some source or sink, which may be one of the following:
A stream can be restricted to input or output, or a single stream can allow both input and output. The iostream library implements these streams using two processing layers.
Standard input, output, and error are handled by special class objects derived from class istream or ostream. The ifstream, ofstream, and fstream classes, which are derived from istream, ostream, and iostream respectively, handle input and output with files. The istrstream, ostrstream, and strstream classes, which are derived from istream, ostream, and iostream respectively, handle input and output to and from arrays of characters. When you open an input or output stream, you create an object of one of these types, and associate the streambuf member of the stream with a device or file. You generally do this association through the stream constructor, so you don't work with the streambuf directly. The iostream library predefines stream objects for the standard input, standard output, and error output, so you don't have to create your own objects for those streams. You use operators or iostream member functions to insert data into a stream (output) or extract data from a stream (input), and to control the format of data that you insert or extract. When you want to insert and extract a new data type--one of your classes--you generally overload the insertion and extraction operators. 14.3 Using the Classic iostream LibraryTo use routines from the classic iostream library, you must include the header files for the part of the library you need. The header files are described in the following table. TABLE 14-1 iostream Routine Header Files
You usually do not need all of these header files in your program. Include only the ones that contain the declarations you need. In compatibility mode (-compat[=4]), the classic iostream library is part of libC, and is linked automatically by the CC driver. In standard mode (the default), libiostream contains the classic iostream library. 14.3.1 Output Using iostreamOutput using iostream usually relies on the overloaded left-shift operator (<<) which, in the context of iostream, is called the insertion operator. To output a value to standard output, you insert the value in the predefined output stream cout. For example, given a value someValue, you send it to standard output with a statement like: The insertion operator is overloaded for all built-in types, and the value represented by someValue is converted to its proper output representation. If, for example, someValue is a float value, the << operator converts the value to the proper sequence of digits with a decimal point. Where it inserts float values on the output stream, << is called the float inserter. In general, given a type X, << is called the X inserter. The format of output and how you can control it is discussed in the ios(3CC4) man page. The iostream library does not support user-defined types. If you define types that you want to output in your own way, you must define an inserter (that is, overload the << operator) to handle them correctly. The << operator can be applied repetitively. To insert two values on cout, you can use a statement like the one in the following example: cout << someValue << anotherValue; The output from the above example will show no space between the two values. So you may want to write the code this way: cout << someValue << " " << anotherValue; The << operator has the precedence of the left shift operator (its built-in meaning). As with other operators, you can always use parentheses to specify the order of action. It is often a good idea to use parentheses to avoid problems of precedence. Of the following four statements, the first two are equivalent, but the last two are not. cout << a+b; // + has higher precedence than << cout << (a+b); cout << (a&y); // << has precedence higher than & cout << a&y; // probably an error: (cout << a) & y 14.3.1.1 Defining Your Own Insertion OperatorThe following example defines a string class: #include <stdlib.h> #include <iostream.h> class string { private: char* data; size_t size; public: // (functions not relevant here) friend ostream& operator<<(ostream&, const string&); friend istream& operator>>(istream&, string&); }; The insertion and extraction operators must in this case be defined as friends because the data part of the string class is private. ostream& operator<< (ostream& ostr, const string& output) { return ostr << output.data;} Here is the definition of operator<< overloaded for use with strings. cout << string1 << string2; operator<< takes ostream& (that is, a reference to an ostream) as its first argument and returns the same ostream, making it possible to combine insertions in one statement. 14.3.1.2 Handling Output ErrorsGenerally, you don't have to check for errors when you overload operator<< because the iostream library is arranged to propagate errors. When an error occurs, the iostream where it occurred enters an error state. Bits in the iostream's state are set according to the general category of the error. The inserters defined in iostream ignore attempts to insert data into any stream that is in an error state, so such attempts do not change the iostream's state. In general, the recommended way to handle errors is to periodically check the state of the output stream in some central place. If there is an error, you should handle it in some way. This chapter assumes that you define a function error, which takes a string and aborts the program. error is not a predefined function. See Section 14.3.9, Handling Input Errors for an example of an error function. You can examine the state of an iostream with the operator !,which returns a nonzero value if the iostream is in an error state. For example: if (!cout) error("output error"); There is another way to test for errors. The ios class defines operator void *(), so it returns a NULL pointer when there is an error. You can use a statement like: if (cout << x) return; // return if successful You can also use the function good, a member of ios: if (cout.good()) return; // return if successful The error bits are declared in the enum: enum io_state {goodbit=0, eofbit=1, failbit=2, badbit=4, hardfail=0x80}; For details on the error functions, see the iostream man pages. 14.3.1.3 FlushingAs with most I/O libraries, iostream often accumulates output and sends it on in larger and generally more efficient chunks. If you want to flush the buffer, you simply insert the special value flush. For example: cout << "This needs to get out immediately." << flush; flush is an example of a kind of object known as a manipulator, which is a value that can be inserted into an iostream to have some effect other than causing output of its value. It is really a function that takes an ostream& or istream& argument and returns its argument after performing some actions on it (see Section 14.7, Manipulators). 14.3.1.4 Binary OutputTo obtain output in the raw binary form of a value, use the member function write as shown in the following example. This example shows the output in the raw binary form of x. cout.write((char*)&x, sizeof(x)); The previous example violates type discipline by converting &x to char*. Doing so is normally harmless, but if the type of x is a class with pointers, virtual member functions, or one that requires nontrivial constructor actions, the value written by the above example cannot be read back in properly. 14.3.2 Input Using iostreamInput using iostream is similar to output. You use the extraction operator >> and you can string together extractions the way you can with insertions. For example: This statement gets two values from standard input. As with other overloaded operators, the extractors used depend on the types of a and b (and two different extractors are used if a and b have different types). The format of input and how you can control it is discussed in some detail in the ios(3CC4) man page. In general, leading whitespace characters (spaces, newlines, tabs, form-feeds, and so on) are ignored. 14.3.3 Defining Your Own Extraction OperatorsWhen you want input for a new type, you overload the extraction operator for it, just as you overload the insertion operator for output. Class string defines its extraction operator in the following code example:
The get function reads characters from the input stream istr and stores them in holder until maxline-1 characters have been read, or a new line is encountered, or EOF, whichever happens first. The data in holder is then null-terminated. Finally, the characters in holder are copied into the target string. By convention, an extractor converts characters from its first argument (in this case, istream& istr), stores them in its second argument, which is always a reference, and returns its first argument. The second argument must be a reference because an extractor is meant to store the input value in its second argument. 14.3.4 Using the char* ExtractorThis predefined extractor is mentioned here because it can cause problems. Use it like this: This extractor skips leading whitespace and extracts characters and copies them to x until it reaches another whitespace character. It then completes the string with a terminating null (0) character. Be careful, because input can overflow the given array. You must also be sure the pointer points to allocated storage. For example, here is a common error: char * p; // not initialized cin >> p; There is no telling where the input data will be stored, and it may cause your program to abort. 14.3.5 Reading Any Single CharacterIn addition to using the char extractor, you can get a single character with either form of the get member function. For example: char c; cin.get(c); // leaves c unchanged if input fails int b; b = cin.get(); // sets b to EOF if input fails
Here is a way to skip only blanks, stopping on a tab, newline, or any other character: int a; do { a = cin.get(); } while(a ==' '); 14.3.6 Binary InputIf you need to read binary values (such as those written with the member function write), you can use the read member function. The following example shows how to input the raw binary form of x using the read member function, and is the inverse of the earlier example that uses write. cin.read((char*)&x, sizeof(x)); 14.3.7 Peeking at InputYou can use the peek member function to look at the next character in the stream without extracting it. For example: if (cin.peek()!= c) return 0; 14.3.8 Extracting WhitespaceBy default, the iostream extractors skip leading whitespace. You can turn off the skip flag to prevent this from happening. The following example turns off whitespace skipping from cin, then turns it back on: cin.unsetf(ios::skipws); // turn off whitespace skipping ... cin.setf(ios::skipws); // turn it on again You can use the iostream manipulator ws to remove leading whitespace from the iostream, whether or not skipping is enabled. The following example shows how to remove the leading whitespace from iostream istr: 14.3.9 Handling Input ErrorsBy convention, an extractor whose first argument has a nonzero error state should not extract anything from the input stream and should not clear any error bits. An extractor that fails should set at least one error bit. As with output errors, you should check the error state periodically and take some action, such as aborting, when you find a nonzero state. The ! operator tests the error state of an iostream. For example, the following code produces an input error if you type alphabetic characters for input: #include <stdlib.h> #include <iostream.h> void error (const char* message) { cerr << message << "\n"; exit(1); } int main() { cout << "Enter some characters: "; int bad; cin >> bad; if (!cin) error("aborted due to input error"); cout << "If you see this, not an error." << "\n"; return 0; } Class ios has member functions that you can use for error handling. See the man pages for details. 14.3.10 Using iostreams With stdioYou can use stdio with C++ programs, but problems can occur when you mix iostreams and stdio in the same standard stream within a program. For example, if you write to both stdout and cout, independent buffering occurs and produces unexpected results. The problem is worse if you input from both stdin and cin, since independent buffering may turn the input into trash. To eliminate this problem with standard input, standard output and standard error, use the following instruction before performing any input or output. It connects all the predefined iostreams with the corresponding predefined stdio FILEs. Such a connection is not the default because there is a significant performance penalty when the predefined streams are made unbuffered as part of the connection. You can use both stdio and iostreams in the same program applied to different files. That is, you can write to stdout using stdio routines and write to other files attached to iostreams. You can open stdio FILEs for input and also read from cin so long as you don't also try to read from stdin. 14.4 Creating iostreamsTo read or write a stream other than the predefined iostreams, you need to create your own iostream. In general, that means creating objects of types defined in the iostream library. This section discusses the various types available. 14.4.1 Dealing With Files Using Class fstreamDealing with files is similar to dealing with standard input and standard output; classes ifstream, ofstream, and fstream are derived from classes istream, ostream, and iostream, respectively. As derived classes, they inherit the insertion and extraction operations (along with the other member functions) and also have members and constructors for use with files. Include the file fstream.h to use any of the fstreams. Use an ifstream when you only want to perform input, an ofstream for output only, and an fstream for a stream on which you want to perform both input and output. Use the name of the file as the constructor argument. For example, copy the file thisFile to the file thatFile as in the following example: ifstream fromFile("thisFile"); if (!fromFile) error("unable to open 'thisFile' for input"); ofstream toFile ("thatFile"); if (!toFile) error("unable to open 'thatFile' for output"); char c; while (toFile && fromFile.get(c)) toFile.put(c); This code:
14.4.1.1 Open ModeThe mode is constructed by or-ing bits from the enumerated type open_mode, which is a public type of class ios and has the definition: enum open_mode {binary=0, in=1, out=2, ate=4, app=8, trunc=0x10, nocreate=0x20, noreplace=0x40};
You can open a file for both input and output. For example, the following code opens file someName for both input and output, attaching it to the fstream variable inoutFile. fstream inoutFile("someName", ios::in|ios::out); 14.4.1.2 Declaring an fstream Without Specifying a FileYou can declare an fstream without specifying a file and open the file later. For example, the following creates the ofstream toFile for writing. ofstream toFile; toFile.open(argv[1], ios::out); 14.4.1.3 Opening and Closing FilesYou can close the fstream and then open it with another file. For example, to process a list of files provided on the command line: ifstream infile; for (char** f = &argv[1]; *f; ++f) { infile.open(*f, ios::in); ...; infile.close(); } 14.4.1.4 Opening a File Using a File DescriptorIf you know a file descriptor, such as the integer 1 for standard output, you can open it like this: ofstream outfile; outfile.attach(1); When you open a file by providing its name to one of the fstream constructors or by using the open function, the file is automatically closed when the fstream is destroyed (by a delete or when it goes out of scope). When you attach a file to an fstream, it is not automatically closed. 14.4.1.5 Repositioning Within a FileYou can alter the reading and writing position in a file. Several tools are supplied for this purpose.
enum seek_dir {beg=0, cur=1, end=2}; For example, given an fstream aFile: streampos original = aFile.tellp(); //save current position aFile.seekp(0, ios::end); //reposition to end of file aFile << x; //write a value to file aFile.seekp(original); //return to original position seekg (seekp) can take one or two parameters. When it has two parameters, the first is a position relative to the position indicated by the seek_dir value given as the second parameter. For example: aFile.seekp(-10, ios::end); moves to 10 bytes from the end while aFile.seekp(10, ios::cur); moves to 10 bytes forward from the current position.
14.5 Assignment of iostreamsiostreams does not allow assignment of one stream to another. The problem with copying a stream object is that there are then two versions of the state information, such as a pointer to the current write position within an output file, which can be changed independently. As a result, problems could occur. 14.6 Format ControlFormat control is discussed in detail in the in the man page ios(3CC4). 14.7 ManipulatorsManipulators are values that you can insert into or extract from iostreams to have special effects. Parameterized manipulators are manipulators that take one or more parameters. Because manipulators are ordinary identifiers, and therefore use up possible names, iostream doesn't define them for every possible function. A number of manipulators are discussed with member functions in other parts of this chapter. There are 13 predefined manipulators, as described in TABLE 14-2. When using that table, assume the following:
To use predefined manipulators, you must include the file iomanip.h in your program. You can define your own manipulators. There are two basic types of manipulator:
14.7.1 Using Plain ManipulatorsA plain manipulator is a function that:
The shift operators taking (a pointer to) such a function are predefined for iostreams, so the function can be put in a sequence of input or output operators. The shift operator calls the function rather than trying to read or write a value. An example of a tab manipulator that inserts a tab in an ostream is: ostream& tab(ostream& os) { return os <<'\t'; } ... cout << x << tab << y; This is an elaborate way to achieve the following: const char tab = '\t'; ... cout << x << tab << y; The following code is another example, which cannot be accomplished with a simple constant. Suppose you want to turn whitespace skipping on and off for an input stream. You can use separate calls to ios::setf and ios::unsetf to turn the skipws flag on and off, or you could define two manipulators. #include <iostream.h> #include <iomanip.h> istream& skipon(istream &is) { is.setf(ios::skipws, ios::skipws); return is; } istream& skipoff(istream& is) { is.unsetf(ios::skipws); return is; } ... int main () { int x,y; cin >> skipon >> x >> skipoff >> y; return 1; } 14.7.2 Parameterized ManipulatorsOne of the parameterized manipulators that is included in iomanip.h is setfill. setfill sets the character that is used to fill out field widths. It is implemented as shown in the following example: //file setfill.cc #include<iostream.h> #include<iomanip.h> //the private manipulator static ios& sfill(ios& i, int f) { i.fill(f); return i; } //the public applicator smanip_int setfill(int f) { return smanip_int(sfill, f); } A parameterized manipulator is implemented in two parts:
Several classes are defined in the header file iomanip.h. Each class holds the address of a manipulator function and the value of one parameter. The iomanip classes are described in the man page manip(3CC4). The previous example uses the smanip_int class, which works with an ios. Because it works with an ios, it also works with an istream and an ostream. The previous example also uses a second parameter of type int. The applicator creates and returns a class object. In the previous code example the class object is an smanip_int, and it contains the manipulator and the int argument to the applicator. The iomanip.h header file defines the shift operators for this class. When the applicator function setfill appears in a sequence of input or output operations, the applicator function is called, and it returns a class. The shift operator acts on the class to call the manipulator function with its parameter value, which is stored in the class. In the following example, the manipulator print_hex:
The class omanip_long is used because this code example is for output only, and it operates on a long rather than an int: #include <iostream.h> #include <iomanip.h> static ostream& xfield(ostream& os, long v) { long save = os.setf(ios::hex, ios::basefield); os << v; os.setf(save, ios::basefield); return os; } omanip_long print_hex(long v) { return omanip_long(xfield, v); } 14.8 Strstreams: iostreams for ArraysSee the strstream(3CC4) man page. 14.9 Stdiobufs: iostreams for stdio FilesSee the stdiobuf(3CC4) man page. 14.10 Streambufsiostreams are the formatting part of a two-part (input or output) system. The other part of the system is made up of streambufs, which deal in input or output of unformatted streams of characters. You usually use streambufs through iostreams, so you don't have to worry about the details of streambufs. You can use streambufs directly if you choose to, for example, if you need to improve efficiency or to get around the error handling or formatting built into iostreams. 14.10.1 Working With StreambufsA streambuf consists of a stream or sequence of characters and one or two pointers into that sequence. Each pointer points between two characters. (Pointers cannot actually point between characters, but it is helpful to think of them that way.) There are two kinds of streambuf pointers:
A streambuf can have one or both of these pointers. 14.10.1.1 Position of PointersThe positions of the pointers and the contents of the sequences can be manipulated in various ways. Whether or not both pointers move when manipulated depends on the kind of streambuf used. Generally, with queue-like streambufs, the get and put pointers move independently; with file-like streambufs the get and put pointers always move together. A strstream is an example of a queue-like stream; an fstream is an example of a file-like stream. 14.10.2 Using StreambufsYou never create an actual streambuf object, but only objects of classes derived from class streambuf. Examples are filebuf and strstreambuf, which are described in man pages filebuf(3CC4) and ssbuf(3), respectively. Advanced users may want to derive their own classes from streambuf to provide an interface to a special device or to provide other than basic buffering. Man pages sbufpub(3CC4) and sbufprot(3CC4) discuss how to do this. Apart from creating your own special kind of streambuf, you may want to access the streambuf associated with an iostream to access the public member functions, as described in the man pages referenced above. In addition, each iostream has a defined inserter and extractor which takes a streambuf pointer. When a streambuf is inserted or extracted, the entire stream is copied. Here is another way to do the file copy discussed earlier, with the error checking omitted for clarity: ifstream fromFile("thisFile"); ofstream toFile ("thatFile"); toFile << fromFile.rdbuf(); We open the input and output files as before. Every iostream class has a member function rdbuf that returns a pointer to the streambuf object associated with it. In the case of an fstream, the streambuf object is type filebuf. The entire file associated with fromFile is copied (inserted into) the file associated with toFile. The last line could also be written like this: fromFile >> toFile.rdbuf(); The source file is then extracted into the destination. The two methods are entirely equivalent. 14.11 iostream Man PagesA number of C++ man pages give details of the iostream library. The following table gives an overview of what is in each man page. To access a classic iostream library man page, type: example% man -s 3CC4 name TABLE 14-3 iostream Man Pages Overview
14.12 iostream TerminologyThe iostream library descriptions often use terms similar to terms from general programming, but with specialized meanings. The following table defines these terms as they are used in discussing the iostream library. TABLE 14-4 iostream Terminology
Copyright © 2004, Sun Microsystems, Inc. All Rights Reserved. What are used to perform standard input and output operations?Most computer operating systems and by extension programming languages have identified the keyboard as the standard input device and the monitor as the standard output device.
What is standard input and standard output in C?An input can be given in the form of a file or from the command line. C programming provides a set of built-in functions to read the given input and feed it to the program as per requirement. When we say Output, it means to display some data on screen, printer, or in any file.
What are standard input output functions in C?The basic input/output functions are getchar , putchar , puts , scanf and printf . The first two functions, getchar and putchar, are used to transfer single characters.
What are input and output operations in C programming?Input and output functions are available in the C language to perform the most common tasks. In every C program, three basic functions take place – accepting of data as input, the processing of data, and the generation of output. The acceptance of data refers to input and the presentation of data refers to the output.
|