C++ 格式化、文件 I/O 和命名空间

C++C++Beginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,你将学习 C++ 中的格式化、文件 I/O 和命名空间。你将学习如何格式化输出、如何格式化输入、如何读写文件以及如何使用命名空间。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("C++")) -.-> cpp/IOandFileHandlingGroup(["I/O and File Handling"]) cpp(("C++")) -.-> cpp/StandardLibraryGroup(["Standard Library"]) cpp(("C++")) -.-> cpp/SyntaxandStyleGroup(["Syntax and Style"]) cpp/IOandFileHandlingGroup -.-> cpp/output("Output") cpp/IOandFileHandlingGroup -.-> cpp/user_input("User Input") cpp/IOandFileHandlingGroup -.-> cpp/files("Files") cpp/StandardLibraryGroup -.-> cpp/string_manipulation("String Manipulation") cpp/SyntaxandStyleGroup -.-> cpp/code_formatting("Code Formatting") subgraph Lab Skills cpp/output -.-> lab-178541{{"C++ 格式化、文件 I/O 和命名空间"}} cpp/user_input -.-> lab-178541{{"C++ 格式化、文件 I/O 和命名空间"}} cpp/files -.-> lab-178541{{"C++ 格式化、文件 I/O 和命名空间"}} cpp/string_manipulation -.-> lab-178541{{"C++ 格式化、文件 I/O 和命名空间"}} cpp/code_formatting -.-> lab-178541{{"C++ 格式化、文件 I/O 和命名空间"}} end

内容预览

使用 <iomanip> 中的 I/O 操纵符(manipulators)来格式化输入和输出。

<fstream> 头文件提供了 ifstream(输入文件流)和 ofstream(输出文件流)用于文件的输入和输出。

  • 格式化输入和输出
  • 文件输入和输出
  • 命名空间(Namespace)

使用 IO 操纵符(Header <iomanip>)格式化输入/输出

<iomanip> 头文件提供了所谓的 I/O 操纵符(manipulators)用于格式化输入和输出:

  • setw(int field-width):为 下一个 IO 操作设置 字段宽度setw()非粘性 的,必须在每次 IO 操作之前调用。每次操作后,字段宽度会重置为默认值(仅足以容纳字段的宽度)。
  • setfill(char fill-char):设置填充字符以填充到 字段宽度
  • left|right|internal:设置对齐方式。
  • fixed/scientific(用于浮点数):使用定点表示法(例如,12.34)或科学计数法(例如,1.23e+006)。
  • setprecision(int numDecimalDigits)(用于浮点数):指定小数点后的位数。
  • boolalpha/noboolalpha(用于 bool):将 bool 值显示为字母字符串(true/false)或 1/0。
/* 测试格式化输出 */
#include <iostream>
#include <iomanip>    // 需要包含此头文件以进行格式化 I/O
using namespace std;

int main() {
   // 浮点数
   double pi = 3.14159265;
   cout << fixed << setprecision(4); // 固定格式,保留 4 位小数
   cout << pi << endl;
   cout << "|" << setw(8) << pi << "|" << setw(10) << pi << "|" << endl;
      // setw() 是非粘性的,仅适用于下一个操作。
   cout << setfill('-');
   cout << "|" << setw(8) << pi << "|" << setw(10) << pi << "|" << endl;
   cout << scientific;  // 使用科学计数法显示指数
   cout << pi << endl;

   // 布尔值
   bool done = false;
   cout << done << endl;  // 打印 0(表示 false)或 1(表示 true)
   cout << boolalpha;     // 打印 true 或 false
   cout << done << endl;
   return 0;
}

输出:

3.1416
|  3.1416|    3.1416|
|--3.1416|----3.1416|
3.1416e+00
0
false
图片描述
/* 测试格式化输入 */
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main() {
   string areaCode, phoneCode;
   string inStr;

   cout << "输入你的电话号码,格式为 (xxx)xxx-xxxx : ";
   cin.ignore();   // 跳过 '('
   cin >> setw(3) >> areaCode;
   cin.ignore();   // 跳过 ')'
   cin >> setw(3) >> phoneCode;
   cin.ignore();   // 跳过 '-'
   cin >> setw(4) >> inStr;
   phoneCode += inStr;

   cout << "电话号码是 (" << areaCode << ")"
        << phoneCode.substr(0, 3) << "-"
        << phoneCode.substr(3, 4) << endl;
   return 0;
}

输出:

输入你的电话号码,格式为 (xxx)xxx-xxxx :  254 845 9946
电话号码是 (254)845-9946
图片描述

文件输入/输出

为了测试文件输入和输出,首先创建一个名为 in.txt 的文件,并在其中写入一些用空格分隔的整数。执行后,计算结果将被写入一个名为 out.txt 的文件。

/* 测试文件 I/O
   从输入文件中读取所有整数,并将平均值写入输出文件 */
#include <iostream>
#include <fstream>   // 文件流
#include <cstdlib>
using namespace std;

int main() {
   ifstream fin;   // 输入流
   ofstream fout;  // 输出流

   // 尝试打开输入文件
   fin.open("in.txt");
   if (!fin.is_open()) {
      cerr << "错误:打开输入文件失败" << endl;
      abort();  // 异常终止程序(位于 <cstdlib> 中)
   }

   int sum = 0, number, count = 0;
   while (fin >> number) {
      // 使用 >> 读取
      cout << number << " ";
      sum += number;
      ++count;
   }
   double average = double(sum) / count;
   cout << "Count = " << count << " average = " << average << endl;
   fin.close();

   // 尝试打开输出文件
   fout.open("out.txt");
   if (!fout.is_open()) {
      cerr << "错误:打开输出文件失败" << endl;
      abort();
   }
   // 使用 << 将平均值写入输出文件
   fout << average;
   fout.close();
   return 0;
}

输出:

12 15 35 26 68 Count = 5 average = 31.2
图片描述

程序说明:

  • 文件一旦打开,你可以使用 >><< 进行输入和输出,类似于 cin >>cout <<。(高级说明:ifstreamistream 的子类,cin 属于 istreamofstreamostream 的子类,cout 属于 ostream。)
  • 类似地,IO 操纵符(如 fixedsetprecision()setw())也适用于文件流。

命名空间(Namespace)

当你使用不同的库模块时,总是存在名称冲突的可能性,因为不同的库可能会为不同的目的使用相同的名称。这个问题可以通过在 C++ 中使用 命名空间 来解决。命名空间 是同一命名作用域下的标识符集合。(在 UML 和 Java 中,它被称为 。)命名空间下的实体名称由命名空间名称限定,后跟 ::(称为作用域解析运算符),形式为 namespace::entityName

要将实体放置在命名空间下,请使用关键字 namespace,如下所示:

// 创建一个名为 myNamespace 的命名空间,用于包含以下实体
namespace myNameSpace {
   int foo;               // 变量
   int f() { ...... };    // 函数
   class Bar { ...... };  // 复合类型,如类和结构体
}

// 引用这些实体时,使用
myNameSpace::foo
myNameSpace::f()
myNameSpace::Bar

命名空间可以包含变量、函数、数组以及类和结构体等复合类型。

#include <iostream>

namespace a {   // 包含变量
   int i1 = 8;
   int i2 = 9;
}

namespace b {   // 包含函数
   int max(int n1, int n2) {
      return (n1 > n2) ? n1 : n2;
   }
}

int main() {
   std::cout << a::i1 << std::endl;                // 8
   std::cout << b::max(a::i1, a::i2) << std::endl; // 9
}

输出:

8
9
图片描述

使用命名空间

// 使用完全限定名称,
// 例如 std::cout、std::endl、std::setw() 和 std::string。
std::cout << std::setw(6) << 1234 << std::endl;

// 使用 using 声明来声明特定的标识符。
using std::cout;
using std::endl;
......
cout << std::setw(6) << 1234 << endl;

// 使用 using namespace 指令。
using namespace std:
......
cout << setw(6) << 1234 << endl;

// 对于较长的命名空间名称,你可以为其定义一个简写(或别名)
namespace shorthand = namespace-name;

总结

文件输入/输出的步骤如下:

  1. 创建一个 ifstream 用于输入,或 ofstream 用于输出。
  2. 通过 open(filename) 将流连接到输入或输出文件。
  3. 通过流插入运算符 << 执行格式化输出,或通过流提取运算符 >> 执行输入,类似于 cout <<cin >>
  4. 关闭文件并释放流。

在 C++ 中,实体(变量、函数或类)属于 全局命名空间(通过 :: 标识,没有命名空间名称)。