输入输出流

读取输入和输出

5.1类型:
  • 标准输入/输出:键盘,显示器。
  • 文件I/O:对外存磁盘文件为对象。
  • 串I/O:对内存中指定空间进行输入/输出。
类名 作用 头文件
istream 通用输入流 iostream
ostream 通用输出流 iostream
iostream 通用输入输出流 iostream
ifstream 文件输入流 fstream
oftream 文件输出流 fstream
fstream 文件输入输出流 fstream
istringstream 字符串输入流 sstream
ostringstream 字符串输出流 sstream
stringstream 字符串输入输出流 sstream
5.2流的四种状态
  • badbit 表示发生系统级的错误,如不可恢复的读写错误。通常情况下一旦 badbit 被置位,流就无法再使用了。

  • failbit 表示发生可恢复的错误,如期望读取一个int数值,却读出一个字符串等错误。这种问题通常是可以修改的,流还可以继续使用。

  • eofbit表示到达流结尾位置, 流在正常输入输出的情况下结束,会被置为eofbit状态。

  • goodbit 表示流处于有效状态。流在有效状态下,才能正常使用。如果 badbit 、 failbit 和 eofbit 任何一个被置位,则流无法正常使用。

5.3标准输入流/输出流
  • 1流提取符 “>>” 从流中提取数据时通常跳过输入流中的空格、 tab 键、换行符等空白字符。只有在输入完数据再按回车键后,该行数据才被送入键盘缓冲区,形成输入流,提取运算符 “>>” 才能从中提取数据。需要注意保证从流中读取数据能正常进行。
void printStreamStatus(std::istream & is){ 
    cout << "is's goodbit:" << is.good() << endl;
    cout << "is's badbit:" << is.bad() << endl;
    cout << "is's failbit:" << is.fail() << endl;
    cout << "is's eofbit:" << is.eof() << endl;
}

void test0(){
    printStreamStatus(cin);  //goodbit状态
    int num;    
    cin >> num;   
    cout << "num:" << num << endl;
    printStreamStatus(cin);  //进行一次输入后再检查cin的状态
}
  • 2如果没有进行正确的输入,输入流会进入failbit的状态,无法正常工作,需要恢复流的状态。

    查看C++参考文档,需要利用clear和ignore函数配合,实现这个过程

    if (!cin.good()) {
            //恢复流状态
            cin.clear();
            //需要清空缓冲区 
       		//std::numeric_limits<T>::max() 是 C++ 中的一个模板函数,用于获取类型 T 的最大值。 表示尽可能忽略多的字符,一直到'\n'结束。
        	//为了避免宏定义冲突,在max和()中间加上()。
      cin.ignore((numeric_limits<std::streamsize>::max)(), '\n');
    }
    
  • 3完成一个整型的输入

void InputInteger() {
    cout << "输入整型:" << endl;
    int num = 0;
    //逗号表达式整体值为最后一个逗号
    //之后的表达式的值
    while (cin >> num, !cin.eof()) {
        if(cin.bad()) {
            cout << "cin has broken!" << endl;
            return;
        }
        else if (cin.fail()) {
            cin.clear();
            cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            cout << "请输入一个int类型数据" << endl;
        }
        else {
            cout << "num:" << num << endl;
            break;
        }
    }
}
5.4缓冲机制
  • 1类型:

  • 缓冲机制分为三种类型:全缓冲、行缓冲和不带缓冲

    全缓冲:在这种情况下,当填满缓冲区后才进行实际 I/O 操作。全缓冲的典型代表是对磁盘文件的读写。

    行缓冲:在这种情况下,当在输入和输出中遇到换行符时,执行真正的 I/O 操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的 I/O 操作。典型代表是cin。

    不带缓冲:也就是不进行缓冲,有多少数据就刷新多少。标准错误输出 cerr是典型代表,这使得出错信息可以直接尽快地显示出来。

  • 2输出缓冲区刷新方式:

    • 程序正常执行完。
    • 缓冲区满。当缓冲区满了之后,就先刷新当前缓冲区种所有内容。
    • 使用操作符显示刷新输出缓冲区,比如endl。endl就是先刷新缓冲区,然后再换行。
  • string str,str1;
    
    	//1.使用输入操作符读取单词,读取两个单词
    	cin >> str >> str1;
    
    	//2.读取一行字符串,
    	string str2;
    	cin.ignore();  // 添加这一行
    	getline(cin, str2);
    	cout << str2 << endl;
    
    	//3.读取字符
    	char ch1;
    	char ch = cin.get();
    	cout << "ch = " << ch << endl;
    
  • 3操作符

    • endl:用来换行,并刷新缓冲区。
    • flush:用来直接刷新缓冲区。cout.flush();
  • 4标准错误流:cerr

  • #include <unistd.h>
    void test1(){
    	cerr << 1;
    	cout << 3;
    	sleep(2);                           
    }//直接输出13
    
5.5文件输入/输出流
  • 1构造函数形式

  • ifstream();
    explicit ifstream(const char* filename, openmode mode = ios_base::in);
    explicit ifstream(const string & filename, openmode mode = ios_base::in);
    
    ofstream();
    explicit ofstream(const char* filename, openmode mode = ios_base::out);
    explicit ofstream(const string & filename, openmode mode = ios_base::out);
    
    fstream();
    explicit fstream(const char* filename, openmode mode = ios_base::in|out);
    explicit fstream(const string & filename, openmode mode = ios_base::in|out);
    
  • 2文件模式

    **in **: 输入,文件将允许做读操作;如果文件不存在,打开失败

    out : 输出,文件将允许做写操作;如果文件不存在,则直接创建一个.会清空。

    app : 追加,写入将始终发生在文件的末尾

    ate : 末尾,写入最初在文件的末尾

    trunc : 截断,如果打开的文件存在,其内容将被丢弃,其大小被截断为零

    binary : 二进制,读取或写入文件的数据为二进制形式

  • 3文件输入流对象

    • 1可以使用无参构造创建ifstream对象,再使用open函数将这个文件输入流对象与文件绑定(若文件不存在,则文件输入流进入failbit状态);

    • //创建文本输入流对象,再绑定文件
          //逐个打印每个字符串
          ifstream ifs;
          ifs.open("a.txt");
          string word;
          while (ifs >> word) {
              cout << word << endl;
          }
          ifs.close();
      
    • 也可以使用有参构造创建ifstream对象,在创建时就将流对象与文件绑定,后续操作这个流对象就可以对文件进行相应操作。

    • ifstream ifs("a.txt");
      ifs.close();
      
    • 2按行读取:getline

    //c风格,不经常使用
    ifstream ifs("test.cc");
    //方法一,兼容C的写法,使用较少
    char buff[100] = {0};
    while(ifs.getline(buff,sizeof(buff))){
        cout << buff << endl;
        memset(buff,0,sizeof(buff));
    }
    
    //c++风格,使用string
    void test5() {
        string line;
        //头文件string
        while (std::getline(ifs, line)) {
            cout << line << endl;
        }
    }
    
    • 3读取指定字节数的内容
      • read()+seekg()+tellg()
      • 通过文件输入流对象读取到的内容交给字符数组,同时需要传入要读取的字符数.
      • 例子读取一个文件的全部内容。
    void test6() {
        string fileName = "b.txt";
        ifstream ifs(fileName);
        if (!ifs) {
            cerr << "ifs open file fail!" << fileName << endl;
            return;
        }
    
        //读取一个文件要获取文件的大小
        //将游标放到文件的最后
        ifs.seekg(0, std::ios::end);
        long length = ifs.tellg();  //获取尾后下标,也就是总的字符数
        cout << length << endl;
    
        char* pdate = new char[length + 1]();
        //需要将游标放在起始位置
        ifs.seekg(0, std::ios::beg);
        ifs.read(pdate, length);
    
        //content包含了文件所有内容,包括空格等
        string content(pdate);
        cout << "conten:" << content << endl;
        ifs.close();
    }
    
    • 4文件输出流
    //文件输出流,如果不存在就创建
    void test7() {
        string fileName = "target.txt";
        ofstream ofs(fileName, std::ios::app);
        string line("hello\n");
        //使用<<写入
        ofs << line;
    }
    
    //使用write()写入内容
    void test8() {
        ofstream ofs("target.txt", std::ios::app);
        string line = "kkkk\n";
        ofs.write(line.c_str(), line.size());
    }
    
5.6字符串输入/输出流
  • 1字符串输入流

    • 将字符串的内容传输给字符串输入流对象,再通过这个对象进行字符串的处理(解析)
    • 通常用来处理字符串内容,比如读取配置文件。
    • 例子:将字符串str传给两个int类型。
  • void test9() {
        string str = "123 456";
        int num1 = 0;
        int num2 = 0;
        //将字符串内容传递给字符串输入流对象
        //头文件sstream
        //输入流运算符会默认空格符作为分隔符
        istringstream iss(str);
        iss >> num1 >> num2;
        cout << "num1: " << num1 << endl;
        cout << "num2: " << num2 << endl;
    }
    
  • 2.字符串输出流

    • 通常的用途就是将各种类型的数据转换成字符串类型。
  • //字符串输出流
    void test10() {
        int num1 = 123;
        int num2 = 456;
        ostringstream oss;
        oss << "num1 = " << num1 << ", num2 = " << num2 << endl;
        cout << oss.str() << endl;
    }
    
posted @ 2024-06-27 16:02  炫炫子  阅读(12)  评论(0编辑  收藏  举报