【C++要笑着学】关键字 | 命名空间 | 输入和输出(二)

简介: 本章将正式开始 C++ 的学习,将深入浅出地讲解。本篇将以 HelloWorld 开始,以 HelloWorld 结束。通过这段代码,讲解C++中的命名空间和输入与输出。话不多说,让我们开始吧

Ⅳ.  C++的输入与输出


0x00 库的展开

我们刚才之所以讲解命名空间,就是为了让大家能够慢慢地看懂本篇一开始写的 HelloWorld。


但是在讲解C++的输入与输出之前,我们还需要再对命名空间做一个小小的补充。

031881a83fc4d61dbf97d55217020038_61d220d6df5b4709b563c263f1844aa6.png


📚 库也是会用命名空间的,C++库的实现定义包含在了一个叫 std 的命名空间中。


我们加上 using namespace std 是为了把 std 空间中所有的内容都展开,


这样我们就可以直接使用它们了。


❓ 为什么C++要把它封装到一个叫 std 的命名空间中呢?


💡 因为这样就不容易冲突了,有效放置了冲突命名。


📌 注意事项:这里要提一下,有些老的教材上有  #include <iostream.h>


这个在老的编译器上是可以的,比如 VC6.0 ,比较老的版本的库,没有命名空间。


早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件 即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文 件不带.h;旧编译器(vc 6.0)中还支持 <iostream.h> 格式,后续编译器已不支持,因此推荐使用 <iostream> +std 的方式。

eb62e1aec1a1bc4423ab31cd47ddde73_ba24a2fd70864489b305406371cf4170.png


【问题来自读者评论:20220612更新】


iostream.h过时了,是早期vs用的,我记得以前 vc6.0 的时候还是用 iostream.h的。

现在的新标准库是用 iostream 的。

文章里说的 "为了和C头文件区分,规定c++头文件不带.h” 是因为新的c++摈弃了.h形式的头文件。现在是标准c的头文件是.h,标准c++头文件不带.h。

所以不建议用iostream.h了。



头文件用尖括号引入,和用引号引入的区别:


首先,< > 和 " " 包含头文件的本质区别是查找策略区别。

① " " 的查找策略:先在源文件所在的目录下查找。如果该头文件未找到,则在库函数的头文件目录下查找

② < > 的查找策略:直接去标准路径下去查找。


所以库文件也是可以使用 " " 包含的。

#include <iostream.h> 是库文件,你用引号形式引入 #include "iostream.h" 也是可以的,


但是这样查找的效率就会低些。



而且这样也不容易区分是库文件还是本地文件。

(看到尖括号引入就知道是库文件,看到引号引入的就知道是本地文件,还是很香的)

因此不建议库文件用 " " 形式引入。


0x01 输入和输出

cout 标准输出(控制台)和 cin 标准输入(键盘)时,必须包含 <iostream> 头文件。


并且需要使用 std 标准命名空间,这里我们下面会详细探讨。


0x02 流插入运算符 <<

6039c233a6405cde7c19be88459fa60b_7af5d7bd50044086aedf9ecd8f541667.png


 📚 cout 后面的 << ,我们称之为 "流插入运算符" 。就像水流的流向一样。


💬 cout 用法演示:


#include <iostream>
using namespace std;
int main()
{
  cout << "Hello";  // 等同于 printf("Hello");
  return 0;
}

🚩 运行结果:  Hello


📜 上面的代码,我们之所以可以直接用 cout,是因为我们已经把 std 这块库命名空间展开了。


我们下面会对专门对展开方式进行一个探讨。


📚 此外,如果我们想换行,我们可以使用 endl 。它就"相当于" \n,都可以起到一个换行的效果。

cd3d130cffd37f2e4d8d6274f5746c84_91ef0c03cb7a420bb0ea1503fda0162a.png


💬 endl 用法演示:


#include <iostream>
using namespace std;
int main()
{
  cout << "Hello" << endl;
  return 0;
}

当然,如果你不喜欢用 endl,完全可以用 \n 替代它:

5bd2d7091d8d141d721180ca17cc75eb_385541d638054578832ce71229cc01a4.png

#include <iostream>
using namespace std;
int main()
{
  cout << "Hello\n";  
  return 0;
}

📚 使用 C++ 的输入输出是很方便的,它最大的特点就是可以自动识别类型。


#include <iostream>
using namespace std;
int main()
{
  int i = 10;
  double d = 3.14;
  cout << i << " " << d << endl;   // 相当于 printf("%d %f\n", i, d);
  return 0;
}

🚩 运行结果: 10  3.14


📌 注意事项:

e52a6917d0d694c6ed4e79b5dea40a1e_b798f9dafd904f99af481969f118fdff.png


大量输入输出时尽量少用或者不用 endl ,每次 endl 会刷新缓冲区,这增加了 io 次数,


在数据非常大的时候尽量不要用endl,转义字符不存在刷新缓冲区的问题。


即 —— 需要大量输入输出时建议用 \n 替换 endl 。


0x03 流提取运算符 >>


📚 cin 后面的 >> ,我们称之为 "流提取运算符" 。


#include <iostream>
using namespace std;
int main()
{
  int i = 0;
  double d = 0.0;
  cout << "请输入一个整数和一个小数:> ";
  cin >> i >> d;
  cout << "你输入的是:> ";
  cout << i << " 和 " <<  d << endl;
  return 0;
}


🚩 运行结果如下:

58fbd2890096c5adfa204860f06baa3f_e33c97805ecd42b9b17119ce3d8c18e7.png


❓ 可以改变流的流向吗?


💡 可以!


#include <iostream>
using namespace std;
struct Student {
    char name[20];
    int age;
};
int main(void)
{
    // cin - 流提取运算符
    struct Student s = {"xiaoming", 18};
    cin >> s.name >> s.age;
    cout << "姓名:" << s.name << endl;    
    cout << "年龄:" << s.age << endl << endl;
    scanf("%s%d", &s.name, &s.age);
    printf("姓名:%s\n年龄:%d\n", s.name, s.age);  
    return 0;
}

0x04 学会因地制宜

我们好像可以在 C++ 里用 printf 欸!


#include <iostream>
int main()
{
  printf("Hello!\n");
  return 0;
}

因为 <iostream> 有些平台间接的包了 printf 等 C语言中的函数。


 有人这时候就会觉得,C++的输入和输出可以自动识别类型,这也太爽了吧,既然 C++ 的输入输出这么好用,那我们是不是就用不上 C语言里的输入输出了?


并不是,我举个简单的栗子:


💬 如果我们想打印某个浮点数,如何控制小数点后的位数呢?在 C++ 的输入中,这是一件比较麻烦的事情。如果想控制小数点的位数,我们完全可以使用C语言的输入:


printf("%.2f", d);

因此,并不是说学了C++的输入输出,我们就不用C语言的输入输出了。


C++ 和 C语言的输入输出可以混在一起写,混在一起用。


什么时候用 C++ 的,什么时候用 C语言的,看情况就可以了。


💬 我们再来举个例子:


// 因地制宜!
struct Student {
    char name[20];
    int age;
};
int main(void)
{
    // 这种情况C++ 就不方便了
    struct Student s = {"xiaoming", 18};
    cout << "姓名:" << s.name << endl;    
    cout << "年龄:" << s.age << endl << endl;
    // 用c呢?
    printf("姓名:%s\n 年龄:%d\n", s.name, s.age);  
    // 所以说C语言也是有它的优势的嗷
    return 0;
}

🔺 总结:哪一个方便就用哪一个,具体谁方便需要看情况,要学会因地制宜。


0x05 对于展开方式的探讨

6fb7202399ac4d13a15381c614c36f20_3be43ee251fc429eb01526707dfde5cf.png


上面我们讨论过使用 using namespace 展开的缺陷,会失去隔离的效果。这样写好吗?不好。这么一来就全展开来了,所以我们可以这么写:


(不裂开了,我合上)


💬 采用方式一:空间名 + 作用域限定符


#include <iostream>
//using namespace std;
int main(void) 
{
    // cout << "Hello, World!\n" << endl; 
    std::cout << "Hello, World!" << std::endl;  // 指定命名空间
    return 0;
}

💬 采用方式二:使用 using namespace 命名空间名称引入 (会破坏隔离效果)


#include <iostream>
using namespace std;
int main()
{
  cout << "Hello,World!" << endl;
  return 0;
}

📌 虽然 using namespace 会破坏隔离效果,但是我们平时写练习还是可以这么去做的。因为我们平时不需要这么过分地讲究命名空间,但是以后在写项目或干正事的时候就得讲究讲究了。


💬 采用方式三:使用 using 将命名空间中成员引入


#include <iostream>
using std::cout; // 把常用的展开
using std::endl;
int main(void)
{
    cout << "Hello, World!" << endl;  
    return 0;
}

Ⅴ.  再看 HelloWorld


深入浅出 —— 浅出


📚 现在我们再来回头看之前的 HelloWorld:


#include <iostream>
using namespace std;
int main()
{
  cout << "Hello,World!" << endl;
  return 0;
}


相关文章
|
15天前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
21 0
|
3月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
3月前
|
安全 程序员 编译器
【C++】如何巧妙运用C++命名空间:初学者必备指南
【C++】如何巧妙运用C++命名空间:初学者必备指南
|
3月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
5月前
|
程序员 C++ 开发者
C++命名空间揭秘:一招解决全局冲突,让你的代码模块化战斗值飙升!
【8月更文挑战第22天】在C++中,命名空间是解决命名冲突的关键机制,它帮助开发者组织代码并提升可维护性。本文通过一个图形库开发案例,展示了如何利用命名空间避免圆形和矩形类间的命名冲突。通过定义和实现这些类,并在主函数中使用命名空间创建对象及调用方法,我们不仅解决了冲突问题,还提高了代码的模块化程度和组织结构。这为实际项目开发提供了宝贵的参考经验。
77 2
|
4月前
|
程序员 C++ 容器
C++编程基础:命名空间、输入输出与默认参数
命名空间、输入输出和函数默认参数是C++编程中的基础概念。合理地使用这些特性能够使代码更加清晰、模块化和易于管理。理解并掌握这些基础知识,对于每一个C++程序员来说都是非常重要的。通过上述介绍和示例,希望能够帮助你更好地理解和运用这些C++的基础特性。
51 0
|
5月前
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
81 4
|
5月前
|
编译器 C语言 C++
C++入门 | 命名空间、输入输出、缺省参数
C++入门 | 命名空间、输入输出、缺省参数
53 4
|
4月前
|
C语言 C++
C++(六)Namespace 命名空间
命名空间(Namespace)是为了解决大型项目中命名冲突而引入的机制。在多库集成时,不同类库可能包含同名函数或变量,导致冲突。C++通过语法形式定义了全局无名命名空间,并允许对全局函数和变量进行作用域划分。命名空间支持嵌套与合并,便于协同开发。其使用需谨慎处理同名冲突。
|
6月前
|
安全 编译器 C++
C++一分钟之-C++中的属性命名空间
【7月更文挑战第22天】C++11引入属性作为元数据,虽无内置属性命名空间,但可通过自定义属性与命名空间组合实现类似效果。例如,创建`perf`命名空间存放`slow`和`fast`属性来标记函数性能。正确使用属性需注意位置、避免重复和确保与实现一致,以提升代码可读性和编译器理解。通过模拟属性命名空间,可以更有效地管理和使用属性。
57 1