第十章---关闭同步流及注意事项及详细分析cin.ignore();

news/2024/12/22 1:13:00/

1.关闭同步流及注意事项

1.关闭同步流:ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

ios::sync_with_stdio(0);

这条语句的目的是告诉C++的IO库,不要将C++的iostream对象(如cin, cout, cerr等)与C的stdio库(如stdin, stdout, stderr等)同步。这通常用于提高输入输出的效率,特别是在需要大量IO操作时。

  • ios::sync_with_stdiostd::ios_base 类的一个枚举值成员,用于控制iostream库是否与C的stdio库同步。
  • 参数 0 表示不进行同步(即禁用同步),而 1 表示启用同步(这是默认行为)。
    禁用同步可以减少iostream操作时的开销,因为iostream不再需要等待stdio操作完成。
cin.tie(0);

这条语句用于解除cin与cout之间的绑定。默认情况下,cin和cout是绑定的,这意味着每次进行cin操作后,都会自动刷新cout缓冲区。

  • cin.tie() 是一个成员函数,返回当前与cin绑定的ostream对象,默认是cout。
  • 参数 0 表示解除绑定,因此cin操作后不会自动刷新cout缓冲区。
    解除绑定可以减少不必要的缓冲区刷新,从而提高性能。
cout.tie(0);

这条语句与 cin.tie(0); 类似,但它是用于解除cout与其他iostream对象的绑定。

  • cout.tie() 是一个成员函数,返回当前与cout绑定的istream对象,默认是cin。
  • 参数 0 表示解除绑定。
    虽然通常情况下,我们主要关注的是解除cin和cout之间的绑定,但在某些情况下,也可能需要解除cout与其他iostream对象的绑定。
另一种方法:
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
  • ios::sync_with_stdio(false); 关闭了C++ IO流与C的stdio库的同步,提高了性能。
  • cin.tie(NULL); 解除了cin和cout之间的绑定,这样cin的操作不会导致cout自动flush。
  • cout.tie(NULL); 通常这一行是不必要的,因为前面已经通过 cin.tie(NULL) 解除了绑定,但是它显式地指出了cout不再与任何流绑定。
区别

首先这两种关闭同步流的代码在功能上并没有区别但是,ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); 中的 cin.tie(0)cout.tie(0) 是不正确的用法,应该使用 cin.tie(NULL)cout.tie(NULL) 来解除流之间的绑定。
正确的代码:

ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);

ios::sync_with_stdio(0)ios::sync_with_stdio(false) 实际上是相同的,0 在这里只是表示逻辑上的假值,关闭同步。使用 false 可能更具可读性,但它们的效果是一样的。

总结

使用这条语句的目的是为了优化C++程序的输入输出性能,特别是在算法竞赛或性能敏感的应用中。这些语句通过减少iostream与stdio的同步以及解除cin和cout之间的绑定,来减少不必要的缓冲区刷新,从而提高程序的运行效率。

2.关闭同步流的注意事项:

① 关闭同步流后,不要用"endl",而是换用"\n"。

在C++中,endl是一个操纵符,它在输出流中插入一个换行符,并刷新输出缓冲区。这通常用于确保在调用endl后,所有输出都被写入到输出设备(如屏幕)上。

  • endl
    • 优点:确保输出立即显示。
    • 缺点:由于刷新输出缓冲区,可能会导致性能下降,尤其是在频繁的输出操作中。
      \n仅是一个字符,它代表换行符,用于在输出流中插入一个新行,但它不会刷新输出缓冲区。
  • \n
    • 优点:比endl更高效,因为它不会导致缓冲区刷新。
    • 缺点:在某些情况下,可能需要手动刷新缓冲区以确保输出。
      当使用ios::sync_with_stdio(false);关闭C++和C标准流的同步时,这意味着C++的IO操作不再与C的stdio库同步。这通常用于提高性能,特别是在处理大量输入输出操作时。在这种情况下,推荐使用\n而不是endl,因为同步已经关闭,且endl的缓冲区刷新操作不再必要,这样可以进一步提高性能。
② 不使用getchar() 而是换用cin.get()

getchar()是C标准库函数,用于从标准输入读取下一个字符,它忽略任何之前的换行符。
cin.get()是C++的iostream库成员函数,它也用于从输入流读取下一个字符,但它可以处理iostream流的状态和格式。
以下是两者的一些区别:

  • getchar()
    • 属于C标准库。
    • 不影响C++的iostream流状态。
    • 通常用于简单的字符读取。
  • cin.get()
    • 属于C++的iostream库。
    • 读取字符时会更新iostream流的状态。
    • 可以更灵活地用于C++的流操作。
      在关闭了stdio同步的情况下(ios::sync_with_stdio(false);),推荐使用cin.get(),因为它与C++的iostream库更加一致,可以更好地处理流的状态。在下面的代码中:
ios::sync_with_stdio(false);
string s;
cin >> s;
char c1 = cin.get();     //char c2=getchar();

在读取字符串s之后,使用cin.get()来读取并丢弃缓冲区中的换行符(如果有的话)。这是因为在读取字符串后,换行符通常留在输入流中。如果不处理这个换行符,它可能会干扰后续的输入操作。

而如果使用getchar(),它不会影响C++的iostream流状态,可能导致流状态不一致的问题。

2.cin.ignore( );

cin.ignore() 是 C++ iostream 库中的一个成员函数,用于忽略输入流中的字符。这个函数通常用于在读取输入之后清除输入缓冲区中的剩余字符,例如换行符、空白字符或其他不需要的字符。

基本语法

cin.ignore(n, delimiter);
  • n:表示要忽略的字符的最大数量。如果 n 被省略,则默认为 std::numeric_limits<std::streamsize>::max(),这意味着将忽略尽可能多的字符,直到遇到文件结束符(EOF)或者指定的 delimiter
  • delimiter:一个可选参数,表示遇到这个字符时停止忽略。如果 delimiter 被省略,则默认忽略所有字符直到 n 个字符被忽略或者到达文件结束。

示例

#include <iostream>
#include <limits>
int main() {std::string s;std::getline(std::cin, s); // 读取一行文本// 忽略接下来的10个字符或者直到遇到换行符std::cin.ignore(10, '\n');// 继续其他输入操作int number;std::cin >> number;return 0;
}

使用场景

  • 清除换行符:在读取一行文本后,通常会有一个换行符留在输入缓冲区中。使用 cin.ignore() 可以清除这个换行符,以免影响后续的输入操作。
  • 忽略特定字符:在某些情况下,你可能想要忽略输入流中的特定字符或字符序列,cin.ignore() 允许你指定一个终止字符来实现这一点。

注意事项

  • 流状态cin.ignore() 会根据读取的字符更新流的状态。如果遇到文件结束符(EOF),则设置 eofbit;如果遇到错误,则设置 failbit
  • 性能:如果指定了一个非常大的 n 值,cin.ignore() 可能会执行大量的读取操作,这可能会影响性能。
  • 缓冲区大小:使用 cin.ignore() 时,需要确保不会超出输入缓冲区的大小。

替代方案

在某些情况下,你可以使用其他方法来清除输入缓冲区:

  • cin.get():可以读取并丢弃缓冲区中的下一个字符。
  • cin.clear() 和 cin.ignore():通常结合使用,先清除错误标志(cin.clear()),然后忽略缓冲区中的剩余字符(cin.ignore())。

总之,cin.ignore() 是一个有用的工具,可以用来控制输入流,确保后续的输入操作能够正确进行。


http://www.ppmy.cn/news/1533805.html

相关文章

ScatterAdd算子实现简介

Ascend C 算子实现简介&#xff1a;ScatterAdd 算子 本文主要对 ScatterAdd 算子进行简要介绍。 ScatterAdd 用于在给定的索引位置上增加一个指定的值。它的用法类似于 ScatterUpdate 操作&#xff0c;但不同的是&#xff0c;ScatterUpdate 是在指定索引位置上直接覆盖原来的…

滚雪球学MySQL[7.2讲]:MySQL安全策略详解:数据加密与SQL注入防护

全文目录&#xff1a; 前言7.2 数据加密与SQL注入防护1. 数据加密1.1 传输层加密&#xff08;SSL/TLS&#xff09;1.1.1 SSL/TLS的配置 1.2 存储加密&#xff08;TDE&#xff09;1.2.1 TDE的配置 1.3 数据加密的注意事项 2. SQL注入防护2.1 SQL注入的工作原理2.2 防护SQL注入的…

源2.0-M32大模型适配AutoGPTQ工具及量化推理教程

AutoGTPQ简介 AutoGPTQ‌是一个开源工具包&#xff0c;专注于简化大规模语言模型(LLMs)的量化过程。它基于高效的GPTQ算法开发&#xff0c;主要使用Python编程语言&#xff0c;并依托PyTorch框架来实现量化功能。AutoGPTQ的设计目标是为开发者和研究人员提供一个易于使用的API接…

Spring之生成Bean

Bean的生命周期&#xff1a;实例化->属性填充->初始化->销毁 核心入口方法&#xff1a;finishBeanFactoryInitialization-->preInstantiateSingletons DefaultListableBeanFactory#preInstantiateSingletons用于实例化非懒加载的bean。 1.preInstantiateSinglet…

Apache POI 2024/10/2

导入Apache POI的maven坐标 通过POI向Excel文件写入文件内容 package com.sky.test;import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File; import java.…

Vue和axios零基础学习

Vue的配置与项目创建 在这之前要先安装nodejs 安装脚手架 官网 Home | Vue CLI (vuejs.org) 先运行&#xff0c;切换成淘宝镜像源&#xff0c;安装速度更快 npm config set registry http://registry.npm.taobao.org 创建项目 用编译器打开一个空文件&#xff0c;在终端输入…

深度学习:cGAN和pix2pix图像转换

cGAN和pix2pix的基础概念 cGAN cGAN是条件生成对抗网络&#xff08;Conditional Generative Adversarial Networks&#xff09;的简称。 它是一种基于基础GAN&#xff08;Generative Adversarial Networks&#xff09;架构的变体&#xff0c;通过给GAN模型引入额外的信息或条…

mp4(H.265编码)转为本地RTSP流

目标&#xff1a;获得H265码流&#xff0c;要么通过在线网址&#xff0c;要么获得H265文件自己产生码流 在以下任意网址中下载得到H265编码的MP4文件 http://www.elecard.com/en/download/videos.html http://ultravideo.cs.tut.fi/#testsequences http://4k.cablelabs.com/](…