专题:输入、输出和文件

一、基本概念

  • 流概念:输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中;程序只检查字节流不需要知道其来自何方,如下图

  • 缓冲区:其为程序与设备之间的中介内存块,显式刷新命令或缓冲区满了都会触发缓冲区刷新

二、cout语句

  • 常规操作
    const char *p = "字符串字面量";
    // 缓冲区:运行到此处,都是加到缓冲区,屏幕不显示字符串
    cout << "p指针指向的字符串是:";
    // 打印字符串:传入字符串指针,屏幕仍不显示字符串
    cout << p;
    // 刷新缓冲区:
    //		endl加换行符,并刷新缓冲区,flush单纯刷新缓冲区
    // 		将缓冲区的字符串释放到默认输出流设备屏幕上
    cout << endl;
    
  • 格式化输出
    #include <iostream>
    // set***方法用
    #include <iomanip>
    // sqrt方法用
    #include <cmath>
    
    using namespace std;
    
    int main()
    {
         double a = 123456.723456;
         // 默认显示位数:6位,其余四舍五入,显示123457
         cout << a << endl;
         // 以下两个不重置不改变
         // fixed:小数点计数法,scientific:科学计数法
         // right:靠右对齐, 还有left,无居中
         cout << fixed << right;
         // setw:设置宽度(小数点也算一位),一次性
         // setfill:设置填充符号,不重置不改变
         cout << setw(6) << setfill('$') << "root"
              << setw(7) << setfill('>') << "sqrt"
              // 虽然字符串超过宽度,但也不截取
              << setw(8) << setfill('<') << "fourth root"
              << endl;
         double root;
         for (int n = 10; n <= 30; n += 10)
         {
              // double:强制类型转换赋给root
              root = sqrt(double(n));
              cout << setw(6) << setfill('$') << n 
                   // setprecision:设置精度位3位,小数点后有三位,不重置不改变
                   << setw(7) << setfill('>') << setprecision(3) << root
                   << setw(8) << setfill('<') << setprecision(4) << sqrt(root)
                   // 重置填充为空
                   << setfill(' ') << endl;
         }
         
         cout << a << endl;
    }
    
  • 输出
    123457
    $$root>>>sqrtfourth root
    $$$$10>>3.162<<1.7783
    $$$$20>>4.472<<2.1147
    $$$$30>>5.477<<2.3403
    123456.7235
    

    补充:<iostream>对应了char,<wiostream>对应了w_char

三、cin语句

3.1 常规输入

  • 空白:cin以输入分隔符,且丢弃空白符,如果a b\tc,代表三次输入
  • 代码示例
    #include <iostream>
    
    using namespace std;
    
    int main() {
        int n;
        cout<< "请输入:";
        // cin返回值:若为n不可接受数据,则返回false,但非法数据停在流中
        while(cin>>n){
            cout<< "输入的字符是:"<< n << endl;
            cout << "请输入:";
        }
        // 流状态:
        //	1、非法输入ios_base::failbit被设置为1,fail()返回true
        //	2、到达末尾ios_base::eofbit被设置为1,eof()返回true
        //	3、其他	 ios_base::badbit被设置为1,bad()返回true
        if(cin.fail()){
            cout << "非法输入导致跳出循环"<< endl;
            // clear()函数清除流状态,加参数为不清除项
            cin.clear(ios_base::failbit);
            // 此处清了个寂寞,failbit还是1
        }
        // 完全清除流状态
        cin.clear();
        // ignore功能:将之前阻塞在流中的换行符清除,否则若之前输入的是11a,
        //  	   在clear函数运行后,a会传给下面cin
        // ignore参数解释:分隔符前要丢弃的字符数,分隔符
        // ignore原型:istream & ignore(int = 1, int = EOF)
        cin.ignore(255,'\n');
        cout<< "请输入:";
        // 若没ignore,非法字符会直接传给n
        cin>> n;
        cout << n <<endl;
        return 0;
    }
    

3.2 c风格getline

  • 行为:读取一行(包含\n),然后将换行符换成\0,赋值给C风格字符串指针
  • 输入行为
    • 仅读到一个换行符:设置failbit,需cin.clear();cin.ignore();后面的cin才能正常
    • 输入字符数>限制:设置failbit值,需cin.clear();,多余字符会直接赋值后续cin语句
  • 原型参数解释:getline(字符指针,可存储字符串长度(含末尾\0),[分隔符])
  • 代码示例(string版见4.1)
    #include <iostream>
    
    using namespace std;
    
    int main() {
        char ch[100] = {};
        char ch_1[100] = {};
    
        // 方法1:指定分隔符
        // 	原型:istream & getline(char *, int, char);
        // 	若输入123x456x,则123赋值ch,456赋值下一条cin语句ch_1
        cin.getline(ch, 5,'x');
        cin.getline(ch_1, 5,'x');
    
        cout<<ch<<endl;
        cout<<ch_1<<endl;
        
        cout<<"显示分隔"<<endl;
        
    	// 详见 3.1
    	cin.ignore(255,'\n');
    
        // 方法2:无分隔符(即默认‘\n’)
        // 原型:istream & getline(char *, int);
        // a、若输入123456,则1234赋值ch,空赋值下一条cin.getline语句ch_1
        // b、若输入123换行456,则显示正常
        cin.getline(ch, 5);
        // 若字符数超限:还有其他字符,设置failbit,所以此处无输入越过
        cin.getline(ch_1, 5);
        
        cout<<ch<<endl;
        cout<<ch_1<<endl;
    
        cout<<"显示结束"<<endl;
        return 0;
    }
    

3.3 c风格get

  • 原型:
    • 不含分隔符:istream & get(char *, int, char);
    • 指定分隔符:istream & get(char *, int);
  • 输入行为
    • 设置failbit
      • 条件:没有读取到任何字符,包括换行符
      • 例子:cin.get(p,3);cin.get(m,3);,第二个cin.fail()为true
    • 特点:<限定值:正常赋值,>限定值:拆分赋值
  • 与getline区别:get将换行符读入字符串,getline将换行符读入,但丢弃

3.4 读取单个字符

  • 循环读入单个字符(C风格字符)
    #include <iostream>
    
    using namespace std;
    
    int main() {
        char ch;
        cout<< "请猜测字母:";
        // 只能读取一个英文字符,中文是两个字符,这里读取会乱码
        // 注意与3.3区别,只有一个参数,且是字符变量(非指针)
        while(cin.get(ch)){
            if (ch=='a'){
                cout<<"选中了"<<endl;
                break;
            }
            cout<<"没选中"<<endl;
            cout<<"请猜测字母:";
            // 下次输入前,清除输入流中的换行符
            cin.ignore();
        }
        cout<< "游戏结束"<<endl;
        return 0;
    }
    

四、文件

  • C++文件打开模式
    C++模式含义
    ios_base::in只读,ifstream fin(filename);默认打开模式
    ios_base::out无则创建并写,有则清空再写,ofstream fin(filename);的默认打开模式
    ios_base::out | ios_base::app打开并在末尾追加写入
    ios_base::in | ios_base::binary以二进制模式打开写入
  • 文件指针位置
    // 头起算:指针指向fileObject的第 n+1 个字节(默认是 ios::beg)
    file.seekg( n );
    // 当前位置起算:把文件的读指针从 fileObject 当前位置向后移n个字节,n正负均可
    file.seekg( n, ios::cur );
    // 尾起算:把文件的读指针从 fileObject 末尾为基点,移n个字节,n<=0
    file.seekg( n, ios::end );
     
    // 返回当前n值:file为fstream,istream
    int n = file.tellg();
    // 返回当前n值:file为ofstream
    int n = file.tellp();
    

4.1 文件输出和读取

  • 代码示例
    #include <iostream>
    #include <string>
    // ofstream和ifstream
    #include <fstream>
    
    using namespace std;
    
    int main() {
        string filename;
        cout<< "请输入文件名:";
        cin >> filename;
        // 清除末尾的换行符
        cin.ignore();
        // 等同于oftream fou;   fou.open(filename.c_str(),ios_base::out);
        // ios_base::out可省略
        ofstream fou(filename.c_str());
        // 用于接收文件传入的行
        string words;
        // getline函数写法是针对string对象的,此处fin等同cin
        while(getline(cin,words)&& words!="q")
        	// 向文件写入,fou 等同 cout
            fou<<words<<endl;
    	// 一定记得关闭文件,可用fou.is_open();判断文件是否是打开的
        fou.close();
        // 清空文件流状态,fou可以复用指向其他文件
        fou.clear();
        cout<< "---------此处以下是读取文件显示-------"<< endl;
        ifstream fin(filename.c_str());
        // getline函数写法是针对string对象的,此处fin等同cin
        while (getline(fin,words)){
        	// 将读取的行打印到屏幕
            cout << words<< endl;
        }
        // 文件流状态判断函数
        // 返回:0
        cout << fin.bad();
        // 返回:1
        cout<< fin.fail();
        // 返回:1
        cout<< fin.eof();
        // 关闭文件
        fin.close();
        return 0;
    }
    

4.2 二进制文件读写

  • 功能:感觉这个可以DIY配置文件、数据库
  • 二进制格式文件:以二进制保存数据,速度更快,不需转换,紧凑准确。
  • 特点:
    • 文本方式打开:以txt方式打开是乱码
    • 多次追加相同数据:都会存,但是提取时用第一个
    • 多平台问题:平台(windows)只可用本平台生成的二进制文件,不可用其他平台的
  • 代码示例
    #include <iostream>
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    // 输入的数据,二进制只接收数据,不接受方法
    class Student{
    private:
        string _name;
        int _age;
        double _height;
    public:
        explicit Student(const string &name="无名",int age=0,double height=0.0) :
                _name(name), _age(age), _height(height) {}
        void show()const{
            cout<<"名字为:"<<_name<<endl;
            cout<<"年龄为:"<<_age<<endl;
            cout<<"身高为:"<<_height<<endl;
        }
    };
    
    int main() {
        // 做数据准备
        Student stu("小王",22,175.5);
    
        // 清空文件输出、二进制
        fstream f("stu.dat",
                  ios_base::out|ios_base::binary);
        if (f.is_open()){
            cout<<"------以下为读取数据-------"<<endl;
            stu.show();
            // 文件输出流用write函数:
            //     参数1:强制类型转换,参数2:内存中stu占用长度
            f.write((char*)&stu,sizeof stu);
            cout<< "传输完毕"<<endl;
        }
        // 关闭文件
        f.close();
        // 清空流状态,为后面重新绑定输入流做准备
        f.clear();
    
        cout<<"------以下为读取数据-------"<<endl;
        // 输入、二进制文件
        f.open("stu.dat",ios_base::in|ios_base::binary);
        if (f.is_open()){
            // 文件输入流用read函数:
            //     参数1:强制类型转换,参数2:内存中stu使用字符串长度
            f.read((char*)&stu,sizeof stu);
            // 测试是否读取正确
            stu.show();
        }
        // 关闭文件
        f.close();
        // 清空流状态,为后面重新绑定输入流做准备,末尾也可以不清
        f.clear();
        return 0;
    }
    

上一篇:C++启蒙笔记(八)—类继承、动态内存分配
下一篇: 专题:泛式编程之函数模板、类模板及STL

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值