【C++】借助cout进行控制台文本输出的基本原理及复杂格式控制方法

本文详细探讨了C++中cout进行控制台文本输出的工作原理和格式控制方法,包括进制转换、输出宽度、浮点数精度、setf函数的应用以及操作算子的使用。通过实例代码解析了各种格式设置技巧,适合初学者和需要理解cout内部机制的开发者参考。
摘要由CSDN通过智能技术生成

建议老师们将本文收藏,待学生的需要时发给学生,免费口舌。

本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频

在C++里,我们使用cout进行控制台文本输出。这在学习编程的阶段很常用,但在真实的工作场合却极少使用,毕竟大部分的应用程序都是基于图形界面,而不是终端的。甚至,在C/C++的某些应用场合,比如单片机编程里,嵌入式设备甚至连屏幕都没有。

考虑到部分OJ系统中的在线编程题可能对输出格式作出精细要求,这里我们对cout控制输出进行“详细”讨论:包括cout的基本工作原理,以及通过cout进行精细格式输出的方法。

对工作原理不感兴趣,只想快速知道HOW的有编程经验的读者请直接阅读本文的第6部分。

1. cout基本工作原理

下述代码可以帮助我们理解通过cout的插入操作符(insertion operator<<)进行控制台文本输出的基本原理。

//Project - COUT
#include <iostream>
using namespace std;

int main() {
   
    cout << "pi = " << 3.14159 << endl;
    operator<<(cout,"pi = ").operator<<(3.14159).operator<<(endl);
    return 0;
}

上述代码的执行结果为:

pi = 3.14159
pi = 3.14159

在iostream头文件中,很容易找到cout的定义。cout是一个类型为ostream的对象,其被连接到了标准输出流,即控制台。

extern ostream cout;    /// Linked to standard output

上述程序的第6行与第7行完全等价。相关代码的执行过程如下:

  • cout << “pi = “的实质是执行了一个名为operator<<( )的函数,其中,第1个参数是cout对象,第2个参数是”pi = “。这个函数把第2个参数的字符串输出到第1个参数所代表的控制台中。同时,该函数返回了cout的引用作为函数执行的结果。
  • … << 3.141519则以前述函数调用所返回的cout引用作为基础,执行其成员函数operator<<( )。该成员函数存在多个函数名重载的版本,其中一个版本接受一个double作为参数,并将double的值输出到cout。同样地,本次函数调用也返回了cout的引用作为结果。
  • 类似地,… << endl同样对应cout.operator<<( )函数的一次执行,该成员函数的一个重载版本接受endl作为参数,并向cout所代表的控制台输出一个换行符。

<<操作符在C语言里用作左移位操作,C++的标准模板库通过定义与该操作符“同名”的函数,扩展了该操作符的功能:向cout输出对象内容。

总结:iostream定义了多个重载的operator<<()操作符函数,这些不同版本的函数接受不同类型的参数,包括int, char, float, double, const char*, string等,并将这些参数对象转换成字符串,并输出到控制台屏幕上。

2. 改变进制

//Project - HexOct
#include <iostream>
#include <stdio.h>
using namespace std;

int main(){
   
    int b = 0x17;          //十六进制 hexadecimal
    int c = 017;           //八进制   octal
    int d = 0b01111110;    //二进制   binary

    cout << "0x17 = " << b << ", 017 = " << c << ", 0b01111110 = " << d << endl;
    printf("17: %x, %d, %o\n", 17, 17, 17);
    cout << "17: " << hex << 17 << ", " << dec << 17 << ", " << oct << 17 << endl;

    hex(cout);
    cout << "17: " << 17 << ", ";
    dec(cout);
    cout << 17 << ", ";
    oct(cout);
    cout << 17 << endl;

    return 0;
}

上述代码的执行结果为:

0x17 = 23, 017 = 15, 0b01111110 = 126
17: 11, 17, 21
17: 11, 17, 21
17: 11, 17, 21

上述代码可以看出,通过执行cout << hex,可以改变cout的内部状态,使用在后续输出数值时使用16进制。cout << dec (十进制),cout << oct (八进制)同理。

事实上,这里的hex, dec, oct是一种被称之为操作算子(manipulator)的特殊函数。下述3行代码事实上等价:

cout << hex;
cout.operator<<(hex);
hex(cout);

在ios_base.h中我们可以找到hex()函数的定义:

inline ios_base&
hex(ios_base& __base)
{
   
  __base.setf(ios_base::hex, ios_base::basefield);
  return __base;
}

在形式上,cout << hex被解释成多轮函数调用,首先是:

cout.operator<<(hex);

这个被重载的operator<<()函数将hex函数名当成一个函数指针,然后通过这个函数指针调用hex()函数:

hex(cout);

而hex()函数又通过cout的setf()函数发挥作用。读者或许会疑惑说,这么多层的函数调用是否会降低代码的执行效率,事实上,由于相关函数多是内联(inline)的,编译器的优化会消除这些“形式”上的不必要的函数调用。

3. 输出宽度控制

#
C++中,读取ASCII文本文件并将其转换为视频输出通常涉及到两个步骤:首先,你需要逐行读取文本文件,将其视为一系列字符数组表示的帧;然后,你需要将这些帧组合成视频流,并在控制台上模拟播放。然而,标准的C++库并不直接支持视频输出控制台,因此这需要借助一些第三方库或自定义方法。 以下是简化的步骤概述: 1. **读取ASCII文本文件**: 使用`ifstream`打开文件,逐行读取内容,每行可以被视为一帧(通常是24x6列的字符矩阵)。 ```cpp std::ifstream file("image.txt"); if (!file.is_open()) { std::cerr << "Failed to open the file." << std::endl; return; } std::string line; while (getline(file, line)) { // 对每一行处理 } ``` 2. **处理字符数组**: 将每一行的字符数组转换为图像数据,例如通过遍历每个字符并使用ASCII码值创建像素矩阵。 3. **模拟播放**: 可能需要自定义一个简单的"动画"循环,每次迭代更新控制台输出,显示新的字符帧。这可能会涉及清屏、移动指针等操作,但实际效果受限于控制台的能力,可能无法像真实视频那样流畅。 ```cpp for (const auto& frame : frames) { for (int i = 0; i < frame.size(); ++i) { // 控制台打印字符,这里仅作示意,实际可能无效 std::cout << static_cast<char>(frame[i]); // 清除上一行以便打印新的一行 std::cout.flush(); std::system("cls"); // Windows清除屏幕 } // 模拟延迟,以增加播放效果(但这不是真正的视频) std::this_thread::sleep_for(std::chrono::milliseconds(50)); } ``` 注意,这个过程在控制台上创建视频是非常有限的,因为控制台的刷新频率较低且没有硬件加速。对于更复杂的视频处理,建议使用专门的图形库如SFML或Emgu CV,或者考虑其他输出形式如文件、窗口等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值