c ++中的各种输入输出
一种新的输出方式 ( A New Way to Output )
![Program code](https://i-blog.csdnimg.cn/blog_migrate/b019d3644562184c2910982116df742e.png)
C++ retains very high backwards compatibility with C, so <stdio.h> can be included to give you access to the printf() function for output. However, the I/O provided by C++ is significantly more powerful and more importantly type safe. You can still also use scanf() for input but the type safety features that C++ provides means that your applications will be more robust if you use C++.
C ++保持了与C的很高的向后兼容性,因此可以包含<stdio.h>以便您访问printf()函数以进行输出。 但是,C ++提供的I / O更加强大,并且更重要的是类型安全。 您仍然可以使用scanf()进行输入,但是C ++提供的类型安全功能意味着如果您使用C ++,您的应用程序将更加健壮。
In the previous lesson, this was touched on with an example that used cout. Here we'll go into a bit more depth starting with output first as it tends to be more used than input.
在上一课中,使用cout的示例对此进行了介绍。 在这里,我们将更深入一点,首先从输出开始,因为它往往比输入更常用。
The iostream class provides access to the objects and methods you need for both output and input. Think of i/o in terms of streams of bytes- either going from your application to a file, the screen or a printer - that's output, or from the keyboard - that's input.
iostream类提供对输出和输入所需的对象和方法的访问。 从字节流的角度来考虑I / O -从应用程序到文件,屏幕或打印机-输出,或者从键盘-输入。
带Cout的输出 ( Output with Cout )
If you know C, you may know that << is used to shift bits to the left. Eg 3 << 3 is 24. Eg left shift doubles the value so 3 left shifts multiplies it by 8.
如果您知道C,则可能知道<<用于将位向左移动。 例如3 << 3是24。例如,左移将值翻倍,因此3左移将其乘以8。
In C++, << has been overloaded in the ostream class so that int, float, and strings types (and their variants- eg doubles) are all supported. This is how you do text output, by stringing together multiple items between <<.
在C ++中, <<在ostream类中已重载 ,以便所有支持int , float和string类型(及其变体,例如double )。 这是通过将<<之间的多个项目串在一起来进行文本输出的方法。
cout << "Some Text" << intvalue << floatdouble << endl;
This peculiar syntax is possible because each of the << is actually a function call which returns a reference to an ostream object. So a line like the above is actually like this
这种特殊的语法是可能的,因为每个<<实际上是一个函数调用,该函数返回对ostream 对象的引用 。 所以上面的线实际上是这样的
cout.<<("some text").cout.<<( intvalue ).cout.<<(floatdouble).cout.<<(endl) ;
The C function printf was able to format output using Format Specifiers such as %d. In C++ cout can also format output but uses a different way of doing it.
C 函数 printf能够使用格式说明符(如%d)格式化输出。 在C ++中,cout也可以格式化输出,但使用不同的方式。
使用Cout格式化输出 ( Using Cout to Format Output )
The object cout is a member of the iostream library. Remember that this has to be included with a
对象cout是iostream库的成员。 请记住,这必须包含在
#include <iostream>
This library iostream is derived from ostream (for output) and istream for input.
该库iostream源自ostream (用于输出)和istream(用于输入)。
Formatting of text output is done by inserting manipulators into the output stream.
通过将操纵器插入输出流来完成文本输出的格式设置 。
什么是机械手? ( What Is a Manipulator? )
It's a function that can alter the characteristics of the output (and input) stream. On the previous page we saw that << was an overloaded function that returned a reference to the calling object e.g. cout for output or cin for input. All manipulators do this so you can include them in the output << or input >>. We'll look at input and >> later on in this lesson.
此功能可以更改输出(和输入)流的特性。 在上一页中,我们看到<<是一个重载函数,该函数返回了对调用对象的引用,例如,cout用于输出,cin用于输入。 所有操纵器都执行此操作,因此您可以将它们包括在输出<<或输入>>中 。 我们将在本课程的后面部分讨论输入和>> 。
count << endl;
endl is a manipulator which ends the line (and starts a new one). It is a function that can also be called in this way.
endl是结束行(并开始新行)的操纵器。 也可以通过这种方式调用它。
endl(cout) ;
Though in practice you wouldn't do that. You use it like this.
尽管实际上您不会那样做。 您可以像这样使用它。
cout << "Some Text" << endl << endl; // Two blank lines
文件只是流 ( Files Are Just Streams )
Something to bear in mind that with much development these days being done in GUI applications, why would you need text I/O functions? Isn't that just for console applications? Well you will probably do file I/O and you can use them there as well but also what is output to screen usually needs formatting as well. Streams are a very flexible way of handling input and output and can work with
要记住的一点是,随着当今在GUI应用程序中进行的大量开发,您为什么需要文本I / O功能? 这不只是用于控制台应用程序吗? 好吧,您可能会执行文件I / O,也可以在其中使用它们,但是输出到屏幕的内容通常也需要格式化。 流是一种非常灵活的处理输入和输出的方式,可以与
- Text I/O. As in console applications. 文本I / O。 如在控制台应用程序中。
- Strings. Handy for formatting. 字符串。 方便格式化。
- File I/O. 文件I / O。
再次操纵者 ( Manipulators Again )
Although we have been using the ostream class, it is a derived class from the ios class which derives from the ios_base. This ancestor class defines the public functions which are manipulators.
尽管我们一直在使用ostream类,但是它是从ios_base派生的ios类的派生类 。 此祖先类定义作为操纵器的公共功能 。
操纵器列表 ( List of Cout Manipulators )
Manipulators can be defined in input or output streams. These are objects that return a reference to the object and are placed between pairs of <<. Most of the manipulators are declared in <ios>, but endl, ends and flush come from <ostream>. Several manipulators take one parameter and these come from <iomanip>.
可以在输入或输出流中定义操纵器。 这些对象返回对该对象的引用,并放置在<<对之间。 大多数操纵器在<ios>中声明,但是endl , ends和flush从<ostream>发出。 多个操纵器采用一个参数,这些参数来自<iomanip>。
Here's a more detailed list.
这是更详细的列表。
From <ostream>
来自<ostream>
- endl - Ends the line and calls flush. endl-结束行并调用flush。
ends - Inserts '\0' ( NULL) into the stream.
结尾-将'\ 0'( NULL )插入流中。
- flush - Force the buffer to be output immediately. flush-强制立即输出缓冲区。
From <ios>. Most are declared in <ios_base> the ancestor of <ios>. I've grouped them by function rather than alphabetically.
来自<ios> 。 大多数在<ios>的祖先<ios_base>中声明。 我已经按功能而不是按字母顺序对它们进行了分组。
- boolalpha - Insert or extract bool objects as "true" or "false". boolalpha-插入或提取布尔对象为“ true”或“ false”。
- noboolalpha - Insert or extract bool objects as numeric values. noboolalpha-插入或提取布尔对象作为数值。
- fixed - Insert floating-point values in fixed format. 固定-以固定格式插入浮点值。
- scientific - Insert floating-point values in scientific format. 科学-以科学格式插入浮点值。
- internal - Internal-justify. 内部-内部调整。
- left - Left-justify. 左-左对齐。
- right - Right-justify. 对-右对齐。
- dec - Insert or extract integer values in decimal format. dec-以十进制格式插入或提取整数值。
- hex - Insert or extract integer values in hexadecimal (base 16) format. hex-以十六进制(以16为底)格式插入或提取整数值。
- oct - Insert or extract values in octal (base 8) format. oct-以八进制(以8为底)格式插入或提取值。
- noshowbase - Do not prefix value with its base. noshowbase-不要在基数前加前缀值。
- showbase - Prefix value with its base. showbase-前缀值及其底数。
- noshowpoint - Do not show decimal point if not necessary. noshowpoint-如有必要,不显示小数点。
- showpoint - Always show decimal point when inserting floating-point values. showpoint-插入浮点值时始终显示小数点。
- noshowpos - Don't insert plus sign (+) if number >= 0. noshowpos-如果数字> = 0,请勿插入加号(+)。
- showpos - Do insert plus sign (+) if number >=0. showpos-如果数字> = 0,请插入加号(+)。
- noskipws - Do not skip initial white space on extracting. noskipws-提取时不要跳过初始空白。
- skipws - Skip initial white space on extracting. skipws-提取时跳过初始空白。
- nouppercase - Don't replace lowercase letters by uppercase equivalents. nouppercase-请勿将小写字母替换为大写字母。
- uppercase - Replace lowercase letters by uppercase equivalents. 大写字母-将小写字母替换为大写字母。
- unitbuf - Flush buffer after an insert. unitbuf-插入后刷新缓冲区。
- nounitbuf - Don't flush buffer after each insert. nounitbuf-每次插入后不要刷新缓冲区。
使用Cout的示例 ( Examples Using Cout )
// ex2_2cpp
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
cout.width(10) ;
cout << right << "Test" << endl;
cout << left << "Test 2" << endl;
cout << internal <<"Test 3" << endl;
cout << endl;
cout.precision(2) ;
cout << 45.678 << endl;
cout << uppercase << "David" << endl;
cout.precision(8) ;
cout << scientific << endl;
cout << 450678762345.123 << endl;
cout << fixed << endl;
cout << 450678762345.123 << endl;
cout << showbase << endl;
cout << showpos << endl;
cout << hex << endl;
cout << 1234 << endl;
cout << oct << endl;
cout << 1234 << endl;
cout << dec << endl;
cout << 1234 << endl;
cout << noshowbase << endl;
cout << noshowpos << endl;
cout.unsetf(ios::uppercase) ;
cout << hex << endl;
cout << 1234 << endl;
cout << oct << endl;
cout << 1234 << endl;
cout << dec << endl;
cout << 1234 << endl;
return 0;
}
The output from this is below, with one or two extra line spaces removed for clarity.
其输出如下,为清楚起见,删除了一个或两个额外的行距。
Test
Test 2
Test 3
46
David
4.50678762E+011
450678762345.12299000
0X4D2
02322
+1234
4d2
2322
1234
Note: Despite the uppercase, David is printed as David and not DAVID. This is because uppercase only affects generated output- e.g. numbers printed in hexadecimal. So the hex output 4d2 is 4D2 when uppercase is in operation.
注意 :尽管是大写字母,但David被打印为David,而不是DAVID。 这是因为大写仅影响生成的输出,例如以十六进制打印的数字。 因此,当大写操作时,十六进制输出4d2为4D2。
Also, most of these manipulators actually set a bit in a flag and it is possible to set this directly with
而且,大多数这些操纵器实际上都在标志中设置了一点,并且可以直接使用
cout.setf()
and clear it with
并用清除
cout.unsetf()
使用Setf和Unsetf操纵I / O格式 ( Using Setf and Unsetf to Manipulate I/O Formatting )
The function setf has two overloaded versions shown below. While unsetf just clears the specified bits.
函数setf具有如下所示的两个重载版本。 而unsetf只是清除指定的位。
setf( flagvalues) ;
setf( flagvalues, maskvalues) ;
unsetf( flagvalues) ;
The variable flags is derived by ORing together all the bits you want with |. So if you want scientific, uppercase and boolalpha then use this. Only the bits passed in as the parameter are set. The other bits are left unchanged.
变量标志是通过将所需的所有位与|进行或运算而得出的。 因此,如果您想要科学,大写和boolalpha,则可以使用它。 仅设置作为参数传递的位。 其他位保持不变。
cout.setf( ios_base::scientific | ios_base::uppercase | ios_base::boolalpha) ;
cout << hex << endl;
cout << 1234 << endl;
cout << dec << endl;
cout << 123400003744.98765 << endl;
bool value=true;
cout << value << endl;
cout.unsetf( ios_base::boolalpha) ;
cout << value << endl;
Produces
产生
4D2
1.234000E+011
true
1
掩蔽位 ( Masking Bits )
The two parameter version of setf uses a mask. If the bit is set in both the first and second parameters then it gets set. If the bit is only in the second parameter then it is cleared. The values adjustfield, basefield and floatfield (listed below) are composite flags, that is several flags Or'd together. For basefield with the values 0x0e00 is the same as dec | oct | hex. So
setf的两个参数版本使用掩码。 如果在第一个和第二个参数中都设置了该位,则它将被设置。 如果该位仅在第二个参数中,则将其清除。 值adjustfield,basefield和floatfield (在下面列出)是复合标志,即几个标志“ 或”在一起。 对于值为0x0e00的 basefield与dec |相同。 十月 十六进制 。 所以
setf( ios_base::hex,ios_basefield ) ;
clears all three flags then sets hex. Similarly adjustfield is left | right | internal and floatfield is scientific | fixed.
清除所有三个标志,然后设置十六进制 。 类似地, 剩下的adjustfield | 对| 内部和floatfield是科学的| 固定的 。
位列表 ( List of Bits )
This list of enums is taken from Microsoft Visual C++ 6.0. The actual values used are arbitrary- another compiler may use different values.
此枚举列表取自Microsoft Visual C ++ 6.0。 使用的实际值是任意的-其他编译器可能使用不同的值。
skipws = 0x0001
unitbuf = 0x0002
uppercase = 0x0004
showbase = 0x0008
showpoint = 0x0010
showpos = 0x0020
left = 0x0040
right = 0x0080
internal = 0x0100
dec = 0x0200
oct = 0x0400
hex = 0x0800
scientific = 0x1000
fixed = 0x2000
boolalpha = 0x4000
adjustfield = 0x01c0
basefield = 0x0e00,
floatfield = 0x3000
_Fmtmask = 0x7fff,
_Fmtzero = 0
关于木log和塞尔 ( About Clog and Cerr )
Like cout, clog and cerr are pre-defined objects defined in ostream. The iostream class inherits from both ostream and istream so that's why the cout examples can use iostream.
像cout一样, clog和cerr是在ostream中定义的预定义对象。 iostream类继承自ostream和istream,因此这就是cout示例可以使用iostream的原因 。
缓冲和非缓冲 ( Buffered and Unbuffered )
Buffered - All output is temporarily stored in a buffer and then dumped to screen in one go. Both cout and clog are buffered.
缓冲-所有输出临时存储在缓冲区中 ,然后一次性转储到屏幕上。 cout和clog都被缓冲。
- Unbuffered- All output goes immediately to the output device. An example of an unbuffered object is cerr. 无缓冲-所有输出立即进入输出设备。 cerr是一个无缓冲对象的例子。
The example below demonstrates that cerr is used in the same way as cout.
下面的示例演示cerr的用法与cout相同。
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{ cerr.width(15) ;
cerr.right;
cerr << "Error" << endl;
return 0;
}
The main problem with buffering, is if the program crashes then the buffer contents are lost and it's harder to see why it crashed. Unbuffered output is immediate so sprinkling a few lines like this through the code might come in useful.
缓冲的主要问题是,如果程序崩溃,则缓冲区内容丢失,并且更难弄清为什么崩溃。 无缓冲的输出是立即产生的,因此通过代码散布这样的几行可能会很有用。
cerr << "Entering Dangerous function zappit" << endl;
记录问题 ( The Logging Problem )
Building a log of program events can be a useful way to spot difficult bugs- the type that only occur now and then. If that event is a crash though, you have the problem- do you flush the log to disk after every call so you can see events right up to the crash or keep it in a buffer and periodically flush the buffer and hope you don't lose too much when the crash occurs?
建立程序事件日志可能是发现棘手错误的一种有用方法,即仅偶尔发生的错误。 如果该事件是崩溃的,那么您有问题-您是否在每次调用后将日志刷新到磁盘,以便可以查看崩溃之前发生的事件或将其保留在缓冲区中,并定期刷新缓冲区,希望您不要崩溃时损失太多?
使用Cin输入:格式化输入 ( Using Cin for Input: Formatted Input )
There are two types of input.
有两种类型的输入。
- Formatted. Reading input as numbers or of a certain type. 格式化的。 以数字或某种类型读取输入。
Unformatted. Reading bytes or strings. This gives much greater control over the input stream.
未格式化。 读取字节或字符串 。 这样可以更好地控制输入流。
Here is a simple example of formatted input.
这是格式化输入的简单示例。
// excin_1.cpp : Defines the entry point for the console application.
#include "stdafx.h" // Microsoft only
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int a = 0;
float b = 0.0;
int c = 0;
cout << "Please Enter an int, a float and int separated by spaces" <<endl;
cin >> a >> b >> c;
cout << "You entered " << a << " " << b << " " << c << endl;
return 0;
}
This uses cin to read three numbers (int, float,int) separated by spaces. You must press enter after typing the number.
它使用cin读取由空格分隔的三个数字( int , float ,int)。 输入数字后,必须按Enter键。
3 7.2 3 will output "You entered 3 7.2 3".
3 7.2 3将输出“您输入了3 7.2 3”。
格式化输入具有局限性! ( Formatted Input has Limitations! )
If you enter 3.76 5 8, you get "You entered 3 0.76 5", all other values on that line are lost. That is behaving correctly, as the . is not part of the int and so marks the start of the float.
如果输入3.76 5 8,则会得到“您输入了3 0.76 5”,该行上的所有其他值都将丢失。 行为正确,如。 不是int的一部分,因此标记为float的开始。
错误陷阱 ( Error Trapping )
The cin object sets a fail bit if the input was not successfully converted. This bit is part of ios and can be read by use of the fail() function on both cin and cout like this.
如果输入未成功转换,则cin对象将设置失败位。 该位是ios的一部分,可以像这样在cin和cout上使用fail()函数读取。
if (cin.fail() ) // do something
Not surprisingly, cout.fail() is rarely set, at least on screen output. In a later lesson on file I/O, we'll see how cout.fail() can become true. There is also a good() function for cin, cout etc.
毫不奇怪,至少在屏幕输出上很少设置cout.fail() 。 在有关文件I / O的下一课中,我们将看到cout.fail()如何变为真实。 cin , cout等也有一个good()函数。
格式化输入中的错误陷阱 ( Error Trapping in Formatted Input )
Here is an example of input looping until a floating point number has been correctly entered.
这是输入循环直到正确输入浮点数之前的示例。
// excin_2.cpp
#include "stdafx.h" // Microsoft only
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
float floatnum;
cout << "Enter a floating point number:" <<endl;
while(!(cin >> floatnum))
{
cin.clear() ;
cin.ignore(256,'\n') ;
cout << "Bad Input - Try again" << endl;
}
cout << "You entered " << floatnum << endl;
return 0;
}
clear()
clear()
ignore
忽略
Note: An input such as 654.56Y will read all the way up to the Y, extract 654.56 and exit the loop. It is considered valid input by cin
注意 :诸如654.56Y之类的输入将一直读取到Y,提取654.56并退出循环。 cin被认为是有效输入
未格式化的输入 ( Unformatted Input )
键盘输入 ( Keyboard Entry )
cin cin Enter 输入 Return 返回This ends the lesson.
本课程到此结束。
翻译自: https://www.thoughtco.com/learn-about-input-and-output-958405
c ++中的各种输入输出