C++基础13:C++输入输出

此专栏为移动机器人知识体系下的编程语言中的 C {\rm C} C++从入门到深入的专栏,参考书籍:《深入浅出 C {\rm C} C++》(马晓锐)和《从 C {\rm C} C C {\rm C} C++精通面向对象编程》(曾凡锋等)。



12.C++输入/输出
12.1 C++流类
  • 计算机的输入和输出是数据传送的过程, C {\rm C} C++将数据的传送过程称为流 ( s t r e a m ) ({\rm stream}) (stream)

  • C {\rm C} C++的 I / O {\rm I/O} I/O流是由若干字节组成的字节序列,称为字节流,字节流中的数据可以是多种形式的,包括:二进制数据、 A S C I I {\rm ASCII} ASCII字符、数字化视频和音频、数字图像信息等;

  • 在进行数据传输时,数据会被从一个对象传送到另一个对象中,这些对象包括:内存、输出设备、输入设备,当进行输入操作时,字节流是从输入设备流向内存,当进行输出操作时,字节流是从内存输出到输出设备;

  • 内存缓冲区:是系统为数据流开辟的一个内存空间,用于存放流中的数据;如果利用输入/输出操作对流进行传送,系统先将数据存入缓冲区中,当缓冲区满或遇到特定的输出指令时,才将这些数据进行传送;

  • c o u t {\rm cout} cout向屏幕输出时,系统将输出的内容先保存在为其开辟的缓冲区内,当此缓冲区满或遇到 e n d l {\rm endl} endl时,才将数据传送到屏幕上显示;利用 c i n {\rm cin} cin进行输入操作时,数据先保存在键盘输入缓冲区,遇到回车时将数据传送到程序输入缓冲区,当程序遇到 < < {\rm <<} <<操作符时,输入缓冲区的数据会被赋予相关的变量;

  • 系统提供缓冲区机制的目的:为了减少数据传送频度,以提高 I / O {\rm I/O} I/O效率;

  • C {\rm C} C++中,输入/输出流被定义为一系列的类,这些类称为流类 ( s t r e a m c l a s s ) ({\rm stream\ class}) (stream class),这些类被包含在 I / O {\rm I/O} I/O类库中,其输入输出包括如下方面的内容:

    • 标准 I / O {\rm I/O} I/O:对系统指定的标准设备,如:显示器、打印机等的输入和输出;
    • 文件 I / O {\rm I/O} I/O:对外存磁盘或外存储设备文件进行输入和输出;
    • 内存 I / O {\rm I/O} I/O(串 I / O {\rm I/O} I/O):对内存中的空间进行输入和输出;
  • 常用的 I / O {\rm I/O} I/O操作类如下表:

    类名 类名 类名 作用 作用 作用 头文件 头文件 头文件
    i o s {\rm ios} ios 输入 / 输出抽象基类 输入/输出抽象基类 输入/输出抽象基类 i o s t r e a m {\rm iostream} iostream
    i s t r e a m {\rm istream} istream 通用输入流和其他输入流基类 通用输入流和其他输入流基类 通用输入流和其他输入流基类 i o s t r e a m {\rm iostream} iostream
    o s t r e a m {\rm ostream} ostream 通用输出流和其他输出流基类 通用输出流和其他输出流基类 通用输出流和其他输出流基类 i o s t r e a m {\rm iostream} iostream
    i o s t r e a m {\rm iostream} iostream 通用输入 / 输出流和其他输入 / 输出流基类 通用输入/输出流和其他输入/输出流基类 通用输入/输出流和其他输入/输出流基类 i o s t r e a m {\rm iostream} iostream
    i f s t r e a m {\rm ifstream} ifstream 输入文件流类 输入文件流类 输入文件流类 f s t r e a m {\rm fstream} fstream
    o f s t r e a m {\rm ofstream} ofstream 输出文件流类 输出文件流类 输出文件流类 f s t r e a m {\rm fstream} fstream
    f s t r e a m {\rm fstream} fstream 输入 / 输出文件流类 输入/输出文件流类 输入/输出文件流类 f s t r e a m {\rm fstream} fstream
    i s t r s t r e a m {\rm istrstream} istrstream 输入字符串流 输入字符串流 输入字符串流 s t r s t r e a m {\rm strstream} strstream
    o s t r s t r e a m {\rm ostrstream} ostrstream 输出字符串流 输出字符串流 输出字符串流 s t r s t r e a m {\rm strstream} strstream
    s t r s t r e a m {\rm strstream} strstream 输入 / 输出字符串流 输入/输出字符串流 输入/输出字符串流 s t r s t r e a m {\rm strstream} strstream
  • 常用的 I / O {\rm I/O} I/O操作流类之间的关系图:

    17

  • 几个常用的流类:

    • i o s t r e a m {\rm iostream} iostream:基本输入/输出流操作;
    • s t r e a m {\rm stream} stream:用于文件的 I / O {\rm I/O} I/O操作;
    • s t r s t r e a m {\rm strstream} strstream:用于字符串流输入/输出;
    • i o m a n i p {\rm iomanip} iomanip:用于对流中的数据进行格式化输入/输出;
12.2 流对象和格式化输出
  • i o s t r e a m {\rm iostream} iostream头文件中,定义了许多相关的类,如: i o s 、 i s t r e a m 、 o s t r e a m 、 i o s t r e a m {\rm ios、istream、ostream、iostream} iosistreamostreamiostream等,还定义了 4 4 4种常用的流对象,如下表所示:

    对象 对象 对象 含义 含义 含义 对应设备 对应设备 对应设备 对应的类 对应的类 对应的类
    c i n {\rm cin} cin 标准输入流 标准输入流 标准输入流 键盘 键盘 键盘 i s t r e a m _ w i t h a s s i g n {\rm istream\_withassign} istream_withassign
    c o u t {\rm cout} cout 标准输出流 标准输出流 标准输出流 显示器 显示器 显示器 o s t r e a m _ w i t h a s s i g n {\rm ostream\_withassign} ostream_withassign
    c e r r {\rm cerr} cerr 标准错误流 标准错误流 标准错误流 显示器 显示器 显示器 o s t r e a m _ w i t h a s s i g n {\rm ostream\_withassign} ostream_withassign
    c l o g {\rm clog} clog 标准输出流 标准输出流 标准输出流 显示器 显示器 显示器 o s t r e a m _ w i t h a s s i g n {\rm ostream\_withassign} ostream_withassign
    • c i n {\rm cin} cin:标准输入流,是类 i s t r e a m _ w i t h a s s i g n {\rm istream\_withassign} istream_withassign的对象,作用为从系统指定的标准输入设备输入数据到程序变量中;
    • c o u t {\rm cout} cout:标准输出流,是类 o s t r e a m _ w i t h a s s i g n {\rm ostream\_withassign} ostream_withassign的对象,作用是将内存数据输出到系统指定的输出设备上;
    • c e r r {\rm cerr} cerr:标准错误流,是类 o s t r e a m {\rm ostream} ostream的对象,作用为向系统指定的标准输出设备输出错误信息;
    • c l o g {\rm clog} clog:标准输出流,是类 o s t r e a m {\rm ostream} ostream的对象,作用为向系统指定的标准输出设备输出日志信息, c e r r {\rm cerr} cerr没有缓冲区, c l o g {\rm clog} clog具有缓冲区,即 c e r r {\rm cerr} cerr结果会立即被显示到输出设备上, c l o g {\rm clog} clog在缓冲区满或遇到 e n d l {\rm endl} endl时才显示;
  • 对输出数据进行格式化称为流格式化输出,如果需要控制流输出的格式,一是使用流格式控制符,二是利用流类的相关成员函数进行控制;

  • 流格式控制符在头文件 i o m a n i p {\rm iomanip} iomanip中定义,使用控制符时需要包含头文件 i o m a n i p {\rm iomanip} iomanip,常用的输入/输出流控制符如下表:

    控制符 控制符 控制符 控制符作用 控制符作用 控制符作用
    d e c {\rm dec} dec 置基数为 10 , 相当 于 ′ % d ′ 置基数为10,相当于'\%{\rm d}' 置基数为10,相当%d
    h e x {\rm hex} hex 置基数为 16 , 相当 于 ′ % X ′ 置基数为16,相当于'\%{\rm X}' 置基数为16,相当%X
    o c t {\rm oct} oct 置基数为 8 , 相当 于 ′ % o ′ 置基数为8,相当于'\%{\rm o}' 置基数为8,相当%o
    s e t b a s e ( n ) {\rm setbase(n)} setbase(n) 置基数为 n 置基数为{\rm n} 置基数为n
    s e t f i l l ( c ) {\rm setfill(c)} setfill(c) 设置填充字符为 c 设置填充字符为{\rm c} 设置填充字符为c
    s e t p r e c i s i o n ( n ) {\rm setprecision(n)} setprecision(n) 设置显示小数精度为 n 位 设置显示小数精度为{\rm n}位 设置显示小数精度为n
    s e t w ( n ) {\rm setw(n)} setw(n) 设置域宽为 n 个字符 设置域宽为{\rm n}个字符 设置域宽为n个字符
    s e t i o s f l a g s ( i o s : : f i x e d ) {\rm setiosflags(ios::fixed)} setiosflags(ios::fixed) 固定的浮点显示 固定的浮点显示 固定的浮点显示
    s e t i o s f l a g s ( i o s : : s c i e n t i f i c ) {\rm setiosflags(ios::scientific)} setiosflags(ios::scientific) 指数表示 指数表示 指数表示
    s e t i o s f l a g s ( i o s : : l e f t ) {\rm setiosflags(ios::left)} setiosflags(ios::left) 左对齐 左对齐 左对齐
    s e t i o s f l a g s ( i o s : : r i g h t ) {\rm setiosflags(ios::right)} setiosflags(ios::right) 右对齐 右对齐 右对齐
    s e t i o s f l a g s ( i o s : : s k i p w s ) {\rm setiosflags(ios::skipws)} setiosflags(ios::skipws) 忽略前导空白 忽略前导空白 忽略前导空白
    s e t i o s f l a g s ( i o s : : u p p e r c a s e ) {\rm setiosflags(ios::uppercase)} setiosflags(ios::uppercase) 十六进制大写输出 十六进制大写输出 十六进制大写输出
    s e t i o s f l a g s ( i o s : : l o w e r c a s e ) {\rm setiosflags(ios::lowercase)} setiosflags(ios::lowercase) 十六进制小写输出 十六进制小写输出 十六进制小写输出
    s e t i o s f l a g s ( i o s : : s h o w p o i n t ) {\rm setiosflags(ios::showpoint)} setiosflags(ios::showpoint) 强制显示小数点 强制显示小数点 强制显示小数点
    s e t i o s f l a g s ( i o s : : s h o w p o s ) {\rm setiosflags(ios::showpos)} setiosflags(ios::showpos) 强制显示符号 强制显示符号 强制显示符号
  • 控制符实例:用控制符控制数据输出格式 ( e x a m p l e 12 _ 1. c p p ) ({\rm example12\_1.cpp}) (example12_1.cpp)

    /*** 作者:罗思维* 时间:2024/03/31* 描述:用控制符控制数据输出格式。 */
    #include <iostream>
    #include <iomanip>using namespace std;int main() {int iNumber;cout << "请输入一个数字:";cin >> iNumber;cout << "iNumber十进制:" << dec << iNumber << endl;cout << "iNumber十六进制:" << hex << iNumber << endl;cout << "iNumber八进制:" << setbase(8) << iNumber << endl;char *pStr = (char*)"Welcome";		// pStr指向字符串"Welcome"; cout << setw(20) << pStr << endl;	// 设置域宽为20,输出字符串; cout << setfill('-') << setw(20) << pStr << endl;	// 设置域宽为20,输出字符串,空白处用-填充; double dNumber = 5.845201314;cout << setiosflags(ios::scientific) << setprecision(8);cout << "dNumber = " << dNumber << endl;cout << "dNumber = " << setprecision(4) << dNumber << endl;			cout << "dNumber = " << setiosflags(ios::fixed) << dNumber << endl;	// 小数形式输出; return 0;
    }
    
  • 流对象 c o u t {\rm cout} cout常用的控制输出格式的成员函数如下:

    成员函数 成员函数 成员函数 对应的控制符 对应的控制符 对应的控制符 作用 作用 作用
    p r e c i s i o n ( n ) {\rm precision(n)} precision(n) s e t p r e c i s i o n ( n ) {\rm setprecision(n)} setprecision(n) 设置显示小数精度为 n 位 设置显示小数精度为{\rm n}位 设置显示小数精度为n
    w i d t h ( n ) {\rm width(n)} width(n) s e t w ( n ) {\rm setw(n)} setw(n) 设置输出宽度为 n 位 设置输出宽度为{\rm n}位 设置输出宽度为n
    f i l l ( c ) {\rm fill(c)} fill(c) s e t f i l l ( c ) {\rm setfill(c)} setfill(c) 当输出长度不足输出长度时 , 设置填充字符 c 当输出长度不足输出长度时,设置填充字符{\rm c} 当输出长度不足输出长度时,设置填充字符c
    s e t f ( f l a g ) {\rm setf(flag)} setf(flag) s e t i o s f l a g s ( f l a g ) {\rm setiosflags(flag)} setiosflags(flag) 设置输出格式状况 设置输出格式状况 设置输出格式状况
    u n s e t f ( ) {\rm unsetf()} unsetf() r e s e t i o s f l a g s ( ) {\rm resetiosflags()} resetiosflags() 终止已设置的输出格式状态 终止已设置的输出格式状态 终止已设置的输出格式状态

    设置格式状态的格式标志:

    • 对齐方式:
      • i o s : : l e f t {\rm ios::left} ios::left:输出数据左对齐;
      • i o s : : r i g h t {\rm ios::right} ios::right:输出数据右对齐;
      • i o s : : i n t e r n a l {\rm ios::internal} ios::internal:数值的符号位左对齐,数值右对齐,中间由填充字符填充,如:输出的数值为 − 10 -10 10,输出长度为 5 5 5,填充字符位为 ∗ * ,则: − ∗ ∗ 10 -**10 10
    • 数值基数设定:
      • i o s : : d e c {\rm ios::dec} ios::dec:设置整数的基数为 10 10 10
      • i o s : : o c t {\rm ios::oct} ios::oct:设置整数的基数为 8 8 8
      • i o s : : h e x {\rm ios::hex} ios::hex:设置整数的基数为 16 16 16
    • 整数格式控制:
      • i o s : : s h o w b a s e {\rm ios::showbase} ios::showbase:强制输出整数的基数;
      • i o s : : s h o w p o i n t {\rm ios::showpoint} ios::showpoint:强制输出浮点数的小数点和尾数 0 0 0
      • i o s : : u p p e r c a s e {\rm ios::uppercase} ios::uppercase:以科学记数法格式 E {\rm E} E和以十六进制输出字母时以大写表示;
      • i o s : : s h o w p o s {\rm ios::showpos} ios::showpos:对整数显示 + + +号;
    • 浮点数格式控制:
      • i o s : : s c i e n t i f i c {\rm ios::scientific} ios::scientific:浮点数以科学记数法格式输出;
      • i o s : : f i x e d {\rm ios::fixed} ios::fixed:浮点数以定点格式(小数形式)输出;
    • 流控制:
      • i o s : : u n i t b u f {\rm ios::unitbuf} ios::unitbuf:每次输出后刷新所有的流;
      • i o s : : s t d i o {\rm ios::stdio} ios::stdio:每次输出后清除 s t d o u t 、 s t d e r r {\rm stdout、stderr} stdoutstderr
  • 流控制成员函数实例:用流控制成员函数控制数据输出格式 ( e x a m p l e 12 _ 2. c p p ) ({\rm example12\_2.cpp}) (example12_2.cpp)

    /*** 作者:罗思维* 时间:2024/03/31* 描述:用流控制成员函数控制数据输出格式。 */
    #include <iostream>using namespace std;int main() {int nNumber = 80;// 进制的设置与取消设置;cout.setf(ios::showbase);cout << "nNumber十进制:" << nNumber << endl;cout.unsetf(ios::dec);cout.setf(ios::hex);cout << "nNumber十六进制:" << nNumber << endl;cout.unsetf(ios::hex);cout.setf(ios::oct);cout << "nNumber八进制:" << nNumber << endl;cout.unsetf(ios::oct);// 域宽与填充的设置与取消设置;char *pStr = (char*)"Welcome";cout.width(20);cout << pStr << endl;cout.width(20);cout.fill('-');cout << pStr << endl;// 小数输出形式设置;double dNumber = 5.845201314;cout.setf(ios::scientific);cout << "dNumber = ";cout.width(15);cout << dNumber << endl;cout.unsetf(ios::scientific);cout.setf(ios::fixed);cout.width(14);cout.setf(ios::showpos);cout.setf(ios::internal);cout.precision(5);cout << dNumber << endl;return 0;
    }
    
12.3 重载流运算符
  • 运算符重载的两种形式:重载为成员函数或重载为友元函数,重载插入运算符和提取运算符时,左边的参数是流,右边的参数是类的对象,因此,只能用友元函数的方式去重载插入运算符和提取运算符;

  • 插入运算符重载的语法格式:

    ostream& operator<<(ostream& os,const T& t)
    {...;	// 函数体;return os;
    }
    
    • 第一个参数:是对 o s t r e a m {\rm ostream} ostream对象的引用,函数返回值必须是这个引用对象;
    • 第二个参数:为输出的对象, T {\rm T} T是用户自定义的类, t {\rm t} t为该类的对象名;
  • 插入运算符重载实例:复数类的输出 ( C o m p l e x 1 ) ({\rm Complex1}) (Complex1)

    • C C o m p l e x {\rm CComplex} CComplex类定义头文件 ( C C o m p l e x . h ) ({\rm CComplex.h}) (CComplex.h)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:复数类定义头文件。*/
      #include <iostream>using namespace std;class CComplex {protected:double real;				// 复数的实部;double imag;				// 复数的虚部;public:CComplex(double pr = 0.0, double pi = 0.0) {real = pr;imag = pi;};virtual ~CComplex();// 重载插入运算符; friend ostream& operator<<(ostream&, const CComplex&);
      };
      
    • C C o m p l e x {\rm CComplex} CComplex类实现文件 ( C C o m p l e x . c p p ) ({\rm CComplex.cpp}) (CComplex.cpp)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:复数类实现文件。*/#include "CComplex.h"CComplex::~CComplex() {
      }// 重载插入运算符实现; 
      ostream& operator<<(ostream& os, const CComplex& c) {os << "(" << c.real << "," << c.imag << "i" << ")" << endl;return os;
      }
      
    • 程序主文件 ( m a i n . c p p ) ({\rm main.cpp}) (main.cpp)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:程序主文件。*/
      #include "CComplex.h"int main() {CComplex a(1, 2);cout << a;return 0;
      }
      
  • 提取运算符重载的语法格式:

    istream& operator>>(istream& is,const T& t)
    {...;	// 函数体;return is;
    }
    
    • 第一个参数:为输入流 i s t r e a m {\rm istream} istream对象的引用,函数返回值必须是这个引用对象;
    • 第二个参数:为提取的对象, T {\rm T} T是用户自定义的类, t {\rm t} t为该类的对象名;
  • 提取运算符重载实例:复数类的输入 ( C o m p l e x 2 ) ({\rm Complex2}) (Complex2)

    • C C o m p l e x {\rm CComplex} CComplex类定义头文件 ( C C o m p l e x . h ) ({\rm CComplex.h}) (CComplex.h)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:复数类定义头文件。*/
      #include <iostream>using namespace std;class CComplex {protected:double real;				// 复数的实部;double imag;				// 复数的虚部;public:CComplex(double pr = 0.0, double pi = 0.0) {real = pr;imag = pi;};virtual ~CComplex();// 重载插入运算符;friend ostream& operator<<(ostream&, const CComplex&);// 重载提取运算符;friend istream& operator>>(istream&, CComplex&);
      };
      
    • C C o m p l e x {\rm CComplex} CComplex类实现文件 ( C C o m p l e x . c p p ) ({\rm CComplex.cpp}) (CComplex.cpp)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:复数类实现文件。*/#include "CComplex.h"CComplex::~CComplex() {
      }// 重载插入运算符实现;
      ostream& operator<<(ostream& os, const CComplex& c) {os << "(" << c.real << "," << c.imag << "i" << ")" << endl;return os;
      }// 重载提取运算符实现;
      istream& operator>>(istream& is, CComplex& c) {cout << "请输入一个复数:";is >> c.real >> c.imag;return is;
      }
      
    • 程序主文件 ( m a i n . c p p ) ({\rm main.cpp}) (main.cpp)

      /*** 作者:罗思维* 时间:2024/03/31* 描述:程序主文件。*/
      #include "CComplex.h"int main() {CComplex a;cin >> a;cout << a;return 0;
      }
      
12.4 文件操作
  • C {\rm C} C++中对文件的读/写是通过流来操作的,操作文件的流称为文件流;

  • 文件是一组由有限且相关的数据组成的有序集合,"有限"指文件中的数据有最大限度,"相关"指这些数据有关联性;

  • 文件通常存储在外部存储设备上,当程序需要使用文件时,才将其中的数据读入内存;

  • 文件可以分为:普通文件和设备文件;

    • 普通文件:指存储在外部设备上的文件;
    • 设备文件:指与计算机主机相关联的各种外部设备,如:显示器、打印机、鼠标、键盘等;
  • 按照文件存储时的编码方式分为:文本文件( A S C I I {\rm ASCII} ASCII码文件)和二进制文件。

    • 文本文件:此类文件在存储时,以 A S C I I {\rm ASCII} ASCII码作为内容来存储,每一个字符对应文件中的一个字节,这些字节按照顺序被存储在磁盘上;
    • 二进制文件:将其内容按照二进制编码的方式来存放的文件;
  • 文本文件和二进制文件存储举例:

    18

  • 在对文本文件进行 I / O {\rm I/O} I/O操作时,需要进行格式转换,二进制文件不需要进行转换;

  • 对文件进行 I / O {\rm I/O} I/O操作的步骤:

    • 打开文件:在读写文件前,需要定义一个文件流类的对象,并用该对象打开文件,得到文件的一个句柄;
    • 读写文件:打开文件后,文件对象中会有一个指向文件中当前位置的指针,该指针的初始位置取决于打开文件时开发者设置的参数,默认情况为 0 0 0;每次从文件读出数据或向文件写入信息后,文件指针自动向后移动相应的字节,对于文本文件,文件指针移动一个字节,对于二进制文件,由数据类型决定;读文件时,如果文件指针移到文件的末尾,则读出的内容是文件结束符;
    • 关闭文件:完成文件的所有操作,需要关闭文件;
  • 常用的文件流对象有: i f s t r e a m 、 o f s t r e a m 、 f s t r e a m {\rm ifstream、ofstream、fstream} ifstreamofstreamfstream

    • i f s t r e a m {\rm ifstream} ifstream:输入文件流对象;
    • o f s t r e a m {\rm ofstream} ofstream:输出文件流对象;
    • f s t r e a m {\rm fstream} fstream:输入/输出文件流对象;
  • 打开文件前,先根据需要进行的操作声明流对象:

    ifstream file_in;			// 建立输入文件流对象;
    ofstream file_out;			// 建立输出文件流对象;
    fstream file_io;			// 建立输入/输出文件流对象;
    
  • 打开文件的两种方式:一是通过文件流的构造函数,二是利用成员函数 o p e n ( ) {\rm open()} open()

    // 1.利用文件流对象构造函数打开文件;
    ofstream file_out("C:\\a_out.dat",ios::out|ios::binary);	// 以二进制方式打开输出文件;
    ifstream file_in("C:\\a_in.dat",ios::in|ios::binary);		// 以二进制方式打开输入文件;// 2.常用文件流对象构造函数:
    ifstream::ifstream(const char*,int=ios::in,int=filebuf::openprot);
    ofstream::ofstream(const char*,int=ios::out,int=filebuf::openprot);
    fstream::fstream(const char*,int,int=filebuf::openprot);// 3.文件流类的成员函数open()原型:
    void open(const char *,int);// 4.三个常用的文件流的默认成员函数原型:
    void ifstream::open(const char*,int=ios::in);
    void ofstream::open(const char*,int=ios::out);
    void fstream::open(const char*,int);// 4.1 参数说明:
    // 参数1:代表文件名的字符串,一般需要完整的路径名,若文件在与exe相同的目录,则可以使用相对路径;
    // 参数2:文件的打开方式;
    

    文件的打开方式:

    常用 常用 常用 作用 作用 作用
    i o s : : i n {\rm ios::in} ios::in 打开文件用于数据输入 , 即从文件中读数据 打开文件用于数据输入,即从文件中读数据 打开文件用于数据输入,即从文件中读数据
    i o s : : o u t {\rm ios::out} ios::out 打开文件用于数据输出 , 即向文件中写数据 打开文件用于数据输出,即向文件中写数据 打开文件用于数据输出,即向文件中写数据
    i o s : : a t e {\rm ios::ate} ios::ate 打开文件后将文件指针置在文件尾部 打开文件后将文件指针置在文件尾部 打开文件后将文件指针置在文件尾部
    i o s : : a p p {\rm ios::app} ios::app 打开文件用于追加数据 , 文件指针始终指向文件尾部 打开文件用于追加数据,文件指针始终指向文件尾部 打开文件用于追加数据,文件指针始终指向文件尾部
    i o s : : t r u n c {\rm ios::trunc} ios::trunc 当打开文件已存在时 , 则清除其内容 , 即擦除以前所有数据 , 使之成为空文件 当打开文件已存在时,则清除其内容,即擦除以前所有数据,使之成为空文件 当打开文件已存在时,则清除其内容,即擦除以前所有数据,使之成为空文件
    i o s : : n o c r e a t e {\rm ios::nocreate} ios::nocreate 如果打开文件不存在 , 则不建立任何文件 , 返回打开失败信息 如果打开文件不存在,则不建立任何文件,返回打开失败信息 如果打开文件不存在,则不建立任何文件,返回打开失败信息
    i o s : : n o r e p l a c e {\rm ios::noreplace} ios::noreplace 如果打开文件已存在 , 不进行覆盖 , 当文件存在时 , 返回错误信息 如果打开文件已存在,不进行覆盖,当文件存在时,返回错误信息 如果打开文件已存在,不进行覆盖,当文件存在时,返回错误信息
    i o s : : b i n a r y {\rm ios::binary} ios::binary 以二进制方式打开文件 , 在不指定的情况下默认以文本文件方式打开文件 以二进制方式打开文件,在不指定的情况下默认以文本文件方式打开文件 以二进制方式打开文件,在不指定的情况下默认以文本文件方式打开文件

    使用符号"|"将常量组合,控制打开文件的多种属性,如下:

    ios::in|ios::nocreate;		// 文件打开用于数据输入,若打开文件不存在,则返回打开失败信息;
    ios::out|ios::noreplace;	// 文件打开用于数据输出,若打开文件存在,则返回打开失败信息;
    ios::in|ios::out;			// 文件打开既用于数据输入,又用于数据输出;
    ios::app|ios::nocreate;		// 文件打开后指针在文件尾,用于追加数据,若打开文件不存在,返回打开失败信息;
    ios::in|ios::out|ios::binary;	// 文件以二进制方式打开,既用于数据输入,又用于输出输出;
    
  • 检查文件是否打开成功,使用 f a i l ( ) {\rm fail()} fail()成员函数判定,原型如下:

    bool fail();	// 打开失败,返回true;打开成功,返回false;
    
  • 文件操作实例:打开一个文件并向其中写入文本数据,如果文件不存在,则新建一个文件,如果文件存在,则以追加方式写入数据 ( e x a m p l e 12 _ 3. c p p ) ({\rm example12\_3.cpp}) (example12_3.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:打开一个文件并向其中写入文本数据。*/
    #include <iostream>
    #include <fstream>using namespace std;int main() {ofstream file_out;file_out.open("./data.txt", ios::out | ios::app);if (file_out.fail()) {cerr << "file data.txt open fail!" << endl;return 1;}file_out.close();		// 关闭文件;return 0;
    }
    
  • 向文本文件输出数据的两种方法:一是使用插入操作符"<<",二是调用成员函数 ( p u t ) ({\rm put}) (put)

  • 文本文件数据输出实例 ( e x a m p l e 12 _ 4. c p p ) ({\rm example12\_4.cpp}) (example12_4.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:文本文件的输出。 */
    #include <iostream>
    #include <fstream>using namespace std;int main() {ofstream file_out("./data2.txt");// 利用插入操作符进行数据输出; file_out << "A B C D E F G" << endl;file_out << "H I J K L M N" << endl;file_out << "O P Q R S T" << endl;file_out << "U V W X Y Z" << endl;// 利用put()成员函数进行数据输出。 for (int i = 65; i <= 90; i++) {file_out.put(i);			// 输出单个字母; file_out.put(32);			// 输出一个空格; switch (i) {case 71:file_out.put(10);	// 输出换行; break;case 78:file_out.put(10);break;case 84:file_out.put(10);break;case 90:file_out.put(10);break;default:break;}}file_out.close();return 0;
    }
    
  • 将文本文件中的数据读入内存的三种方法:一是利用提取操作符">>",二是调用成员函数 g e t ( ) {\rm get()} get(),三是调用成员函数 g e t l i n e ( ) {\rm getline()} getline()

    // 1.利用提取操作符">>",原型如下:
    istream& operator >>(C++标准类型 &);// 2.调用成员函数get();
    int get();					// 读取字符;
    istream& get(char& c);		// 读取一个字符并存储到c中;// 3.调用成员函数getline();
    istream& getline(char * buffer,int len,char="\n");// 参数说明:
    // getline()用于读入文本文件中的一块文本;
    // 参数1:读入数据转存到的字符串,即将读入的字符存储到buffer;
    // 参数2:读入字符块的长度;
    // 参数3:默认为换行,当遇到换行时,则停止本次读取;
    
  • 利用提取操作符读取文本数据 ( e x a m p l e 12 _ 5. c p p ) ({\rm example12\_5.cpp}) (example12_5.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:利用提取操作符读取文本数据。 */
    #include <iostream>
    #include <fstream>using namespace std;int main() {ifstream file_in("./data3.txt", ios::in);			// 打开文件; if (file_in.fail()) {			// 判断文件打开是否成功; cerr << "File data3.txt open fail!" << endl;}char cRead;while (file_in >> cRead) {		// 读取单个字符; cout << cRead << " ";		// 输出单个字符; }file_in.close();				// 关闭文件; return 0;
    }
    
  • 利用 g e t ( ) {\rm get()} get()成员函数读取文本数据 ( e x a m p l e 12 _ 6. c p p ) ({\rm example12\_6.cpp}) (example12_6.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:利用get()成员函数读取文本数据。 */
    #include <iostream>
    #include <fstream>using namespace std;int main() {ifstream file_in("./data3.txt", ios::in);			// 打开文件; if (file_in.fail()) {			// 判断文件是否成功打开; cerr << "File data3.txt open fail!" << endl;}char cRead;while (!file_in.eof()) {		// 判断文件内容是否结束,读取单个字符并输出到屏幕上; cRead = file_in.get();cout << cRead;}file_in.close();				// 关闭文件; return 0;
    }
    
  • 利用提取操作符读取数据时,忽略空格、换行符,利用 g e t ( ) {\rm get()} get()成员函数读取数据时,会将空格、换行符全部读出;

  • 利用 g e t ( c h a r & c ) {\rm get(char\&\ c)} get(char& c)成员函数读取文本数据 ( e x a m p l e 12 _ 7. c p p ) ({\rm example12\_7.cpp}) (example12_7.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:利用get(char& c)成员函数读取文本数据。 */
    #include <iostream>
    #include <fstream>using namespace std;int main() {ifstream file_in("./data3.txt", ios::in);			// 打开文件; if (file_in.fail()) {								// 判断文件打开是否成功; cerr << "File data3.txt open fail!" << endl;}char c;while (!file_in.eof()) {		// 当没有读到文件尾部时,读取单个字符并输出到屏幕上; file_in.get(c);cout << c;}file_in.close();				// 关闭文件; return 0;
    }
    
  • 利用 g e t l i n e ( ) {\rm getline()} getline()成员函数读取文本数据 ( e x a m p l e 12 _ 8. c p p ) ({\rm example12\_8.cpp}) (example12_8.cpp)

    /*** 作者:罗思维* 时间:2024/04/01* 描述:利用getline()成员函数读取文本数据。*/
    #include <iostream>
    #include <fstream>
    #include <string.h>using namespace std;int main() {ifstream file_in("./data3.txt", ios::in);		// 打开文件;if (file_in.fail()) {			// 判断文件打开是否成功;cerr << "File data3.txt open fail!" << endl;}char* buf = new char[128];memset(buf, 0, 128);			// 清空buf内容;while (!file_in.eof()) {file_in.getline(buf, 128);	// 逐行读取数据到buf中;cout << buf << endl;memset(buf, 0x00, 128);		// 清空buf内容;}delete[] buf;					// 释放动态内存;file_in.close();				// 关闭文件;return 0;
    }
    
  • 向二进制文件写入数据是利用流类 o s t r e a m {\rm ostream} ostream w r i t e ( ) {\rm write()} write()函数实现,原型如下:

    ostream& write(const char * buffer,int len);// 参数说明:
    // 参数1:buffer用于存储需要写入文件的内容;
    // 参数2:len是设定写入数据的长度;
    
  • 向二进制文件写入数据实例 ( e x a m p l e 12 _ 9. c p p ) ({\rm example12\_9.cpp}) (example12_9.cpp)

    /*** 作者:罗思维* 时间:2024/04/02* 描述:向二进制写入数据。* 数据:1 2 3 4 5 6 7 8 9*  	A B C D E F G*/
    #include <iostream>
    #include <fstream>using namespace std;int main() {// 打开二进制文件; ofstream file_out("./data.dat", ios::out | ios::binary | ios::trunc);// 如果文件打开失败,则显示错误信息; if (!file_out) {cerr << "File data.dat open fail!" << endl;exit(1);}// 写入1,2,3,4,5,6,7,8,9; for (int i = 49; i <= 57; i++) {file_out.write((char*)&i, sizeof(int));}// 写入A,B,C,D,E,F,G for (int i = 65; i <= 70; i++) {file_out.write((char*)&i, sizeof(int));}file_out.close();return 0;
    }
    
  • 将二进制文件作为输入文件,则读取其数据时使用流类 i s t r e a m {\rm istream} istream的成员函数 r e a d ( ) {\rm read()} read(),函数原型为:

    istream& read(char * buffer,int len);// 参数说明:
    // 参数1:buffer用于存储需要读取的内容;
    // 参数2:len是设定读取数据的长度;
    
  • 读取二进制文件数据实例,每次只读一个数值 ( e x a m p l e 12 _ 10. c p p ) ({\rm example12\_10.cpp}) (example12_10.cpp)

    /*** 作者:罗思维* 时间:2024/04/02* 描述:从二进制读入数据。* 数据:1 2 3 4 5 6 7 8 9*  	 A B C D E F G*/
    #include <iostream>
    #include <fstream>using namespace std;int main() {ifstream file_in("./data.dat", ios::in | ios::binary);if (!file_in) {cerr << "File data.dat open fail!" << endl;exit(1);}int n;while (!file_in.eof()) {file_in.read((char*)&n, sizeof(n));cout << (char)n << " ";}file_in.close();return 0;
    }
    
  • 读取二进制文件数据实例,一次性从文件中读出多个字节 ( e x a m p l e 12 _ 11. c p p ) ({\rm example12\_11.cpp}) (example12_11.cpp)

    /*** 作者:罗思维* 时间:2024/04/02* 描述:从二进制读入数据。* 数据:1 2 3 4 5 6 7 8 9*  	 A B C D E F*/
    #include <iostream>
    #include <fstream>
    #include <string.h>using namespace std;// 定义函数,输出字符串; 
    void print(char* &str, int len) {for (int i = 0; i < len; i++) {cout << str[i];}
    }int main() {ifstream file_in("./data.dat", ios::in | ios::binary);if (!file_in) {cerr << "File data.dat open fail!" << endl;exit(1);}char* buf = new char[11];		// 开辟空间; memset(buf, 0x00, 11);			// 清空空间内容; while (!file_in.eof()) {file_in.read(buf, 10);		// 一次性读取10个字节; print(buf, 10);memset(buf, 0x00, 10);		// 清空空间内容; }delete[] buf;					// 释放内存; file_in.close();				// 关闭文件; return 0;
    }
    
  • 与文件相关联的指针:读取指针和写入指针。

    • 读取指针:指向文件当前要读取的数据的位置;
    • 写入指针:指向现在正要写入数据的位置;
  • 控制文件指针的两个函数:

    • 流类 i s t r e a m {\rm istream} istream的成员函数 s e e k g ( ) {\rm seekg()} seekg()用于把读文件指针移动到指定位置,函数原型:

      istream& seekg(long dis,seek_dir ref=ios::beg);
      
    • 流类 o s t r e a m {\rm ostream} ostream的成员函数 s e e k p ( ) {\rm seekp()} seekp()用于把写文件指针移动到指定位置,函数原型:

      ostream& seekp(long dis,seek_dir ref=ios::beg);
      
    • 参数 d i s {\rm dis} dis:文件指针需要移动的字节数,当其为正数时,表示向后移,向文件末尾,当其为负数时,表示向前移,向文件开头;

    • 参数 s e e k _ d i r {\rm seek\_dir} seek_dir i o s {\rm ios} ios根基类中定义的枚举类型;

      enum seek_dir {beg = 0,cur = 1,end =2};// ios::beg:文件的开始位置;
      // ios::cur:当前位置;
      // ios::end:结束位置;
      
  • 通过文件指针移动把二进制文件数据显示到屏幕上 ( e x a m p l e 12 _ 12. c p p ) ({\rm example12\_12.cpp}) (example12_12.cpp)

    /*** 作者:罗思维* 时间:2024/04/02* 描述:从二进制读入数据。* 数据:1 2 3 4 5 6 7 8 9*  	 A B C D E F*/
    #include <iostream>
    #include <fstream>using namespace std;int main() {// 打开二进制文件; ifstream file_in("./data.dat", ios::in | ios::binary);// 判断文件是否打开成功; if (!file_in) {cerr << "File data.dat open fail!" << endl;exit(1);}int n;// 移动指针,9x4个字节; file_in.seekg(9 * 4, ios::beg);while (!file_in.eof()) {file_in.read((char*)&n, sizeof(n));		// 读取二进制文件数据; cout << (char)n << " ";}file_in.close();							// 关闭文件; return 0;
    }
    
12.5 实战

项目需求 :编写一个学生信息管理系统,要求将学生数据保存在文件中,提供查询、修改、删除学生信息的功能。

代码实现 ( S t u M a n a g e I n f o S y s t e m ) {\rm (StuManageInfoSystem)} (StuManageInfoSystem)

  • S t u d e n t . h {\rm Student.h} Student.h

    /*** 作者:罗思维* 时间:2024/04/03* 描述:定义存储学生信息结构体。 */
    #pragma once
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <vector>using namespace std;#define NULL 0
    int const MAX_NUM = 20;
    #define LEN sizeof(struct student)// 定义一个学生考试信息的结构体;
    /* 	参数说明:* 	name:	姓名;*  sex:	性别;*  id:	准考证号;*  score:	分数;*  total:	总分数;
    */
    struct student {char name[MAX_NUM];char sex[MAX_NUM];long int id;int score[4];int total;struct student *next;
    };
    
  • I n f o r m a t i o n . h {\rm Information.h} Information.h

    /*** 作者:罗思维* 时间:2024/04/03* 描述:学生信息类定义头文件。 */
    #pragma once
    #include "Student.h"static int n = 0;
    class CInformation {private:student *p1, *p2, *p3, *head, st;public:CInformation();virtual ~CInformation();student* create();					// 建立链表函数; void output(student* head);			// 输出链表; int count(student* head);			// 函数count统计考生总数; student* insert(student* head);		// 指针函数insert添加考生信息; student* cancel(student* head, long int num);	// 指针函数cancel删除考生信息; student* find(student* head, long int num);		// 指针函数find查找考生信息; void sort(student* head);			// 考生总分从大到小排列输出; void average(student* head);		// 考生成绩平均分; void save(student* head);			// 保存信息函数; student* Read();					// 读取信息函数; 
    };
    
  • I n f o r m a t i o n . c p p {\rm Information.cpp} Information.cpp

    /*** 作者:罗思维* 时间:2024/04/03* 描述:学生信息各种接口函数实现。 */
    #include "Information.h"
    #include "Student.h"
    #include <string.h>CInformation::CInformation() {
    }CInformation::~CInformation() {
    }// 新建学生信息成员函数;
    student *CInformation::create(void) {char ch[MAX_NUM];n = 0;p1 = p2 = (student *) malloc(LEN);cout << "------<<请建立学生考试信息表>>------" << endl;cout << "姓名:";cin >> ch;head = NULL;while (strcmp(ch, "!") != 0) {p1 = (student *)malloc(LEN);strcpy(p1->name, ch);cout << "性别:";cin >> p1->sex;cout << "准考证号(8位):";cin >> p1->id;cout << "数学成绩:";cin >> p1->score[0];cout << "物理成绩:";cin >> p1->score[1];cout << "英语成绩:";cin >> p1->score[2];cout << "C语言成绩:";cin >> p1->score[3];p1->total = p1->score[0] + p1->score[1] + p1->score[2] + p1->score[3];if (n == 0) {head = p1;} else {p2->next = p1;}p2 = p1;n++;cout << "姓名:";cin >> ch;}p2->next = NULL;return (head);
    }// 输出学生信息成员函数;
    void CInformation::output(student *head) {if (head == NULL) {cout << "这是一个空表,请先输入考生成绩.\n";} else {cout << "-------------------------\n";cout << " *学生考试成绩信息表*\n";cout << "-------------------------\n";cout << "准考证号 姓名 性别 数学 物理 英语 C语言 平均分 总分\n";p1 = head;do {cout << setw(8) << p1->id<< setw(9) << p1->name<< setw(8) << p1->sex<< setw(8) << p1->score[0]<< setw(9) << p1->score[1]<< setw(9) << p1->score[2]<< setw(9) << p1->score[3]<< setw(9) << p1->total / 4.0<< setw(9) << p1->total << endl;cout << "-------------------------\n";p1 = p1->next;} while (p1 != NULL);}
    }// 获得存储的学生数成员函数;
    int CInformation::count(struct student *head) {if (head == NULL) {return (0);} else {return (1 + count(head->next));}
    }// 插入存储的学生信息成员函数;
    student  *CInformation::insert(student *head) {cout << "\t---------------<<请输入新增学生成绩信息>>---------------\n" << endl;p1 = (student *)malloc(LEN);cout << "准考证号(8位):";cin >> p1->id;cout << "姓名:";cin >> p1->name;cout << "性别:";cin >> p1->sex;cout << "数学成绩:";cin >> p1->score[0];cout << "物理成绩:";cin >> p1->score[1];cout << "英语成绩:";cin >> p1->score[2];cout << "C语言成绩:";cin >> p1->score[3];p1->total = p1->score[0] + p1->score[1] + p1->score[2] + p1->score[3];p2 = head;if (head == NULL) {head = p1;p1->next = NULL;} else {while ((p1->id > p2->id) && (p2->next != NULL)) {p3 = p2;p2 = p2->next;}if (p1->id <= p2->id) {if (head == p2) {p1->next = head;head = p1;} else {p3->next = p1;p1->next = p2;}} else {p2->next = p1;p1->next = NULL;}}n++;cout << "\t---------------<<你输入的学生信息已经成功插入>>---------------\n" << endl;return head;
    }// 删除某学生信息成员函数;
    student *CInformation::cancel(student *head, long int num) {if (head == NULL) {return (head);} else {p1 = head;while (num != p1->id && p1->next != NULL) {p2 = p1;p1 = p1->next;}if (num == p1->id) {if (p1 == head) {head = p1->next;} else {p2->next = p1->next;}cout << "删除准考证号为" << num << "的学生\n";n--;}return (head);}
    }// 查找某学生信息成员函数;
    student *CInformation::find(student *head, long int num) {if (head == NULL) {cout << "这是一个空表,请先输入考生成绩.\n";return (head);} else {p1 = head;while (num != p1->id && p1->next != NULL) {p1 = p1->next;}if (num == p1->id) {cout << setw(8) << p1->id<< setw(9) << p1->name<< setw(8) << p1->sex<< setw(8) << p1->score[0]<< setw(9) << p1->score[1]<< setw(9) << p1->score[2]<< setw(9) << p1->score[3]<< setw(9) << p1->total / 4.0<< setw(9) << p1->total << endl;cout << "-------------------------\n";} else {cout << "没找到准考证号为" << num << "的学生.\n";}return (head);}
    }// 信息排序成员函数;
    void CInformation::sort(student *head) {int i, k, m = 0, j;student *p[MAX_NUM];if (head != NULL) {m = count(head);cout << "-------------------------\n";cout << "*学生考试成绩统计表*\n";cout << "-------------------------\n";cout << "准考证号 姓名 性别 数学 物理 英语 C语言 平均分 总分 名次\n";cout << "-------------------------\n";p1 = head;for (k = 0; k < m; k++) {p[k] = p1;p1 = p1->next;}for (k = 0; k < m - 1; k++) {for (j = k + 1; j < m; j++) {if (p[k]->total < p[j]->total) {p2 = p[k];p[k] = p[j];p[j] = p2;}}}for (i = 0; i < m; i++) {cout << setw(8) << p[i]->id<< setw(9) << p[i]->name<< setw(6) << p[i]->sex<< setw(7) << p[i]->score[0]<< setw(7) << p[i]->score[1]<< setw(7) << p[i]->score[2]<< setw(7) << p[i]->score[3]<< setw(8) << p[i]->total / 4.0<< setw(7) << p[i]->total<< setw(9) << i + 1 << endl;cout << "-------------------------\n";}}
    }// 计算学生各科平均成绩成员函数;
    void CInformation::average(student *head) {int k, m;float arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0;if (head == NULL) {cout << "这是一个空表,请先输入考生成绩.\n";} else {m = count(head);p1 = head;for (k = 0; k < m; k++) {arg1 += p1->score[0];arg2 += p1->score[1];arg3 += p1->score[2];arg4 += p1->score[3];p1 = p1->next;}arg1 /= m;arg2 /= m;arg3 /= m;arg4 /= m;cout << "*全班单科成绩平均分*\n";cout << "-------------------------\n";cout << "数学平均分:" << setw(7) << arg1<< "物理平均分:" << setw(7) << arg2<< "英语平均分:" << setw(7) << arg3<< "C语言平均分:" << setw(7) << arg4 << endl;cout << "-------------------------\n";}
    }// 信息保存成员函数;
    void CInformation::save(student *head) {ofstream out("data.txt", ios::out);out << count(head) << endl;while (head != NULL) {out << head->name << "\t"<< head->id << "\t" << "\t"<< head->sex << "\t"<< head->score[0] << "\t"<< head->score[1] << "\t"<< head->score[2] << "\t"<< head->score[3] << "\t"<< head->total << endl;head = head->next;}
    }// 学生信息读取成员函数;
    student *CInformation::Read() {int i = 0;p1 = p2 = (student *) malloc(LEN);head = NULL;ifstream in("data.txt", ios::out);in >> i;if (i == 0) {cout << "data.txt文件中的数据为空,请先输入数据." << endl;return 0;} else {cout << "-------------------------\n";for (; i > 0; i--) {p1 = (student *)malloc(LEN);in >> st.name >> st.id >> st.sex>> st.score[0] >> st.score[1]>> st.score[2] >> st.score[3]>> st.total;strcpy(p1->name, st.name);p1->id = st.id;strcpy(p1->sex, st.sex);p1->score[0] = st.score[0];p1->score[1] = st.score[1];p1->score[2] = st.score[2];p1->score[3] = st.score[3];p1->total = st.total;if (n == 0) {head = p1;} else {p2->next = p1;}p2 = p1;n++;cout << " " << p1->name << "\t"<< p1->id << "\t" << "\t"<< p1->sex << "\t"<< p1->score[0] << "\t"<< p1->score[1] << "\t"<< p1->score[2] << "\t"<< p1->score[3] << "\t"<< p1->total << endl;cout << "-------------------------\n";}cout << "数据已经成功读取完毕." << endl;p2->next = NULL;return (head);}
    }
    
  • m a i n . c p p {\rm main.cpp} main.cpp

    /*** 作者:罗思维* 时间:2024/04/03* 描述:程序主文件。 */
    #include "Student.h"
    #include "Information.h"vector<student> stu;int main() {CInformation person;student *head = NULL;int choice;long int i;do {cout << " 1.输入学生成绩" << endl;cout << " 2.显示学生成绩" << endl;cout << " 3.排序统计成绩" << endl;cout << " 4.查找学生成绩" << endl;cout << " 5.增加学生成绩" << endl;cout << " 6.删除学生成绩" << endl;cout << " 7.安全退出系统" << endl;cout << " 请输入您的选择(0-7):";cin >> choice;switch (choice) {case 0:head = person.Read();break;case 1:head = person.create();break;case 2:person.output(head);break;case 3:person.sort(head);person.average(head);cout << "参加考试的学生人数为:" << person.count(head) << "人\n";break;case 4:cout << "请输入要查找的准考证号(8位):";cin >> i;person.find(head, i);break;case 5:head = person.insert(head);person.output(head);break;case 6:cout << "请输入要删除的准考证号(8位):";cin >> i;head = person.cancel(head, i);person.output(head);break;case 7:person.save(head);break;default:cout << "输入有误,请重新输入.\n";break;}} while (choice != 7);
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/590071.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年购买阿里云服务器多少钱?100元-5000元预算

2024年阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核4G服务…

E5071C是德科技E5071C网络分析仪

181/2461/8938产品概述&#xff1a; E5071C ENA 矢量网络分析仪&#xff0c;9 kHz 至 20 GHz&#xff0c;配有增强型 TDR 测量选件。E5071C 网络分析仪具有较高的射频性能和较快的速度&#xff0c;并具有宽频率范围和全面的功能。它是制造和研发工程师们测试频率范围在 20 GHz…

2024年 前端JavaScript 进阶 第3天 笔记

3.1-JS进阶-内容和两种编程思想 3.2-构造函数实现封装以及存在 3.3-原型对象prototype 3.4-数组扩展案例-求最大值和数组求和 3.5-constructor属性以及应用 3.6-对象原型proto 3.7-原型继承 3.8-原型链以及instanceof运算符 3.9-综合案例-模态框构造函数写法 3.10-综合案例-0pe…

《PDVC》论文笔记

PS&#xff1a;模型代码解释清明后出 原文链接&#xff1a; [2108.07781v1] End-to-End Dense Video Captioning with Parallel Decoding (arxiv.org) 原文笔记&#xff1a; What&#xff1a; End-to-End Dense Video Captioning with Parallel Decoding 并行解码的端到端…

[C#]使用OpencvSharp去除面积较小的连通域

【C介绍】 关于opencv实现有比较好的算法&#xff0c;可以参考这个博客OpenCV去除面积较小的连通域_c#opencv 筛选小面积区域-CSDN博客 但是没有对应opencvsharp实现同类算法&#xff0c;为了照顾懂C#编程同学们&#xff0c;因此将 去除面积较小的连通域算法转成C#代码。 方…

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换

医学图像处理 利用pytorch实现的可用于反传的Radon变换和逆变换 前言代码实现思路实验结果 前言 Computed Tomography&#xff08;CT&#xff0c;计算机断层成像&#xff09;技术作为如今医学中重要的辅助诊断手段&#xff0c;也是医学图像研究的重要主题。如今&#xff0c;随…

【WebSocket】快速入门 springboot中使用

WebSocket 介绍 WebSocket缺点&#xff1a; 服务器长期维护长连接需要一定的成本 各个浏览器支持程度不一 WebSocket 是长连接&#xff0c;受网络限制比较大&#xff0c;需要处理好重连 结论&#xff1a; WebSocket并不能完全取代HTTP&#xff0c;它只适合在特定的场景下使用…

C++ 2024-4-2 作业

1.模板类实现顺序栈 #include <iostream> #define MAX 8 using namespace std; template<typename T> class stack {T data[MAX];int top; public:stack():top(-1){}bool empty_stack();bool full_stack();void push_stack(T data);void pop_stack();void show();…

Phpstorm配置Xdebug

步骤 1、先去官网找到对应的php xdebug的版本 2、配置phpstorm断点调试 网址&#xff1a;https://xdebug.org/ 查看php对应的xdebug版本&#xff1a;Xdebug: Support — Tailored Installation Instructions 1.1查看对应php xdebug版本 全选&#xff0c;复制到目标网址 我…

Flutter中setState函数的使用注意事项

文章目录 Flutter中setState函数的使用注意事项只能在具有State对象的类中使用不要在build方法中使用将状态更新逻辑放在setState方法内部避免频繁调用使用回调函数更新状态 Flutter中setState函数的使用注意事项 setState()函数是Flutter中非常重要的一个函数&#xff0c;它用…

antd/x6-graph——实现流程图绘制功能——技能提升

效果图&#xff1a; 解决步骤1&#xff1a;安装"antv/x6": "^1.35.0" npm install antv/x61.35.0安装指定版本的antv/x6插件 解决步骤2&#xff1a;配置tools文件 在assets/js中新增一个graphTools.js文件 内容如下&#xff1a; /* antv x6图谱相关…

基于深度学习的吸烟检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要&#xff1a;本文深入研究了基于YOLOv8/v7/v6/v5等深度学习模型的吸烟行为检测系统&#xff0c;核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法&#xff0c;进行性能指标对比&#xff1b;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码&#xff0c;及…