C++ IOStream

打印 上一主题 下一主题

主题 1009|帖子 1009|积分 3027


  • IOStream

    • 类流特性

      • 不可赋值和复制
      • 缓冲
      • 重载了<< >>


  • 状态位

    • 示例

  • 状态位利用函数
  • cout
  • cin

    • get
    • get(s,n)/get(s,n,d):
    • getline

  • other
  • if(!fs)/while(cin)

    • operator void*()与 operator!()
    • 代码示例

  • File Stream

    • open 函数

      • 文件打开方式


  • 文件读写

    • 读写接口

      • 一次读一个字符
      • 一次读一行
      • 读写二进制


  • 文件指针相关的函数
  IOStream


类流特性

不可赋值和复制

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. void print(fstream fs) //fstream& fs
  5. {
  6. }
  7. int main()
  8. {
  9.     fstream fs1,fs2;
  10.     fs1 = fs2;
  11.     fstream fs3(fs2);
  12.     print(fs3);
  13.   return 0;
  14. }
复制代码
差别于标准库其他 class 的"值语意",iostream 是"对象语意",即 iostream
是 non-copyable。这是准确的,因为如果 fstream 代表一个文件的话,拷贝一个
fstream 对象意味着什么呢?表示打开了两个文件吗?如果烧毁一个 fstream 对象,它会关闭文件句柄,那么另一个 fstream copy 对象会因此受影响吗?
C++ 同时支持"数据抽象"和"面向对象编程",其实主要就是"值语意"与"对象语意
"的区别,标准库里的 complex<> 、pair<>、vector<>、 string 等等都是值语意,
拷贝之后就与原对象离开关系,就跟拷贝一个 int 一样。而我们自己写的 Employee
class、TcpConnection class 通常是对象语意,拷贝一个 Employee 对象是没有
意义的,一个雇员不会变成两个雇员,他也不会领两份薪水。拷贝 TcpConnection 对
象也没故意义,系统里边只有一个 TCP 连接,拷贝 TcpConnection 对象不会让我们
拥有两个连接。因此如果在 C++ 里做面向对象编程,写的 class 通常应该禁用 copy
constructor 和 assignment operator。
缓冲

  1. 下面几种情况会导致刷缓冲
  2. 1,程序正常结束,作为 main 函数结束的一部分,将清空所有缓冲区。
  3. 2,缓冲区满,则会刷缓冲。
  4. 3,endl, flush 也会刷缓冲。
复制代码
重载了<< >>

  1. #include <iostream>  // 引入标准输入输出流库
  2. #include <fstream>    // 引入文件流库
  3. using namespace std;  // 使用标准命名空间
  4. int main()
  5. {
  6.     // 创建一个 fstream 对象 fs,打开名为 "abc.txt" 的文件,模式为输入、输出和截断(清空文件内容)
  7.     fstream fs("abc.txt", ios::in | ios::out | ios::trunc);
  8.     // 检查文件是否成功打开
  9.     if (!fs)
  10.     {
  11.         // 如果文件打开失败,输出错误信息
  12.         cout << "error" << endl;
  13.     }
  14.     // 向文件中写入数据 "1 2 3"
  15.     fs << 1 << " " << 2 << " " << 3;
  16.     // 将文件指针重新定位到文件开头
  17.     fs.seekg(0, ios::beg);
  18.     // 声明三个整数变量 x, y, z
  19.     int x, y, z;
  20.     // 从文件中读取数据到变量 x, y, z
  21.     fs >> x >> y >> z;
  22.     // 输出读取到的数据
  23.     cout << x << y << z;
  24.     // 程序结束,返回 0 表示成功
  25.     return 0;
  26. }
复制代码
状态位

大部分情况下 , 我们可能并不关心这些标记状态位 , 好比我们从前用到的 cin/cout。
但是在循环读写中,这些标记位确实大用用途。好比,用于判断文件竣事
标记的位。
ios_base.h 中状态位的定义如下:
  1. /// Indicates a loss of integrity in an input or output sequence (such
  2. /// as an irrecoverable read error from a file).
  3. static const iostate badbit = _S_badbit;
  4. /// Indicates that an input operation reached the end of an input sequence.
  5. static const iostate eofbit = _S_eofbit;
  6. /// Indicates that an input operation failed to read the expected
  7. /// characters, or that an output operation failed to generate the
  8. /// desired characters.
  9. static const iostate failbit = _S_failbit;
  10. /// Indicates all is well.
  11. static const iostate goodbit = _S_goodbit;
复制代码
  1. 在C++标准库中,ios_base.h头文件定义了输入输出流的基础类ios_base,以及与之相关的各种枚举和常量。
  2. 其中,状态位(state flags)用于表示流的状态。
  3. 这些状态位可以通过ios_base类的成员函数进行设置和查询。
  4. 以下是一些常用的状态位:
  5. goodbit:表示流处于正常状态,没有错误。
  6. badbit:表示流发生了致命错误,可能导致数据丢失。
  7. failbit:表示流发生了可恢复的错误,通常是由于格式错误或无效输入。
  8. eofbit:表示流已经到达文件末尾。
  9. 这些状态位可以通过ios_base类的以下成员函数进行操作:
  10. rdstate():返回当前的状态位。
  11. setstate(iostate state):设置指定的状态位。
  12. clear(iostate state = goodbit):清除当前的状态位,并设置为指定的状态位。
复制代码
示例

在这个例子中,我们打开一个文件并检查其状态。
如果文件无法打开,步伐会输堕落误信息并退出。
然后,我们尝试从文件中读取数据,
并检查读取利用后的状态位,以确定是否乐成读取数据或是否到达文件末端。
  1. #include <iostream>
  2. #include <fstream>
  3. int main() {
  4.     std::ifstream file("example.txt");
  5.     if (!file) {
  6.         std::cerr << "无法打开文件" << std::endl;
  7.         return 1;
  8.     }
  9.     // 检查流的状态
  10.     if (file.rdstate() & std::ios_base::failbit) {
  11.         std::cerr << "流发生了可恢复的错误" << std::endl;
  12.     }
  13.     // 读取文件内容
  14.     int data;
  15.     file >> data;
  16.     // 检查读取操作后的状态
  17.     if (file.rdstate() & std::ios_base::eofbit) {
  18.         std::cout << "已到达文件末尾" << std::endl;
  19.     }
  20.     if (file.rdstate() & std::ios_base::failbit) {
  21.         std::cerr << "读取操作失败" << std::endl;
  22.     }
  23.     file.close();
  24.     return 0;
  25. }
复制代码
状态位利用函数

函数功能eof()如果读文件到达文件末端,返回 true。fail()除了与 bad() 同样的情况下会返回 true 以外,加上格式错误时也返回 true , 例如当想要读入一个整数,而获得了一个字母的时间。或是碰到 eof。bad()如果在读写过程中堕落,返回 true 。例如:当我们要对一个不是打开为写状态的文件举行写入时,大概我们要写入的设备没有剩余空间的时间。clear()标识位一旦被置位,这些标记将不会被改变,要想重置以上成员函数所检查的状态标记,你可以使用成员函数 clear(),没有参数。好比:通过函数移动文件指针,并不会使 eofbit 自动重置。good()这是最通用的:如果调用以上任何一个函数返回 true 的话,此函数返回 false 。
  1. 在这段代码中,主要使用了以下几个与输入流状态相关的函数:
  2. cin.eof():
  3. 功能:检查是否到达文件末尾(EOF)。
  4. 返回值:如果到达文件末尾,返回true;否则返回false。
  5. 使用场景:通常在读取文件时使用,用于判断是否已经读取到文件的末尾。
  6. cin.fail():
  7. 功能:检查是否发生格式错误。例如,尝试将非数字字符读取为整数时会触发格式错误。
  8. 返回值:如果发生格式错误,返回true;否则返回false。
  9. 使用场景:用于检测输入操作是否因为格式不匹配而失败。
  10. cin.bad():
  11. 功能:检查是否发生致命错误。例如,流被破坏或硬件故障等。
  12. 返回值:如果发生致命错误,返回true;否则返回false。
  13. 使用场景:用于检测流是否处于不可恢复的错误状态。
  14. cin.good():
  15. 功能:检查流是否处于良好状态,即没有发生任何错误。
  16. 返回值:如果流处于良好状态,返回true;否则返回false。
  17. 使用场景:用于检测流是否可以正常使用。
  18. cin.clear():
  19. 功能:清除流的错误状态标志。调用此函数后,流的failbit和badbit会被清除,流的状态会被重置为良好状态。
  20. 参数:可以传递一个参数来指定要清除的错误标志,默认情况下会清除所有错误标志。
  21. 使用场景:在检测到输入错误后,通常需要调用此函数来清除错误状态,以便继续使用流进行后续的输入操作。
  22. 通过这些函数,程序可以有效地检测和处理输入流中的错误,确保输入操作的可靠性和程序的健壮性。
  23. 在实际应用中,这些函数常用于输入验证和错误处理,以提高程序的容错能力。
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int val;
  6.     // 输出在错误输入操作之前的流状态
  7.     cout << "Before a bad input operation:"
  8.          << "\n cin.eof() : " << cin.eof()  // 检查是否到达文件末尾
  9.          << "\n cin.fail(): " << cin.fail() // 检查是否发生格式错误
  10.          << "\n cin.bad() : " << cin.bad()  // 检查是否发生致命错误
  11.          << "\n cin.good(): " << cin.good() // 检查流是否处于良好状态
  12.          << endl;
  13.     // 尝试从标准输入读取一个整数,可以通过输入非数字字符(如'a')或模拟文件结束(如在Unix系统上按Ctrl+D,在Windows系统上按Ctrl+Z)来触发错误
  14.     cin >> val;
  15.     // 输出在错误输入操作之后的流状态
  16.     cout << "After a bad input operation:"
  17.          << "\n cin.eof() : " << cin.eof()  // 检查是否到达文件末尾
  18.          << "\n cin.fail(): " << cin.fail() // 检查是否发生格式错误
  19.          << "\n cin.bad() : " << cin.bad()  // 检查是否发生致命错误
  20.          << "\n cin.good(): " << cin.good() // 检查流是否处于良好状态
  21.          << endl;
  22.     // 清除流的错误状态标志
  23.     cin.clear();
  24.     // 输出清除错误状态标志后的流状态
  25.     cout << "\n cin.eof() : " << cin.eof()  // 检查是否到达文件末尾
  26.          << "\n cin.fail(): " << cin.fail() // 检查是否发生格式错误
  27.          << "\n cin.bad() : " << cin.bad()  // 检查是否发生致命错误
  28.          << "\n cin.good(): " << cin.good() // 检查流是否处于良好状态
  29.          << endl;
  30.     return 0;
  31. }
复制代码
cout

格式输出:

成员函数:
函数功能ostream& put( char )输出一个字符ostream& write( const char* s, streamsize n )输出一个字符串ostream& operator<<(T v)输出一个值 cin

get

  1. 函数声明
  2. int get();
  3. istream& get (char& c);
  4. istream& get (char* s, streamsize n);          //终止符为'\n'
  5. istream& get (char* s, streamsize n, char delim);
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char ch;
  6.     while((ch = cin.get())!=EOF)
  7.     {
  8.         cout<<ch<<endl;
  9.     }
  10.     while(cin.get(ch))
  11.     {
  12.         cout<<ch<<endl;
  13.     }
  14.     return 0;
  15. }
复制代码
get(s,n)/get(s,n,d):

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char ch;
  6.     char buf[10];
  7.     while(cin.get(buf,10))
  8.     {
  9.         cout<<buf<<endl;
  10.     }
  11.     cout<< "\n cin.eof() : " <<cin.eof()
  12.         << "\n cin.fail(): " <<cin.fail()
  13.         << "\n cin.bad() : " <<cin.bad()
  14.         << "\n cin.good(): " <<cin.good()<<endl;
  15.     return 0;
  16. }
复制代码
  1. 输出:
  2. 12345678901234567890
  3. 123456789
  4. 012345678
  5. 90
  6. cin.eof() : 0
  7. cin.fail(): 1
  8. cin.bad() : 0
  9. cin.good(): 0
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char ch;
  6.     char buf[10];
  7.     while(cin.get(buf,10,'S'))
  8.     {
  9.         cout<<buf<<endl;
  10.     }
  11.     cout<< "\n cin.eof() : " <<cin.eof()
  12.         << "\n cin.fail(): " <<cin.fail()
  13.         << "\n cin.bad() : " <<cin.bad()
  14.         << "\n cin.good(): " <<cin.good()<<endl;
  15.     return 0;
  16. }
复制代码
  1. 输出:
  2. cvdScjkvds
  3. cvd
  4. cin.eof() : 0
  5. cin.fail(): 1
  6. cin.bad() : 0
  7. cin.good(): 0
复制代码
getline

  1. 函数声明
  2. istream& getline (char* s, streamsize n );
  3. istream& getline (char* s, streamsize n, char delim );
  4. 在读取 n-1 个字符前,遇到标志位,则会读到标志位前的字符。然后越过标志位
  5. 继续读取。
  6. 若在读到 n-1 个字符前没有遇到标志位,则会退出。
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char buf[10];
  6.     while(cin.getline(buf,10))
  7.     {
  8.         cout<<buf<<endl;
  9.     }
  10.     cout<< "\ncin.eof() : " <<cin.eof()
  11.         << "\ncin.fail(): " <<cin.fail()
  12.         << "\ncin.bad() : " <<cin.bad()
  13.         << "\ncin.good(): " <<cin.good()<<endl;
  14.     return 0;
  15. }
复制代码
  1. 输出
  2. 1234567890
  3. cin.eof() : 0
  4. cin.fail(): 1
  5. cin.bad() : 0
  6. cin.good(): 0
复制代码
  1. 输出
  2. 123456789
  3. 123456789
  4. ad fd gd
  5. ad fd gd
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char buf[10];
  6.     while(cin.getline(buf,10,'x'))
  7.     {
  8.         cout<<buf<<endl;
  9.     }
  10.     cout<< "\ncin.eof() : " <<cin.eof()
  11.         << "\ncin.fail(): " <<cin.fail()
  12.         << "\ncin.bad() : " <<cin.bad()
  13.         << "\ncin.good(): " <<cin.good()<<endl;
  14.     return 0;
  15. }
复制代码
  1. 输出
  2. 12x22x23x
  3. 12
  4. 22
  5. 23
复制代码
other

  1. 函数声明
  2. istream& ignore (streamsize n = 1, int delim = EOF);
  3. 跳过流中的 n 个字符,或遇到终止字符为止(包含),默认参数忽略一个字符。
  4. int peek();
  5. 窥视当前指针,文件指针未发生移动
  6. istream& putback (char c);
  7. 回推插入当前指针位置
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     char ch[20];
  6.     // 使用cin.get读取输入,最多读取19个字符,直到遇到'/'为止
  7.     // 例如输入 "i like c/ i like C++ also/",将读取 "i like c"
  8.     cin.get(ch, 20, '/');
  9.     cout << "the first part is :" << ch << endl;
  10.     // 忽略接下来的10个字符或直到遇到字符'i'为止
  11.     cin.ignore(10, 'i');
  12.     // 将字符'i'放回输入流的最前面
  13.     cin.putback('i');
  14.     // 查看输入流中的下一个字符,但不移除它
  15.     // 由于之前putback('i'),所以peek将是'i'
  16.     char peek = cin.peek();
  17.     cout << "peek is :" << peek << endl;
  18.     // 再次使用cin.get读取输入,最多读取19个字符,直到遇到'/'为止
  19.     cin.get(ch, 20, '/');
  20.     cout << "this second part is:" << ch << endl;
  21.     return 0;
  22. }
复制代码
  1. 输出
  2. i like c/ i like C++ also/
  3. the first part is :i like c
  4. peek is :i
  5. this second part is:i like C++ also
复制代码
if(!fs)/while(cin)

在判断文件打开乐成与否或是一连从流中读取数据时,就要用到对流对像的利用,
好比 if(!fs)和 while(cin>>val),
我们都知道 cin 是一个流对象,
而>>运算符返回左边的流对象,也就是说 cin>>val 返回 cin,
于是 while(cin>>val)就变成了while(cin),问题就变成了一个流对象在判断语句中的合法性。
不管是 while(cin)还是 if(!fs),都是合法的,为什么呢?
我们自己定义一个类,然后定义该类的对象,然后使用 if 语句来判断它是不合法
的。
这说明,流对象具有某种转换函数,可以将一个流对象转换成判断语句可以识别的范例。
operator void*()与 operator!()

打开 iostream.h 文件,找到 cin 的定义,发现是来自于 istream.h,其中的模
板类 basic_istream 继承自 basic_ios,打开 basic_ios 的定义,发现它有两个重载
函数。
operator void *() const 和 operator!() const。这两个函数使得流对象
可作为判断语句的内容。
  1. operator void*() const //转化函数 A 类对象-> void *对象
  2. {
  3. return this->fail() ? 0 : const_cast<basic_ios*>(this);
  4. }
  5. bool operator!() const //运算符重载函数 对象调用 operator!()
  6. {
  7. return this->fail();
  8. }
复制代码
  1. 常见策略
  2. while(cin)  ===> while(!cin.fail())   //while the stream is OK
  3. if(!cin)    ===> if(cin.fail())        //if the stream is NOT OK
复制代码
代码示例

  1. #if 1
  2. #include <iostream>
  3. using namespace std;
  4. class A
  5. {
  6. public:
  7.     A() {}  // 构造函数
  8.     ~A() {} // 析构函数
  9.     // 类型转换运算符,将对象转换为void*类型
  10.     operator void* () const
  11.     {
  12.         cout << "operator void* () cast to void*; " << endl;
  13.         return (void *)this;  // 返回当前对象的指针
  14.     }
  15.     // 重载逻辑非运算符
  16.     bool operator!() const
  17.     {
  18.         cout << "bool operator!() return bool; " << endl;
  19.         return true;  // 返回true
  20.     }
  21. };
  22. int main()
  23. {
  24.     A a;  // 创建对象a
  25.     // 使用对象a作为while循环的条件
  26.     // 由于a可以隐式转换为void*类型,且void*类型的非零值被视为true
  27.     while (a) {
  28.         cout << "while" << endl;
  29.         break;  // 跳出循环
  30.     }
  31.     // 使用对象a作为if语句的条件
  32.     // 由于a可以隐式转换为void*类型,且void*类型的非零值被视为true
  33.     if (a) cout << "first" << endl;
  34.     // 使用逻辑非运算符!a作为if语句的条件
  35.     // 由于重载了!运算符,返回true
  36.     if (!a) cout << "second" << endl;
  37.     return 0;
  38. }
  39. # endif
复制代码
  1. 输出
  2. operator void* () cast to void*;
  3. while
  4. operator void* () cast to void*;
  5. first
  6. bool operator!() return bool;
  7. second
复制代码
File Stream

对文件的利用是由文件流类完成的。文件流类在流与文件间建立连接。由于文件流
分为三种:文件输入流、文件输出流、文件输入/输出流,所以相应的必须将文件流说
明为 ifstream、ofstream 和 fstream 类的对象,然后利用文件流的对象对文件举行利用
   对文件的利用过程可按照以下四步举行:即定义文件流类的对象、打开文件、对文
件举行读写利用、关闭文件,下面分别举行介绍。
  1. 流对象的定义
  2. //流类 流对象;
  3. ifstream ifile; //定义一个文件输入流对象
  4. ofstream ofile; //定义一个文件输出流对象
  5. fstream iofile; //定义一个文件输出/输入流对象
复制代码
open 函数

定义了文件流对象后,就可以利用其成员函数 open()打开需要利用的文件,该
成员函数的函数原型为:
  1. void open(const unsigned char *filename,int mode,int access=filebuf:openprot);
  2. 其中:filename 是一个字符型指针,指定了要打开的文件名;
  3. mode 指定了文件的打开方式,其值如下表所示;
  4. access 指定了文件的系统属性,取默认即可
复制代码
文件打开方式

打开方式值寄义ios::in0x01以输入(读)方式打开文件,若文件不存在则报错。ios:ut0x02以输出(写)方式打开文件, 若文件不存则创建。ios::ate0x04打开文件时指针指向文件尾ios::app0x08打开一个文件使新的内容始终添加在文件的末端,若文件不存在,则创建。ios::trunc0x10若文件存在,则截断文件ios::binary0x80以二进制方式打开文件,缺省时以文本方式打开文件。ios::nocreate0x20若文件不存在,则打开失败,而不是创建文件。ios::noreplace0x40若文件存在,则打开失败,而不是覆盖文件。
  1. 几点说明:
  2. a.在实际使用过程中,可以根据需要将以上打开文件的方式用"|"组合起来。如:
  3. ios::in|ios::out
  4. 表示以读/写方式打开文件
  5. ios::in|ios:: binary
  6. 表示以二进制读方式打开文件
  7. ios::out|ios:: binary
  8. 表示以二进制写方式打开文件
  9. ios::in|ios::out|ios::binary 表示以二进制读/写方式打开文件
  10. b.如果未指明以二进制方式打开文件,则默认是以文本方式打开文件。
  11. c.构造函数打开文件
  12. 对于 ifstream 流, mode 参数的默认值为 ios::in,
  13. 对于 ofstream 流,mode 的默 认值为 ios::out|ios::trunc,
  14. 对于 fstream 流, mode 的默认值为 ios::int|ios::out|ios::app
  15. d.ios::int|ios::out 是是命名空间的 ios 中一堆枚举
复制代码
文件读写

读写接口


一次读一个字符

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main()
  5. {
  6.     // 创建一个 fstream 对象 fs
  7.     fstream fs;
  8.     // 以读写模式打开文件 "test.txt",如果文件存在则截断文件
  9.     fs.open("test.txt", ios::in | ios::out | ios::trunc);
  10.     // 检查文件是否成功打开
  11.     if (!fs)
  12.     {
  13.         cout << "open error" << endl;
  14.         return -1; // 如果打开失败,返回 -1
  15.     }
  16.     // 向文件中写入从 'a' 到 'z' 的字符
  17.     for (char c = 'a'; c <= 'z'; c++)
  18.     {
  19.         fs.put(c); // 将字符 c 写入文件
  20.     }
  21.     // 将文件指针移动到文件开头
  22.     fs.seekp(0, ios::beg);
  23.     // 从文件中读取字符并输出到控制台
  24.     char ch;
  25.     while (fs.get(ch)) // 从文件中读取一个字符并存储到 ch 中
  26.     {
  27.         cout << ch << endl; // 输出字符 ch 并换行
  28.     }
  29.     // 关闭文件
  30.     fs.close();
  31.     // 程序正常结束,返回 0
  32.     return 0;
  33. }
复制代码
可以用<<和>>
  1. for(char c='a';c<='z';c++){
  2.         fs<<c;
  3.     }
  4.     fs.seekp(0,ios::beg);
  5.     char ch;
  6.     while (fs>>ch){
  7.         cout<<ch<<endl;
  8.     }
复制代码
一次读一行

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main()
  5. {
  6.     fstream fs;
  7.     fs.open("test.txt",ios::in|ios::out|ios::trunc);
  8.     if(!fs)
  9.     {
  10.         cout<<"open error"<<endl;
  11.         return -1;
  12.     }
  13.     //按行写入
  14.     fs<<"hello world1"<<endl;
  15.     fs<<"hello world2"<<endl;
  16.     fs<<"hello world3"<<endl;
  17.     fs.seekp(0,ios::beg);
  18.     char buf[100];
  19.     while (fs>>buf){ //读取一行 以空格换行符为分隔
  20.         cout<<buf<<endl;
  21.     }
  22.    
  23.     //getline读到换行符为止,但是会丢弃换行符,所以要补上换行符
  24.     while (fs.getline(buf,100,'\n')){//'\n'参数不加也是可以的,默认就是换行符
  25.             cout<<buf<<endl;//补上换行符
  26.     }
  27.    
  28.     fs.close();
  29.     return 0;
  30. }
复制代码
读写二进制

读写接口:
ostream & write(const char*buf, int len);
istream & read(char * buff, int len);
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. // 定义学生结构体
  5. struct Student
  6. {
  7.     char name[100]; // 学生姓名
  8.     int num;        // 学生学号
  9.     int age;        // 学生年龄
  10.     char sex;       // 学生性别
  11. };
  12. int main() {
  13.     fstream fs; // 定义文件流对象
  14.     // 打开文件,模式为读写和截断(如果文件存在,清空文件内容)
  15.     fs.open("test.txt", ios::in | ios::out | ios::trunc);
  16.     // 检查文件是否成功打开
  17.     if (!fs) {
  18.         cout << "open error" << endl;
  19.         return -1; // 打开失败,返回错误码
  20.     }
  21.     // 定义并初始化学生数组
  22.     Student s[3] = {
  23.             {"li",   1001, 18, 'f'},
  24.             {"liu",  1002, 19, 'm'},
  25.             {"Wang", 1004, 17, 'f'}
  26.     };
  27.     // 将学生数组以二进制形式写入文件
  28.     fs.write((char*)&s, sizeof(s));
  29.     // 将文件指针移动到文件开头
  30.     fs.seekp(0, ios::beg);
  31.     Student s1; // 定义一个学生结构体变量用于读取数据
  32.     // 从文件中读取数据,直到文件结束
  33.     while (fs.read((char*)&s1, sizeof(s1))){
  34.         // 输出读取到的学生信息
  35.         cout << s1.name << " " << s1.num << " " << s1.age << " " << s1.sex << endl;
  36.     }
  37.     fs.close(); // 关闭文件
  38.     return 0; // 程序正常结束
  39. }
复制代码
  1. 输出
  2. li 1001 18 f
  3. liu 1002 19 m
  4. Wang 1004 17 f
复制代码
文件指针相关的函数


   g 代表 get 的意思用于输入的函数。p 代表 put 的意思,用于输出函数。如果既是
可输入又是可输出的文件,则任意使用。
  

  1. 代码示例:
  2. infile.seekg(100);//输入文件中的指针向前移到 100 个字节的位置
  3. infile.seekg(-50,ios::cur); //输入文件中的指针从当前位置后移 50 个字节
  4. outfile.seekp(-75,iso::end); //输出文件中指针从文件尾后移 75 个字节
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

兜兜零元

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表