精华内容
下载资源
问答
  • c 输入输出流运算符重载One of the first things you do when you are designing and implementing a class is to determine some way to get the data into your class objects and some way to get data out of ...

    c 输入输出流运算符重载

    One of the first things you do when you are designing and implementing a class is to determine some way to get the data into your class objects and some way to get data out of your objects. Sometimes member functions work well for this, but at other times you want to use the input and output operators like you use with the built-in data types.

    在设计和实现类时,要做的第一件事就是确定某种将数据放入类对象的方法以及某种将数据从对象中取出的方法。 有时成员函数可以很好地实现此目的,但有时您希望像使用内置数据类型一样使用输入和输出运算符。

    In this article I’m going to show you how to overload the input operator (>>) and the output operator (<<) so that you can use them with your class objects.

    在本文中,我将向您展示如何重载输入运算符( >> )和输出运算符( << ),以便可以将其与类对象一起使用。

    关于运算符重载的几句话 (A Few Words about Operator Overloading)

    C++ is one of the few languages to allow operator overloading. Overloading operators is useful with classes because there are times when you want to use a class object with an operator that does not recognize that object. This will be true for all your user-defined types (classes).

    C ++是少数允许运算符重载的语言之一。 重载运算符对类很有用,因为有时您想将类对象与无法识别该对象的运算符一起使用。 所有用户定义的类型(类)都是如此。

    For an example, consider a class called IntData. This class is a wrapper class for integers that includes (hypothetically) some functionality not found in the int type itself. If I want to add two IntData objects together, without operator overloading I will have to provide a member function for doing this. Here is an example code fragment:

    例如,考虑一个名为IntData的类。 此类是整数的包装器类,该类包括(假设)包括int类型本身未提供的某些功能。 如果我想将两个IntData对象一起添加而没有操作符重载,则必须提供一个成员函数来执行此操作。 这是一个示例代码片段:

    IntData d1(1);
    IntData d2(2);
    IntData d3 = d1.add(d2);

    What I would rather do is this:

    我宁愿这样做:

    IntData d1(1);
    IntData s2(2);
    IntData d3 = d1 + d2;

    I cannot do this without operator overloading because the + operator is not defined to work with my IntData objects. With operator overloading, on the other hand, I can have the + operator recognize my IntData objects and perform the resulting addition. This makes operator overloading an important part of many class definitions.

    没有运算符重载,我无法做到这一点,因为+运算符未定义为与我的IntData对象一起使用。 另一方面,通过运算符重载,我可以让+运算符识别我的IntData对象并执行结果加法。 这使得运算符重载是许多类定义的重要组成部分。

    This also applies to operations such as input and output. I can’t simply write this to display the contents of an IntData object:

    这也适用于输入和输出等操作。 我不能简单地编写以下代码来显示IntData对象的内容:

    cout << d1 << endl;

    The << operator has no knowledge of my class definition. Nor can I use the input operator to put data into an IntData object:

    <<操作符不了解我的类定义。 我也不能使用输入运算符将数据放入IntData对象:

    cin >> d2;

    To allow these operations to work so that the users of my class can use these objects in the same manner they use primitive data types, I need to overload the input and output operators to recognize IntData objects.

    为了使这些操作起作用,以便类的用户可以使用与使用原始数据类型相同的方式使用这些对象,我需要重载输入和输出运算符以识别IntData对象。

    重载初步:朋友功能 (Overloading Preliminary: Friend Functions)

    To properly overload operators to work with classes, you must define the function that overloads the operator as a friend function. A friend function is a function that has access to the private member variables of a class. The function is not considered part of the class; it just has access to the private member variables of the class to perform its function.

    要适当地重载运算符以使用类,您必须将重载该运算符的函数定义为friend function 。 朋友函数是可以访问类的私有成员变量的函数。 该功能不属于该类; 它只能访问该类的私有成员变量以执行其功能。

    Here is a simple example using a definition of the IntData class I discussed above. To more realistically demonstrate how friend functions work, I need to split the declaration of the class out from the definition of the class, though I am going to keep them both in the same file for readability sake. Here is the declaration and definition of the IntData class:

    这是一个使用上面讨论的IntData类的定义的简单示例。 为了更真实地展示友善函数的工作方式,我需要将类的声明与类的定义分开,尽管为了便于阅读,我将它们都保留在同一文件中。 这是IntData类的声明和定义:

    class IntData {
    private:
    int data;public:
    IntData(int);
    friend void print(const IntData &);
    };IntData::IntData(int d) {
    data = d;
    }void print(const IntData &d) {
    cout << d.data;
    }

    You can see that the print function is defined in the class definition but is not really part of the class. I can’t access it from an IntData object using the dot operator. If I try I get an error. Instead, I use it like a regular function and pass an IntData object to it. Here is a sample program to demonstrate how to use the friend function:

    您可以看到print函数是在类定义中定义的,但实际上并不是该类的一部分。 我无法使用点运算符从IntData对象访问它。 如果尝试,会出现错误。 相反,我将其像常规函数一样使用,并将IntData对象传递给它。 这是一个示例程序,以演示如何使用friend函数:

    int main ()
    {
    IntData d1(12);
    print(d1); // displays 12
    return 0;
    }

    There is, of course, more to friend functions than what I’ve shown here but this is enough to get you through this article on operator overloading. I will cover the details of friend functions, and friend classes, in a separate article.

    当然,与朋友功能相比,我在这里展示的功能更多,但这足以使您了解这篇有关运算符重载的文章。 我将在另一篇文章中介绍朋友功能和朋友类的详细信息。

    重载输出运算符 (Overloading the Output Operator)

    I’ll start my overloading demonstration by overloading the output operator (<<) to work with a Point class that I’ve defined. Here is the simple class definition for Point:

    我将通过重载输出运算符( << )以与我定义的Point类一起工作来开始重载演示。 这是Point的简单类定义:

    class Point {
    private:
    int x, y;
    public:
    Point(int, int);
    };

    First, let’s discuss how the output operator is overloaded. Overloading an operator involves creating a function definition that extends the definition of what data types the operator can work with. The function looks like a regular function. It has a return type, a name (the operator itself), a parameter list, a function body, and a return value.

    首先,让我们讨论输出运算符是如何重载的。 重载运算符涉及创建一个函数定义,该函数定义扩展了该运算符可以使用的数据类型的定义。 该函数看起来像常规函数。 它具有返回类型,名称(运算符本身),参数列表,函数主体和返回值。

    Overloaded functions are defined as friend functions to the class they are accepting data from. This is so we can pass the needed private member variables of the class directly to the function, even though the overloaded operator function is outside the class definition.

    重载函数定义为它们从中接受数据的类的朋友函数。 这样,即使重载的运算符函数在类定义之外,我们也可以将所需的类的私有成员变量直接传递给函数。

    Here is what the function definition signature line looks like for overloading the output operator to output Point object member variables:

    这是用于重载输出运算符以输出Point对象成员变量的函数定义签名行:

    ostream &operator << (ostream &strm, const Point &p)

    The function’s return type is ostream, which represents the output stream. The output operator name is next and it is defined as a reference object so that you can chain multiple output operators together. The parameter list consists of an ostream object reference, which is what the Point data is going to be streamed to, and a constant Point object reference so there will be no chance the data is modified in the function. These parameters are also passed by reference for efficiency purposes.

    该函数的返回类型为ostream ,它表示输出流。 接下来是输出运算符名称,它被定义为参考对象,以便您可以将多个输出运算符链接在一起。 参数列表由一个ostream对象引用和一个恒定的Point对象引用组成,这是Point数据将要流到的对象,因此不会在函数中修改数据。 这些参数也出于效率目的通过引用传递。

    Now let’s look at the function body:

    现在让我们看一下函数体:

    {
    strm << "x:" << x << ", y:" << y;
    return strm;
    }

    The function streams a label for the x and y coordinates along with the member variables themselves to the strm object and this object is returned by the function.

    该函数将x和y坐标的标签以及成员变量本身发送到strm对象,该对象由函数返回。

    Here is how you declare the function in the class declaration section:

    这是在类声明部分中声明函数的方式:

    friend ostream &operator << (ostream &, const Point &);

    Here is the complete class declaration and definition code, along with a test program:

    这是完整的类声明和定义代码,以及测试程序:

    class Point {
    private:
    int x, y;
    public:
    Point(int, int);
    friend ostream &operator << (ostream &, const Point &);
    };Point::Point(int newx, int newy) {
    x = newx;
    y = newy;
    }ostream &operator << (ostream &strm, const Point &p) {
    strm << "x:" << p.x << ", y:" << p.y;
    return strm;
    }int main ()
    {
    Point p1(1,2);
    cout << p1 << endl;
    return 0;
    }

    The output from this program is:

    该程序的输出为:

    x:1, y:2

    重载输入运算符 (Overloading the Input Operator)

    The code needed to overload the input operator is similar to the code for the output operator, except for obviously using an istream object instead of an ostream object. The overloading function needs to be declared as a friend in the class declaration section and defined outside the class as we did with the overloaded output operator.

    重载输入运算符所需的代码与输出运算符的代码相似,除了显然使用istream对象而不是ostream对象。 需要像在重载输出运算符中一样,在类声明部分中将重载函数声明为好友,并在类外部进行定义。

    Here is the function declaration and function definition for an overloaded input operator for the Point class:

    这是Point类的重载输入运算符的函数声明和函数定义:

    friend istream &operator >> (istream &, Point &);istream &operator >> (istream &strm, Point &p) {
    cout << "x coordinate: ";
    strm >> p.x;
    cout << "y coordinate: ";
    strm >> p.y;
    return strm;
    }

    Notice that the Point object is a constant parameter because we want the function to modify the member variables of the object. I also provided some prompting information in the function definition that is not strictly necessary but makes the operator more user-friendly.

    注意Point对象是一个常量参数,因为我们希望函数修改该对象的成员变量。 我还在功能定义中提供了一些提示信息,这些信息不是严格必要的,但是使操作员更易于使用。

    Here is a program that tests both the input operator and the output operator:

    这是一个测试输入运算符和输出运算符的程序:

    int main ()
    {
    Point p1;
    cout << "Enter a point: " << endl;
    cin >> p1;
    cout << p1 << endl;
    return 0;
    }

    The output from this program is:

    该程序的输出为:

    Enter a point:
    x coordinate: 5
    y coordinate: 8
    x:5, y:8

    未来有更多超载 (More Overloading Ahead)

    These two operators are just the first of many operators we can overload in the service of our class definitions. In my next article I’ll discuss how to overload the assignment operator and the increment and decrement operators.

    这两个运算符只是我们可以在我们的类定义的服务中重载的众多运算符中的第一个。 在我的下一篇文章中,我将讨论如何重载赋值运算符以及递增和递减运算符。

    Thanks for reading and please email me at mmmcmillan1@att.net with comments and suggestions. If you are interested in my online programming courses, please visit https://learningcpp.teachable.com.

    感谢您的阅读,请给我发电子邮件mmmmmillan1@att.net并提供评论和建议。 如果您对我的在线编程课程感兴趣,请访问https://learningcpp.teachable.com

    翻译自: https://levelup.gitconnected.com/learning-c-overloading-the-input-and-output-operators-807564b33e62

    c 输入输出流运算符重载

    展开全文
  • C++输入流和输出流

    2020-08-17 16:49:37
    本教程一开始就提到,C++ 又可以称为“带类的 C”,即可以理解为 C++ 是 C 语言的基础上增加了面向对象(类对象)。在此基础上,学过 C 语言的读者应该知道,它有一整套完成数据读写(I/O)的解决方案: 1.使用 ...

    C++输入和输出

    本教程一开始就提到,C++ 又可以称为“带类的 C”,即可以理解为 C++ 是 C 语言的基础上增加了面向对象(类和对象)。在此基础上,学过 C 语言的读者应该知道,它有一整套完成数据读写(I/O)的解决方案:
    1.使用 scanf()、gets() 等函数从键盘读取数据,使用 printf()、puts() 等函数向屏幕上输出数据;
    2.使用 fscanf()、fgets() 等函数读取文件中的数据,使用 fprintf()、fputs() 等函数向文件中写入数据。
    要知道,C 语言的这套 I/O 解决方案也适用于 C++ 程序,但 C++ 并没有“偷懒”,它自己独立开发了一套全新的 I/O 解决方案,其中就包含大家一直使用的 cin 和 cout。前面章节中,我们一直在用 cin 接收从键盘输入的数据,用 cout 向屏幕上输出数据(这 2 个过程又统称为“标准 I/O”)。除此之外,C++ 也对从文件中读取数据和向文件中写入数据做了支持(统称为“文件 I/O”)。

    本质上来说,C++ 的这套 I/O 解决方案就是一个包含很多类的类库(作为 C++ 标准库的组成部分),这些类常被称为“流类”。
    C++ 的开发者认为数据输入和输出的过程也是数据传输的过程,数据像水一样从一个地方流动到另一个地方,所以 C++ 中将此过程称为“流”,实现此过程的类称为“流类”。
    图 1 展示了 C++ 中用于实现数据输入和输出的这些流类以及它们之间的关系:
    在这里插入图片描述

    其中,图中的箭头代表各个类之间的派生关系。比如,ios 是所有流类的基类,它派生出 istream 和 ostream。特别需要指出的是,为了避免多继承的二义性,从 ios 派生出 istream 和 ostream 时,均使用了 virtual 关键字(虚继承)。
    图 1 中这些流类各自的功能分别为:
    istream:常用于接收从键盘输入的数据;
    ostream:常用于将数据输出到屏幕上;
    ifstream:用于读取文件中的数据;
    ofstream:用于向文件中写入数据;
    iostream:继承自 istream 和 ostream 类,因为该类的功能兼两者于一身,既能用于输入,也能用于输出;
    fstream:兼 ifstream 和 ofstream 类功能于一身,既能读取文件中的数据,又能向文件中写入数据。
    本章仅讲解实现标准 I/O 操作的 istream、ostream 和 iostream 类,有关实现文件 I/O 操作的流类放到后续章节讲解。

    C++输入流和输出流
    在前面章节的学习中,只要涉及输入或者输出数据,我们立马想到的就是 cin 和 cout。其实,cin 就是 istream 类的对象,cout 是 ostream 类的对象,它们都声明在 头文件中,这也解释了“为什么在 C++ 程序中引入 就可以使用 cin 和 cout”(当然使用 cin 和 cout,还需要声明 std 命名空间)。

    除此之外, 头文件中还声明有 2 个 ostream 类对象,分别为 cerr 和 clog。它们的用法和 cout 完全一样,但 cerr 常用来输出警告和错误信息给程序的使用者,clog 常用来输出程序执行过程中的日志信息(此部分信息只有程序开发者看得到,不需要对普通用户公开)。

    cout、cerr 和 clog 之间的区别如下:
    1.cout 除了可以将数据输出到屏幕上,通过重定向(后续会讲),还可以实现将数据输出到指定文件中;而 cerr 和 clog 都不支持重定向,它们只能将数据输出到屏幕上;
    2.cout 和 clog 都设有缓冲区,即它们在输出数据时,会先将要数据放到缓冲区,等缓冲区满或者手动换行(使用换行符 ‘\n’ 或者 endl)时,才会将数据全部显示到屏幕上;而 cerr 则不设缓冲区,它会直接将数据输出到屏幕上。

    除了以上 2 点特性上的不同之外,cerr、clog 和 cout 没有任何不同。之所以我们常用 cout,是因为 cerr 和 clog 有各自不同的适用场景。以 cerr 为例,一旦程序某处使用 cerr 输出数据,我们自然而然地会认为此处输出的是警告或者错误信息。

    值得一提的是,类似 cin、cout、cerr 和 clog 这样,它们都是 C++ 标准库的开发者创建好的,可以直接拿来使用,这种在 C++ 中提前创建好的对象称为内置对象。实际上, 头文件中还声明有处理宽字符的 4 个内置对象,分别为 wcin、wcout、wcerr 以及 wclog,由于不是本节重点,这里不再对它们做详细讲解。

    如下程序演示了 cin、cout、cerr 和 clog 的基本用法:

    #include <iostream>
    #include <string>
    
    int main() {
        std::string url;
        std::cin >> url;
        std::cout << "cout:" << url << std::endl;
        std::cerr << "cerr:" << url << std::endl;
        std::clog << "clog:" << url << std::endl;
        return 0;
    }

    程序执行结果为:

    http://c.biancheng.net
    cout:http://c.biancheng.net
    cerr:http://c.biancheng.net
    clog:http://c.biancheng.net

    注意,此程序中并没有考虑 cerr 和 clog 各自特有的含义,这里仅是为了演示 cerr 和 clog 的基础用法,不建议读者这样使用。另外,如果程序中 std 命名空间提前声明,则所有的 std:: 可以省略。

    它们的用法远不止此,istream 和 ostream 类提供了很多实用的函数,cin、cout、cerr 和 clog 作为类对象,当然也能调用。
    表 1 罗列了 cin 对象常用的一些成员方法以及它们的功能:

    表 1 C++ cin 输入流对象常用成员方法

    成员方法名		功能
    getline(str,n,ch)	从输入流中接收 n-1 个字符给 str 变量,当遇到指定 ch 字符时会停止读取,默认情况下 ch 为 '\0'get()			从输入流中读取一个字符,同时该字符会从输入流中消失。
    gcount() 		返回上次从输入流提取出的字符个数,该函数常和 get()getline()ignore()peek()read()readsome()putback()unget() 联用。
    peek()			返回输入流中的第一个字符,但并不是提取该字符。
    putback(c) 		将字符 c 置入输入流(缓冲区)。
    ignore(n,ch)		从输入流中逐个提取字符,但提取出的字符被忽略,不被使用,直至提取出 n 个字符,或者当前读取的字符为 ch。
    operator>>		重载 >> 运算符,用于读取指定类型的数据,并返回输入流对象本身。

    表 2 罗列了 cout、cerr 和 clog 对象常用的一些成员方法以及它们的功能:

    表 2 C++ cout 输出流对象常用成员方法

    成员方法名	功能
    put()		输出单个字符。
    write()		输出指定的字符串。
    tellp()		用于获取当前输出流指针的位置。
    seekp()		设置输出流指针的位置。
    flush()		刷新输出流缓冲区。
    operator<<	重载 << 运算符,使其用于输出其后指定类型的数据。

    举个例子:

    #include <iostream>
    using namespace std;
    
    int main() {
        char url[30] = {0};
        //读取一行字符串
        cin.getline(url, 30);
        //输出上一条语句读取字符串的个数
        cout << "读取了 "<<cin.gcount()<<" 个字符" << endl;
        //输出 url 数组存储的字符串
        cout.write(url, 30);
        return 0;
    }

    程序执行结果为:

    http://c.biancheng.net
    读取了 23 个字符
    http://c.biancheng.net

    C++ cout.put():输出单个字符

    通过前面的学习我们知道,C++ 程序中一般用 ostream 类的 cout 输出流对象和 << 输出运算符实现输出,并且 cout 输出流在内存中有相应的缓冲区。但有时用户还有特殊的输出需求,例如只输出一个字符,这种情况下可以借助该类提供的 put() 成员方法实现。

    put() 方法专用于向输出流缓冲区中添加单个字符,其语法格式如下:

    ostream&put(char c);

    其中,参数 c 为要输出的字符。

    可以看到,该函数会返回一个 ostream 类的引用对象,可以理解返回的是 cout 的引用。这意味着,我们可以像下面这样使用 put() 函数:

    cout.put(c1).put(c2).put(c3);

    因为 cout.put(c1) 向输出流缓冲区中添加 c1 字符的同时,返回一个引用形式的 cout 对象,所以可以继续用此对象调用 put(c2),依次类推。

    【实例1】输出单个字符 a。

    cout.put('a');

    调用该方法的结果是在屏幕上显示一个字符 a。

    【实例2】put() 函数的参数可以是字符或字符的 ASCII 代码(也可以是一个整型表达式)。

    cout.put(65 + 32);
    cout.put(97);

    上面两行代码都输出字符 a,因为 97 是字符 a 的 ASCII 代码。

    【实例3】可以在一个语句中连续调用 put() 函数,例如:

    cout.put(71).put(79).put(79). put(68).put('\n');

    在屏幕上显示GOOD。

    【实例4】有一个字符串 “ten.gnehcnaib.c//:ptth”,要求把它们按相反的顺序输出。

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main(){
        string str = "ten.gnehcnaib.c//:ptth";
        for (int i = str.length() - 1; i >= 0; i--) {
            cout.put(str[i]);  //从最后一个字符开始输出
        }
        cout.put('\n');
    
        return 0;
    }

    运行结果:

    http://c.biancheng.net

    除了使用 cout.put() 函数输出一个字符外,还可以用 putchar() 函数输出一个字符。putchar() 函数是C语言中使用的,在 <stdio.h> 头文件中定义,C++保留了这个函数,在 头文件中定义。

    C++ cout.write():输出字符串

    在某些场景中,我们还需要输出指定的字符串,这时可以使用 ostream 类提供的 write() 成员方法。
    write() 成员方法专用于向输出流缓冲区中添加指定的字符串,初学者可以简单的理解为输出指定的字符串。其语法格式如下:

    ostream&write(const char * s,streamsize n);

    其中,s 用于指定某个长度至少为 n 的字符数组或字符串;n 表示要输出的前 n 个字符。
    可以看到,该函数会返回一个 ostream 类的引用对象,可以理解返回的是 cout 的引用。这意味着,我们可以像下面这样使用 write() 方法:

    cout.write(c1, 1).write(c2, 2).write(c3, 3);

    因为 cout.write(c1, 1) 向输出流缓冲区中添加 c1 字符串中第 1 字符的同时,会返回一个引用形式的 cout 对象,所以可以继续用此对象调用 write(c2, 2),向输出流缓冲区添加 c2 字符串中前 2 个字符,依次类推。
    【例 1】输出 “http://c.biancheng.net/cplus/” 字符串中前 4 个字符。

    #include <iostream>
    using namespace std;
    
    int main() {
        const char * str = "http://c.biancheng.net/cplus/";
        cout.write(str, 4);
        return 0;
    }

    程序执行结果为:

    http

    【例 2】连续使用 write() 方法。

    #include <iostream>
    using namespace std;
    
    int main() {
        cout.write("http://", 7).write("c.biancheng.net", 15).write("/cplus/", 7);
        return 0;
    }

    程序执行结果为:

    http://c.biancheng.net/cplus/

    C++ cout.tellp()和cout.seekp()方法详解

    通过前面章节的学习我们知道,无论是使用 cout 输出普通数据,用 cout.put() 输出指定字符,还是用 cout.write() 输出指定字符串,数据都会先放到输出流缓冲区,待缓冲区刷新,数据才会输出到指定位置(屏幕或者文件中)。

    值得一提的是,当数据暂存于输出流缓冲区中时,我们仍可以对其进行修改。ostream 类中提供有 tellp() 和 seekp() 成员方法,借助它们就可以修改位于输出流缓冲区中的数据。

    C++ tellp()成员方法
    首先,tellp() 成员方法用于获取当前输出流缓冲区中最后一个字符所在的位置,其语法格式如下:

    streampos tellp();

    显然,tellp() 不需要传递任何参数,会返回一个 streampos 类型值。事实上,streampos 是 fpos 类型的别名,而 fpos 通过自动类型转换,可以直接赋值给一个整形变量(即 short、int 和 long)。也就是说,在使用此函数时,我们可以用一个整形变量来接收该函数的返回值。

    注意,当输出流缓冲区中没有任何数据时,该函数返回的整形值为 0;当指定的输出流缓冲区不支持此操作,或者操作失败时,该函数返回的整形值为 -1。

    在下面的样例中,实现了借助 cout.put() 方法向 test.txt 文件中写入指定字符,由于此过程中字符会先存入输出流缓冲区,所以借助 tellp() 方法,我们可以实时监控新存入缓冲区中字符的位置。

    举个例子:

    #include <iostream> //cin 和 cout
    #include <fstream> //文件输入输出流
    int main() {
        //定义一个文件输出流对象
        std::ofstream outfile;
        //打开 test.txt,等待接收数据
        outfile.open("test.txt");
        const char * str = "http://c.biancheng.net/cplus/";
        //将 str 字符串中的字符逐个输出到 test.txt 文件中,每个字符都会暂时存在输出流缓冲区中
        for (int i = 0; i < strlen(str); i++) {
            outfile.put(str[i]);
            //获取当前输出流
            long pos = outfile.tellp();
            std::cout << pos << std::endl;
        }
        //关闭文件之前,刷新 outfile 输出流缓冲区,使所有字符由缓冲区流入test.txt文件
        outfile.close();
        return 0;
    }

    注意,此例中涉及到了文件操作的相关知识,初学者仅需借助注释了解程序的执行脉络即可,不需要研究具体实现细节。有关文件操作,后续章节会做详细讲解。

    读者可自行运行此程序,其输出结果为 1~29。这意味着,程序中每次向输出流缓冲区中放入字符时,pos 都表示的是当前字符的位置。比如,当将 str 全部放入缓冲区中时,pos 值为 29,表示的是最后一个字符 ‘/’ 位于第 29 个位置处。

    C++ seekp()成员方法
    seekp() 方法用于指定下一个进入输出缓冲区的字符所在的位置。

    举个例子,假设当前输出缓冲区中存有如下数据:

    http://c.biancheng.net/cplus/
    借助 tellp() 方法得知,最后一个 ‘/’ 字符所在的位置是 29。此时如果继续向缓冲区中存入数据,则下一个字符所在的位置应该是 30,但借助 seekp() 方法,我们可以手动指定下一个字符存放的位置。

    比如通过 seekp() 指定下一个字符所在的位置为 23,即对应 “cplus/” 部分中字符 ‘c’ 所在的位置。此时若再向缓冲区中存入 “python/”,则缓冲区中存储的数据就变成了:

    http://c.biancheng.net/python/

    显然,新的 “python/” 覆盖了原来的 “cplus/”。

    seekp() 方法有如下 2 种语法格式:

    //指定下一个字符存储的位置
    ostream& seekp (streampos pos);
    //通过偏移量间接指定下一个字符的存储位置   
    ostream& seekp (streamoff off, ios_base::seekdir way);

    其中,各个参数的含义如下:
    pos:用于接收一个正整数;、
    off:用于指定相对于 way 位置的偏移量,其本质也是接收一个整数,可以是正数(代表正偏移)或者负数(代表负偏移);
    way:用于指定偏移位置,即从哪里计算偏移量,它可以接收表 1 所示的 3 个值。

    表 1 文件定位标志

    模式标志	    描 述
    ios::beg    从文件头开始计算偏移量
    ios::end    从文件末尾开始计算偏移量
    ios::cur    从当前位置开始计算偏移量

    同时,seekp() 方法会返回一个引用形式的 ostream 类对象,这意味着 seekp() 方法可以这样使用:

    cout.seekp(23) << "当前位置为:" << cout.tellp();

    举个例子:

    #include <iostream> //cin 和 cout
    #include <fstream> //文件输入输出流
    using namespace std;
    int main() {
        //定义一个文件输出流对象
        ofstream outfile;
        //打开 test.txt,等待接收数据
        outfile.open("test.txt");
        const char * str = "http://c.biancheng.net/cplus/";
        //将 str 字符串中的字符逐个输出到 test.txt 文件中,每个字符都会暂时存在输出流缓冲区中
        for (int i = 0; i < strlen(str); i++) {
            outfile.put(str[i]);
            //获取当前输出流
           
        }
        cout << "当前位置为:" << outfile.tellp() << endl;
        //调整新进入缓冲区字符的存储位置
        outfile.seekp(23);  //等价于:
                            //outfile.seekp(23, ios::beg);
                            //outfile.seekp(-6, ios::cur);
                            //outfile.seekp(-6, ios::end);
       
        cout << "新插入位置为:" << outfile.tellp() << endl;
        const char* newstr = "python/";
        outfile.write("python/", 7);
    
        //关闭文件之前,刷新 outfile 输出流缓冲区,使所有字符由缓冲区流入test.txt文件
        outfile.close();
        return 0;
    }

    读者可自行执行此程序,会发现最终 test.txt 文件中存储的为 “http://c.biancheng.net/python/”。

    C++ cout格式化输出(超级详细)

    在某些实际场景中,我们经常需要按照一定的格式输出数据,比如输出浮点数时保留 2 位小数,再比如以十六进制的形式输出整数,等等。

    对于学过 C 语言的读者应该知道,当使用 printf() 函数输出数据时,可以通过设定一些合理的格式控制符,来达到以指定格式输出数据的目的。例如 %.2f 表示输出浮点数时保留 2 位小数,%#X 表示以十六进制、带 0X 前缀的方式输出整数。

    关于 printf() 函数支持的格式控制符,更详细的讲解,可阅读《C语言数据输出大汇总》一节,这里不做详细赘述。

    C++ 通常使用 cout 输出数据,和 printf() 函数相比,cout 实现格式化输出数据的方式更加多样化。一方面,cout 作为 ostream 类的对象,该类中提供有一些成员方法,可实现对输出数据的格式化;另一方面,为了方便用户格式化输出数据,C++ 标准库专门提供了一个 头文件,该头文件中包含有大量的格式控制符(严格意义上称为“流操纵算子”),使用更加方便。

    C++ cout成员方法格式化输出
    《C++输入流和输出流》一节中,已经针对 cout 讲解了一些常用成员方法的用法。除此之外,ostream 类中还包含一些可实现格式化输出的成员方法,这些成员方法都是从 ios 基类(以及 ios_base 类)中继承来的,cout(以及 cerr、clog)也能调用。
    表 1 罗列了 ostream 类中可实现格式化输出的常用成员方法,以及它们各自的用法。

    表 1 ostream 类的成员方法

    成员函数  	  说明
    flags(fmtfl)	  当前格式状态全部替换为 fmtfl。注意,fmtfl 可以表示一种格式,也可以表示多种格式。
    precision(n)	  设置输出浮点数的精度为 n。
    width(w)	  指定输出宽度为 w 个字符。
    fill(c)		  在指定输出宽度的情况下,输出的宽度不足时用字符 c 填充(默认情况是用空格填充)。
    setf(fmtfl, mask) 在当前格式的基础上,追加 fmtfl 格式,并删除 mask 格式。其中,mask 参数可以省略。
    unsetf(mask)	  在当前格式的基础上,删除 mask 格式。

    其中,对于表 1 中 flags() 函数的 fmtfl 参数、setf() 函数中的 fmtfl 参数和 mask 参数以及 unsetf() 函数 mask 参数,可以选择表 2 中列出的这些值。
    表 2 fmtfl 和 mask 参数可选值

    标 志		作 用
    ios::boolapha	把 truefalse 输出为字符串
    ios::left	输出数据在本域宽范围内向左对齐
    ios::right	输出数据在本域宽范围内向右对齐
    ios::internal	数值的符号位在域宽内左对齐,数值右对齐,中间由填充字符填充
    ios::dec	设置整数的基数为 10
    ios::oct	设置整数的基数为 8
    ios::hex	设置整数的基数为 16
    ios::showbase	强制输出整数的基数(八进制数以 0 开头,十六进制数以 0x 打头)
    ios::showpoint	强制输出浮点数的小点和尾数 0
    ios::uppercase	在以科学记数法格式 E 和以十六进制输出字母时以大写表示
    ios::showpos	对正数显示“+”号
    ios::scientific	浮点数以科学记数法格式输出
    ios::fixed	浮点数以定点格式(小数形式)输出
    ios::unitbuf	每次输出之后刷新所有的流

    举个例子:

    #include <iostream>
    using namespace std;
    int main()
    {
        double a = 1.23;
        //设定后续输出的浮点数的精度为 4
        cout.precision(4);
        cout <<"precision: "<< a << endl;
        //设定后续以科学计数法的方式输出浮点数
        cout.setf(ios::scientific);
        cout <<"scientific:"<< a << endl;
        return 0;
    }

    程序执行结果为:

    precision: 1.23
    scientific:1.2300e+00

    注意,当 cout 采用此方式进行格式化输出时,其后不能立即输出数据,而只能像示例程序中那样,再用一个 cout 输出数据。

    值得一提的是,当调用 unsetf() 或者 2 个参数的 setf() 函数时,为了提高编写代码的效率,可以给 mask 参数传递如下 3 个组合格式:
    ios::adjustfield:等价于 ios::left | ios::right | ios::internal;
    ios::basefield:等价于 ios::dec | ios::oct | ios::hex;
    ios::floatfield:等价于 ios::scientific | ios::fixed。
    举个例子:

    #include <iostream>
    using namespace std;
    int main()
    {
        double f = 123;
        //设定后续以科学计数法表示浮点数
        cout.setf(ios::scientific);
        cout << f << '\n';
        //删除之前有关浮点表示的设定
        cout.unsetf(ios::floatfield);
        cout << f;
        return 0;
    }

    程序执行结果为:

    1.230000e+02
    123

    使用流操纵算子格式化输出
    表 3 罗列了 头文件中定义的一些常用的格式控制符,它们都可用于格式化输出。

    表 3 C++ 流操纵算子
    在这里插入图片描述

    注意:“流操纵算子”一栏带有星号 * 的格式控制符,默认情况下就会使用。例如在默认情况下,整数是用十进制形式输出的,等效于使用了 dec 格式控制符。

    和 cout 成员方法的用法不同,下面程序演示了表 3 中这些格式控制符的用法:

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
        //以十六进制输出整数
        cout << hex << 16 << endl;
        //删除之前设定的进制格式,以默认的 10 进制输出整数
        cout << resetiosflags(ios::basefield)<< 16 << endl;
    
        double a = 123;
        //以科学计数法的方式输出浮点数
        cout << scientific << a << endl;
        //删除之前设定的科学计数法的方法
        cout << resetiosflags(ios::scientific) << a << endl;
        return 0;
    }

    程序执行结果为:

    10
    16
    1.230000e+02
    123

    注意,
    如果两个相互矛盾的标志同时被设置,如先设置 setiosflags(ios::fixed),然后又设置 setiosflags(ios::scientific),那么结果可能就是两个标志都不起作用。因此,在设置了某标志,又要设置其他与之矛盾的标志时,就应该用 resetiosflags 清除原先的标志。

    cin.get():C++读取单个字符

    get() 是 istream 类的成员函数,它有多种重载形式(请猛击这里了解详情),不过本文只介绍最简单最常用的一种:

    int get();

    此函数从输入流中读入一个字符,返回值就是该字符的 ASCII 码。如果碰到输入的末尾,则返回值为 EOF。

    EOF 是 End of File 的缩写。istream 类中从输入流(包括文件)中读取数据的成员函数,在把输入数据都读取完后再进行读取,就会返回 EOF。EOF 是在 iostream 类中定义的一个整型常量,值为 -1。

    get() 函数不会跳过空格、制表符、回车等特殊字符,所有的字符都能被读入。例如下面的程序:

    #include <iostream>
    using namespace std;
    int main()
    {
        int c;
        while ((c = cin.get()) != EOF)
            cout.put(c);
        return 0;
    }

    程序运行情况如下:

    http://c.biancheng.net/cplus/↙
    http://c.biancheng.net/cplus/
    C++ Tutorial↙
    C++ Tutorial
    ^Z↙
    ↙表示

    回车键,^Z表示 Ctrl+Z 组合键。

    程序中的变量 c 应为 int 类型,而不能是 char 类型。在输入流中碰到 ASCII 码等于 0xFF 的字符时,cin.get() 返回 0xFF,0xFF 赋值给 c,此时如果 c 是 char 类型的,那么其值就是 -1(因为符号位为 1 代表负数),即等于 EOF,于是程序就错误地认为输入已经结束。

    而在 c 为 int 类型的情况下,将 0xFF 赋值给 c,c 的值是 255(因为符号位为 0,是正数),而非 -1,即除非读到输入末尾,c 的值都不可能是 -1。

    要将文本文件 test.txt 中的全部内容原样显示出来,程序可以如下编写:

    #include <iostream>
    using namespace std;
    int main()
    {
        int c;
        freopen("test.txt", "r", stdin);  //将标准输入重定向为 test.txt
        while ((c = cin.get()) != EOF)
            cout.put(c);
        return 0;
    }

    cin.getline():C++读入一行字符串(整行数据)

    getline() 是 istream 类的成员函数,它有如下两个重载版本:

    istream & getline(char* buf, int bufSize);
    istream & getline(char* buf, int bufSize, char delim);

    第一个版本从输入流中读取 bufSize-1 个字符到缓冲区 buf,或遇到\n为止(哪个条件先满足就按哪个执行)。函数会自动在 buf 中读入数据的结尾添加\0。

    第二个版本和第一个版本的区别在于,第一个版本是读到\n为止,第二个版本是读到 delim 字符为止。\n或 delim 都不会被读入 buf,但会被从输入流中取走。

    这两个函数的返回值就是函数所作用的对象的引用。如果输入流中\n或 delim 之前的字符个数达到或超过 bufSize,就会导致读入出错,其结果是:虽然本次读入已经完成,但是之后的读入都会失败。

    从输入流中读入一行,可以用第一个版本。用cin >> str这种写法是不行的,因为此种读法在碰到行中的空格或制表符时就会停止,因此就不能保证 str 中读入的是整行。

    第一个版本的 getline 函数的用法示例如下:

    #include <iostream>
    using namespace std;
    int main()
    {
        char szBuf[20];
        int n = 120;
        if(!cin.getline(szBuf,6))  //如果输入流中一行字符超过5个,就会出错
            cout << "error" << endl;
        cout << szBuf << endl;
        cin >> n;
        cout << n  << endl;
        cin.clear(); //clear能够清除cin内部的错误标记,使之恢复正常
        cin >> n;
        cout << n << endl;
        return 0;
    }

    程序的运行过程如下:

    ab cd↙
    ab cd
    3333
    4444
    

    在上面的输入情况下,程序是正常的。程序运行过程中还可能出现如下情况:

    ab cd123456k↙
    error
    ab cd
    120
    123456

    第 7 行,读入时因字符串超长导致出错,于是第 11 行并没有从输入流读入 n,n 维持了原来的值 120。

    第 12 行,调用 istream 的成员函数 clear() 清除 cin 内部的错误标记,此后 cin 又能正常读入了。因此,123456 在第 13 行被读入 n。

    可以用 getline() 函数的返回值(为 false 则输入结束)来判断输入是否结束。例如,要将文件 test.txt 中的全部内容(假设文件中一行最长有 10 000个字符)原样显示,程序可以如下编写:

    #include <iostream>
    using namespace std;
    const int MAX_LINE_LEN = 10000;  //假设文件中一行最长 10000 个字符
    int main()
    {
        char szBuf[MAX_LINE_LEN + 10];
        freopen("test.txt", "r", stdin);  //将标准输入重定向为 test.txt
        while (cin.getline(szBuf, MAX_LINE_LEN + 5))
            cout << szBuf << endl;
        return 0;
    }

    程序每次读入文件中的一行到 szBuf 并输出。szBuf 中不会读入回车符,因此输出 szBuf 后要再输出 endl 以换行。

    展开全文
  • 输入流和输出流: 输入流: FileInputStream: 1.read()方法;一个字节一个字节的读 2.read(bytes)方法:一次读取一个数组,快捷常用。不知道数组需要读取几次的情况下,利用-1来判断数组的最后一位,以防止死循环...

    输入流和输出流:
    输入流:

    FileInputStream:
    
    	1.read()方法;一个字节一个字节的读
    	2.read(bytes)方法:一次读取一个数组,快捷常用。不知道数组需要读取几次的情况下,利用-1来判断数组的最后一位,以防止死循环或者报错;
    
    
    FileInputStream fis = new FileInputStream("c://a.txt");
    	/*  while(true){
            //这种方法是 一个字节一个字节 的读,不经常用;
            byte b = (byte)
            fis.read();
            if(b == -1){
                break;
            }
            System.out.println(b);
        }
      */
    
        //一次读取一个数组,方便常用;
        byte [] bytes = new byte[1000];
        //读取返回的是一个参数
        int len = fis.read(bytes);
        //将读取的字节转成字符串,从0-读取到数组参数的个数(len)
        System.out.println(new String(bytes,0,len));
       /* 
       len = fis.read(bytes);
        System.out.println(new String(bytes,0,len));
        len = fis.read(bytes);
        System.out.println(new String(bytes,0,len));
        //当数组内容读取完毕后,返回-1;可以用这个方法来判断:
        len = fis.read(bytes);
        System.out.println(len);
        */
        fis.close();
    }
    

    输出流:

    FileOutputStream:
    一切皆字节:
        计算机中任何数据(文本,图片,视频,音乐)都是以二进制存储;
        在数据传输中,也是以二进制的形式存储的
        后续学习任何流,传输时底层都是以二进制
        
    public static void main(String[] args) throws IOException {
       //加了true之后,会在创建的文件中追加内容;不加true,则每次都会删除重写
        FileOutputStream fos = new FileOutputStream("c://a.txt");
        //byte [] bytes = {65,66,67,68,69};
        byte [] bytes = "ABCDEF".getBytes();
        //写一个具有开始下标及长度的字节
        fos.write(bytes,1,2);
        //1.写一个指定字节
        //fos.write(65);
        //写一个字节
    	//fos.write(bytes);
        fos.close();
        System.out.println("已经写出");
    }
    

    IO流常用方法演示:

    //从指定文件夹移动文件到另一个指定文件夹;不建议移动电脑内部文件夹,容易出错
        File file = new File("E://QQ文件//QQ图片.jpg");
        File newFile = new File("D://1");
        file.renameTo(newFile);
      //创建文件
        boolean flag = file.createNewFile();
        System.out.println(flag?"创建成功":"创建失败");*//**//*
      //创建文件夹,并在文件夹内创建文件
        //file.mkdir();
        File a = new File(file,"a.txt");
        a.createNewFile();
        File b = new File("C://1.txt","b.txt");
        b.createNewFile();
      //删除文件
        a.delete();
        b.delete();*/
    }
    

    .ListFile()方法:

    1.根据具体条件,对文件夹进行遍历。遍历并打印出文件夹中的内容或地址;
    2.过滤器(FileFilter):通过实现FileFilter 接口,在接口方法内部写入条件;
    读取文件夹中符合条件的内容;
    
    展开全文
  • 输入和输出并不是C++语言中的正式组成成分。C和C++本身都没有为输入和输出提供专门的语句结构。输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的。 C++的输出和输入是用“”(stream)的方式实现的...

    目录

    一 输入流与输出流的基本操作
    二 在输入流与输出流中使用控制符

    输入和输出并不是C++语言中的正式组成成分。C和C++本身都没有为输入和输出提供专门的语句结构。输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的。

    C++的输出和输入是用“流”(stream)的方式实现的。图3.2和图3.3表示C++通过流进行输入输出的过程。

    有关流对象cin、cout和流运算符的定义等信息是存放在C++的输入输出流库中的,因此如果在程序中使用cin、cout和流运算符,就必须使用预处理命令把头文件stream包含到本文件中:

    #include

    尽管cin和cout不是C++本身提供的语句,但是在不致混淆的情况下,为了叙述方便,常常把由cin和流提取运算符“>>”实现输入的语句称为输入语句或cin语句,把由cout和流插入运算符“<<”实现输出的语句称为输出语句或cout语句。根据C++的语法,凡是能实现某种操作而且最后以分号结束的都是语句。
    一、输入流与输出流的基本操作

    cout语句的一般格式为:
    cout<<表达式1<<表达式2<<……<<表达式n;
    cin语句的一般格式为:
    cin>>变量1>>变量2>>……>>变量n;

    **在定义流对象时,系统会在内存中开辟一段缓冲区,用来暂存输入输出流的数据。在执行cout语句时,先把插入的数据顺序存放在输出缓冲区中,直到输出缓冲区满或遇到cout语句中的endl(或’\n’,ends,flush)为止,此时将缓冲区中已有的数据一起输出,并清空缓冲区。**输出流中的数据在系统默认的设备(一般为显示器)输出。

    一个cout语句可以分写成若干行。如
    cout<<“This is a simple C++ program.”<<endl;
    可以写成
    cout<<"This is " //注意行末尾无分号
    <<"a C++ "
    <<“program.”
    <<endl; //语句最后有分号
    也可写成多个cout语句,即
    cout<<"This is "; //语句末尾有分号
    cout <<"a C++ ";
    cout <<“program.”;
    cout<<endl;
    以上3种情况的输出均为
    This is a simple C++ program.

    注意 不能用一个插入运算符“<<”插入多个输出项,如:
    cout<<a,b,c; //错误,不能一次插入多项
    cout<<a+b+c; //正确,这是一个表达式,作为一项

    在用cout输出时,用户不必通知计算机按何种类型输出,系统会自动判别输出数据的类型,使输出的数据按相应的类型输出。如已定义a为int型,b为float型,c为char型,则
    cout<<a<<’ ‘<<b<<’ '<<c<<endl;
    会以下面的形式输出:
    4 345.789 a

    与cout类似,一个cin语句可以分写成若干行。如
    cin>>a>>b>>c>>d;
    可以写成
    cin>>a //注意行末尾无分号

    b //这样写可能看起来清晰些
    c
    d;
    也可以写成
    cin>>a;
    cin>>b;
    cin>>c;
    cin>>d;
    以上3种情况均可以从键盘输入: 1 2 3 4 ↙

    也可以分多行输入数据:
    1↙
    2 3↙
    4↙
    在用cin输入时,系统也会根据变量的类型从输入流中提取相应长度的字节。如有
    char c1,c2;
    int a;
    float b;
    cin>>c1>>c2>>a>>b;
    如果输入
    1234 56.78↙

    注意: 34后面应该有空格以便和56.78分隔开。也可以按下面格式输入:
    1 2 34 56.78↙ (在1和2之间有空格)
    **不能用cin语句把空格字符和回车换行符作为字符输入给字符变量,它们将被跳过。**如果想将空格字符或回车换行符(或任何其他键盘上的字符)输入给字符变量,可以用3.4.3节介绍的getchar函数。
    在组织输入流数据时,要仔细分析cin语句中变量的类型,按照相应的格式输入,否则容易出错。
    二、在输入流与输出流中使用控制符

    上面介绍的是使用cout和cin时的默认格式。但有时人们在输入输出时有一些特殊的要求,如在输出实数时规定字段宽度,只保留两位小数,数据向左或向右对齐等。C++提供了在输入输出流中使用的控制符(有的书中称为操纵符)。

    需要注意的是: 如果使用了控制符,在程序单位的开头除了要加iostream头文件外,还要加iomanip头文件。

    举例: 输出双精度数。
    double a=123.456789012345;对a赋初值
    (1) cout<<a;输出: 123.456
    (2) cout<<setprecision(9)<<a;输出: 123.456789
    (3) cout<<setprecision(6);恢复默认格式(精度为6)
    (4) cout<< setiosflags(ios∷fixed);输出: 123.456789
    (5) cout<<setiosflags(ios∷fixed)<<setprecision(8)<<a;输出: 123.45678901
    (6) cout<<setiosflags(ios∷scientific)<<a;输出: 1.234568e+02
    (7) cout<<setiosflags(ios∷scientific)<<setprecision(4)<<a; 输出: 1.2346e02

    下面是整数输出的例子:
    int b=123456;对b赋初值
    (1) cout<<b;输出: 123456
    (2) cout<<hex<<b; 输出: 1e240
    (3) cout<<setiosflags(ios∷uppercase)<<b;输出: 1E240
    (4) cout<<setw(10)<<b<<’,’<<b; 输出: 123456,123456
    (5) cout<<setfill(’*’)<<setw(10)<<b;输出: **** 123456
    (6) cout<<setiosflags(ios∷showpos)<<b;输出: +123456

    如果在多个cout语句中使用相同的setw(n),并使用setiosflags(ios∷right),可以实现各行数据右对齐,如果指定相同的精度,可以实现上下小数点对齐。

    例3.1 各行小数点对齐。
    #include
    #include
    using namespace std;
    int main( )
    {
    double a=123.456,b=3.14159,c=-3214.67;
    cout<<setiosflags(ios∷fixed)<<setiosflags(ios∷right)<<setprecision(2);
    cout<<setw(10)<<a<<endl;
    cout<<setw(10)<<b<<endl;
    cout<<setw(10)<<c<<endl;
    return 0;
    }

    输出如下:
    123.46 (字段宽度为10,右对齐,取两位小数)
    3.14
    -3214.67
    先统一设置定点形式输出、取两位小数、右对齐。这些设置对其后的输出均有效(除非重新设置),而setw只对其后一个输出项有效,因此必须在输出a,b,c之前都要写setw(10)。

    学C++的时候,这几个输入函数弄的有点迷糊;这里做个小结,为了自己复习,也希望对后来者能有所帮助,如果有差错的地方还请各位多多指教(本文所有程序均通过VC 6.0运行)转载请保留作者信息;
    1、cin
    1、cin.get()
    2、cin.getline()
    3、getline()
    4、gets()
    5、getchar()

    1、cin>>

    用法1:最基本,也是最常用的用法,输入一个数字:

    #include
    using namespace std;
    main ()
    {
    int a,b;
    cin>>a>>b;
    cout<<a+b<<endl;
    }

    输入:2[回车]3[回车]
    输出:5

    用法2:接受一个字符串,遇“空格”、“TAB”、“回车”都结束

    #include
    using namespace std;
    main ()
    {
    char a[20];
    cin>>a;
    cout<<a<<endl;
    }

    输入:jkljkljkl
    输出:jkljkljkl

    输入:jkljkl jkljkl //遇空格结束
    输出:jkljkl

    2、cin.get()

    用法1: cin.get(字符变量名)可以用来接收字符

    #include
    using namespace std;
    main ()
    {
    char ch;
    ch=cin.get(); //或者cin.get(ch);
    cout<<ch<<endl;
    }

    输入:jljkljkl
    输出:j

    用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格

    #include
    using namespace std;
    main ()
    {
    char a[20];
    cin.get(a,20);
    cout<<a<<endl;
    }

    输入:jkl jkl jkl
    输出:jkl jkl jkl

    输入:abcdeabcdeabcdeabcdeabcde (输入25个字符)
    输出:abcdeabcdeabcdeabcd (接收19个字符+1个’\0’)

    用法3:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.

    这个我还不知道怎么用,知道的前辈请赐教;

    3、cin.getline() // 接受一个字符串,可以接收空格并输出

    #include
    using namespace std;
    main ()
    {
    char m[20];
    cin.getline(m,5);
    cout<<m<<endl;
    }

    输入:jkljkljkl
    输出:jklj

    接受5个字符到m中,其中最后一个为’\0’,所以只看到4个字符输出;

    如果把5改成20:
    输入:jkljkljkl
    输出:jkljkljkl

    输入:jklf fjlsjf fjsdklf
    输出:jklf fjlsjf fjsdklf

    //延伸:
    //cin.getline()实际上有三个参数,cin.getline(接受字符串的看哦那间m,接受个数5,结束字符)
    //当第三个参数省略时,系统默认为’\0’
    //如果将例子中cin.getline()改为cin.getline(m,5,‘a’);当输入jlkjkljkl时输出jklj,输入jkaljkljkl时,输出jk

    当用在多维数组中的时候,也可以用cin.getline(m[i],20)之类的用法:

    #include
    #include
    using namespace std;

    main ()
    {
    char m[3][20];
    for(int i=0;i<3;i++)
    {
    cout<<"\n请输入第"<<i+1<<“个字符串:”<<endl;
    cin.getline(m[i],20);
    }

    cout<<endl;
    for(int j=0;j<3;j++)
    cout<<“输出m[”<<j<<"]的值:"<<m[j]<<endl;

    }

    请输入第1个字符串:
    kskr1

    请输入第2个字符串:
    kskr2

    请输入第3个字符串:
    kskr3

    输出m[0]的值:kskr1
    输出m[1]的值:kskr2
    输出m[2]的值:kskr3

    4、getline() // 接受一个字符串,可以接收空格并输出,需包含“#include”

    #include
    #include
    using namespace std;
    main ()
    {
    string str;
    getline(cin,str);
    cout<<str<<endl;
    }

    输入:jkljkljkl
    输出:jkljkljkl

    输入:jkl jfksldfj jklsjfl
    输出:jkl jfksldfj jklsjfl

    和cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数

    5、gets() // 接受一个字符串,可以接收空格并输出,需包含“#include”

    #include
    #include
    using namespace std;
    main ()
    {
    char m[20];
    gets(m); //不能写成m=gets();
    cout<<m<<endl;
    }

    输入:jkljkljkl
    输出:jkljkljkl

    输入:jkl jkl jkl
    输出:jkl jkl jkl

    类似cin.getline()里面的一个例子,gets()同样可以用在多维数组里面:

    #include
    #include
    using namespace std;

    main ()
    {
    char m[3][20];
    for(int i=0;i<3;i++)
    {
    cout<<"\n请输入第"<<i+1<<“个字符串:”<<endl;
    gets(m[i]);
    }

    cout<<endl;
    for(int j=0;j<3;j++)
    cout<<“输出m[”<<j<<"]的值:"<<m[j]<<endl;

    }

    请输入第1个字符串:
    kskr1

    请输入第2个字符串:
    kskr2

    请输入第3个字符串:
    kskr3

    输出m[0]的值:kskr1
    输出m[1]的值:kskr2
    输出m[2]的值:kskr3

    自我感觉gets()和cin.getline()的用法很类似,只不过cin.getline()多一个参数罢了;

    这里顺带说明一下,对于本文中的这个kskr1,kskr2,kskr3的例子,对于cin>>也可以适用,原因是这里输入的没有空格,如果输入了空格,比如“ks kr jkl[回车]”那么cin就会已经接收到3个字符串,“ks,kr,jkl”;再如“kskr 1[回车]kskr 2[回车]”,那么则接收“kskr,1,kskr”;这不是我们所要的结果!而cin.getline()和gets()因为可以接收空格,所以不会产生这个错误;

    6、getchar() //接受一个字符,需包含“#include”

    #include
    #include
    using namespace std;
    main ()
    {
    char ch;
    ch=getchar(); //不能写成getchar(ch);
    cout<<ch<<endl;
    }

    输入:jkljkljkl
    输出:j

    //getchar()是C语言的函数,C++也可以兼容,但是尽量不用或少用;

    展开全文
  • 1. 输入输出流(IO)运行结构 2.File类 创建文件对象 File file = new File(String pathname); String pathname:创建文件对象(物理文件或目录) 格式:“c:\\test.txt"或者"c:/test.txt" ...
  • C++的输入输出流和缓冲区 一、 C++ 输入输出的含义  以前所用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上。从操作系统的角度看,每一个与主机相连的输入输出设备都...
  • Java中的字节输入流和字符输入输出流

    千次阅读 多人点赞 2016-02-25 16:35:46
    Java中的字节输入出流和字符输入输出流下面哪个流类属于面向字符的输入流( )A BufferedWriter B FileInputStream C ObjectInputStream D InputStreamReader解析:IO流(1)字节输入流 基类:InputStream ...
  • cio.c的内容如下,其中scanf为输入流,printf为输出流,&为取地址符 #include <stdio.h> int main() { printf("hello world!\n"); int a; scanf("%d",&a); printf("input value is : %d\n",a); ...
  • 一个简单的scanf输入流的细节问题printf的本质对于任何一个接触过c的人,都会知道这个函数怎么用。可是不一定知道它本质是一个输入流。举个例子:scanf("%d%c%d",&x, &ch, &y);在运行输入时候,必须scanf格式...
  • IO输出流和输入流

    2021-03-20 14:17:43
    输出流 创建文件并向文件中写入数据 1.使用方法 //创建输出流 FileWriter fw=new FileWriter("文件名称文件类型"); //相关方法 //向文件中写入字符串hello,这是内容只存在缓冲流当中,还没有写入文件 fw.write(...
  • :从输入/输出源到目标之间的有序数据  a)比如水流、电流、气流;计算机中流的本质是脉冲电流。  b)为进行数据的输入/输出操作,Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“”(stream)  ...
  • 总结前言C++输入和输出流(一)——标准输入输出记录了cin和cout的一些使用总结。本文记录文件输入输出的一些代码,理论太多了,其实看完代码,大概就可以使用了。文件I/O文件输入流:ifstream 文件输出流:ofstream ...
  • 第二十讲: C++的输入和输出与标准输出流 本讲基本要求 * 掌握:输入输出的含意;文件流以及输入/输出的格式控制;标准输出在C++程序中的应用。 * 理解:C++类库中的常用流类。 * 了解:C++的I/O对C的发展。 重点、...
  • b)为进行数据的输入/输出操作,Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“”(stream) c)Stream是从起源(source)到接收(sink)的有序数据 d)java.io包中定义了多个类型(类或抽象类)来...
  • 1、的控制 iomanip 在使用格式化I/O时应包含此头文件。 stdiostream 用于混合... ios是抽象基类,由它派生出istream类ostream类, iostream类支持输入输出操作,iostream类是从istream类ostream类通过多...
  • 输入流输出流问题

    2017-06-15 22:03:33
    只能输出一个字符型,且C和C++的标准输入流按回车后才会返回 ,如果流里没东西, 那就得回车才有反应, 如果已经有东西,就可以直接返回 .[系统的输入(读入到缓冲区)和输出函数(在屏幕上回显,所以你能看到输入的内容...
  • C/C++输入输出流

    2021-01-25 12:22:19
    istream中的类(如cin)提供了一些面向行的类成员函数:getline()get()。这两个函数都读取一行输入,直到达到换行符。不同的是,getline()将丢弃换行符,而get()将换行符保留在输入序列中。 一、字符串 I/O 1....
  • 题目: 下面那个流类输出面向字符的输入流() A、BufferedWriter B、FileInputStream C、ObjectInputStream D、InputStreamReader ...输入流和输出流是相对于内存而言,那从磁盘中读取的流肯定是输入流了,所以Rea
  • 目标 当输入一个生日时,如“1992 3 18”,程序输出相应的问好信息,如“Hello! 3 18 1992”。 使用流对象进行输入输出是 C++ 对 C 语言在 ...cout 代表标准输出流,关联显示器; cin 代表标准输入流,关联键盘; cer
  • 输入输出流

    2019-06-09 17:44:12
    下面编写程序统计一个文件中的字符总数、非空白字符...这个要用到输入输出流 #include<iostream> #include<fstream> #include<iomanip> using namespace std; bool isalph(char c) { return ((c ...
  • 输入和输出流的含义       以前所用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上。       从操作系统的角度看...
  • 类库和输入输出

    千次阅读 2008-08-21 15:01:00
    第12章 流类库和输入输出本章要点: 1.... 12.1 输入/输出流的概念 C++完全支持C输入输出系统,但由于C输入输出系统不支持类对象,所以C++又提供了自己的输入输出系统,并通过重载运算符“”“>>”来
  • 1、的控制 iomanip 在使用格式化I/O时应包含此头文件。...ios是抽象基类,由它派生出istream类ostream类, iostream类支持输入输出操作,iostream类是从istream类ostream类通过多重继承而...
  • 学习标准输入输出,我们都会遇到一个概念,流和缓冲区,但到底什么是流,什么是缓冲区呢? 书《C Primer Plus》上说,C程序处理一个流而不是直接处理文件。后面的解释十分抽象:『流(stream)是一个理想化的数据...
  • C/C++输入输出流总结

    2015-09-22 18:40:04
    C/C++输入输出流总结  前两天写C++实习作业,突然发现I/O是那么的陌生,打了好长时间的文件都没有打开,今天终于有点时间了,决定找本书,好好整理一下,大家共享。 C++ I/O C++支持两种I/O,第一种是从C语言...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,743
精华内容 1,097
关键字:

c输入流和输出流