欢迎光临
我们一直在努力

CS106L C++斯坦福大学计算机教程详解 一

前言:鉴于在C转C++的过程中,遇到的种种困难,我认为,有必要把我在学习C++的过程中和这套课程之间有所缺失的部分补齐,让初学者也能够听得懂,跟上名校的节奏,故写出此博客

CS106L C++ 学习笔记:第 1、2 课时(课程入门 · 字符串与流)

本合集把前两课合并为一篇:第 1 课时介绍课程工具、课程目标、C 与 C++ 的主要区别与标准 C++ 代码;第 2 课时深入讲解字符串、流(Stream)、ostringstream / istringstream 以及流的异常处理与状态位。


第一部分 · 第 1 课时:课程入门与概览

一、课程工具

  • 必须使用 QT Creator:以前从来没有听过这个软件。

二、编写代码的不同方式

  • 31:19:C++ 编写代码的不同方式。

三、C 语言与 C++ 的主要区别

  • 36:23:
    • 核心区别:C 语言无法抽象出"对象"与"类"的概念,无法表示复杂的数据总体。
    • 正如视频中所说,struct 是一个开放的公共列表,功能过于简单,无法起到更大的作用。
    • 这种更好的数据结构叫做类(class),和结构体是同一类东西,但更好用。
    • ⚠️ 它是否还有更大的作用,有待后续学习验证。

四、课程目标

  • 内存分配、向量类(vector):实际上就是 malloc 类的升级版,通常意味着更高效。
  • 完全表达代码中的意图和理想。
  • 42:22:课程的最终目标。
  • 45:25:标准 C++ 代码。

  • 五、标准 C++ 代码的不同之处

  • 开头有所不同:#include <iostream>——这实际上只是标准库的一个小部分。
  • 插入符号 <<。
  • std 与 ::、cout。
  • 这些内容会在后面的课时有相应的解释。
  • 在这里插入图片描述


    第二部分 · 第 2 课时:字符串与流(Stream)

    一、核心概念速览

    • C++ 字符串:真正的字符串类型 std::string(C 语言的 char* 只是字符指针,不是真字符串)。
    • 流(stream):一条能自动转换内容的"管道",把字符串 / 数字 / 小数统一输入输出。
    • << / >>:<< 把右边的数据"送进"左边的流对象(输出);>> 从流中"取出"数据存进变量(输入)。

    二、字符串:C 与 C++ 的区别

    • C 语言里"字符串"实际是 char*(字符指针)。
    • C++ 引入真正的字符串类 std::string:
      • 可以直接赋值。
      • 自动扩容空间。
      • 支持直接载入。

    三、流(Stream)

    3.1 流存在的目的与 << 的作用
    • 08:37:流存在的目的,以及 << 的作用和方式。
    • 整个流就是你所输出内容的总和,它提供了一个整体的接口。
    • 流能自动转化(类型转化)input 中的内容,字符串可被写入控制台。
    3.2 缓冲区与流
    • 12:06:缓冲区与流。
    • 如何创建一个字符串输出流,流能自动转化其中的内容。

    四、与 C 语言相比的四大不同

  • std::cout

    • 把字符串放进流中,再由重载的 << 输出到屏幕上。
    • 这就是"重载"的意义;cout / endl 替代了 C 的 printf,且具有实际语义。
  • 运载重算符(向左执行)

    • 优先取第一位的逻辑,把右边的数据输入到左边。
    • cout 与 endl 类似 C 中的函数:endl 会修改 cout 流的状态并执行一个动作(换行 + 刷新)。
    • 可以把字符直接载入右边的变量,无需提前开辟空间。
  • 字符串类 std::string

    • 可直接赋值、自动扩容、支持直接载入。
  • ostringstream 的用法

    • 详见下节。

  • 五、深入解析 ostringstream

    5.1 语句各部分含义

    ostringstream oss("Ito‑En Green Tea");

    部分含义
    ostringstream 类名,代表"输出字符串流"(流管道类型)
    oss 对象变量名,自己取的名字
    ("Ito‑En Green Tea") 构造函数传参:对象创建的瞬间,把字符串送入内部缓冲区,作为初始内容

    这一步是对象初始化(构造),即创建对象的同时给内部成员赋初始值。

    5.2 为什么不需要 = 等号赋值

    C++ 类对象有两种初始化写法,效果等价:

    // 写法1:括号直接初始化(当前代码)
    ostringstream oss("Ito‑En Green Tea");

    // 写法2:等号拷贝初始化,效果一样
    ostringstream oss = ostringstream("Ito‑En Green Tea");

    • 括号 () 的作用:在创建对象的那一行,直接调用类的构造函数,把括号内的数据交给对象完成初始化,因此不需要写 =。
    • ⚠️ 注意:括号只在定义对象这一行代表构造传参。对象创建完成后,不能再写 oss("xxx")。
    • ❌ 错误写法:对象建好后,不能直接用 = 给 ostringstream 赋值字符串。

    ostringstream oss;
    oss = "Ito‑En Green Tea"; // 编译报错,不支持该赋值

    对比基础类型:int a = 10; 是内置基础类型,用等号赋值;而类对象支持"构造函数括号传参"的初始化语法。

    5.3 ostringstream 与 std::string 的区别

    两行初始化写法长得很像,但底层完全不同:

    std::string s("Ito‑En Green Tea");
    ostringstream oss("Ito‑En Green Tea");

    对比项std::stringostringstream
    本质 纯粹的字符串存储容器,专门存放字符 输出流管道对象,主打格式化写入
    追加内容 += / .append() 重载运算符 <<
    数字处理 不能直接写入数字,需手动转换 oss << 123 << 3.14; 自动把数字转文本
    取出内容 直接使用变量本身 必须调用 .str(),导出一份 std::string 拷贝
    流能力 不是流,不能用 << 写入 属于 ostream 输出流,支持 << 管道写入
    通俗比喻
    • std::string:罐子,专门装文字,往里加文字用 +=。
    • ostringstream:带管道入口的罐子,可以通过管道 << 丢字符串、数字、小数;想读取全部内容,调用 .str() 拿出来。
    使用场景选择
  • 只做普通字符串存储、拼接 → 使用 std::string。
  • 需要混合拼接字符串、数字、浮点数做格式化 → 使用 ostringstream。
  • 重要小坑

    .str() 返回的是缓冲区的拷贝快照,不是引用。

    ostringstream oss("aaa");
    std::string s = oss.str();
    oss << "bbb";
    // s 的内容不会跟着改变,s 保存的是调用 .str() 那一刻的副本


    六、C 语言等价对照

    6.1 ostringstream oss("Ito‑En Green Tea");

    char buf[256];
    strcpy(buf, "Ito‑En Green Tea");

    6.2 oss << "16.9 Ounces";

    strcat(buf, "16.9 Ounces");

    • ostringstream 会自动扩容;C 语言 char 数组大小固定,容易缓冲区溢出。
    • ostringstream 可以直接 <<数字;C 语言需要借助 sprintf 格式化。

    七、<< 与 >> 的区别(直观体现)

    在这里插入图片描述


    八、深入解析 istringstream(输入流)

    在这里插入图片描述

    8.1 作用
    • istringstream 输入流从已有字符串中读取数据:把变量命名后输入进去存储,再通过 >> 把数据输出成其他变量。
    • 如图所示:
    8.2 执行原理

    以原始流内容 16.9 \\n Ounces. . \\t \\n \\n -38271 为例,流内部维护一个读取光标,每次读取后光标移动,逐个取出不同类型的数据:

  • iss >> token1(int):读取 16,碰到 .。. 对 int 是无效字符,读取停止。token1 = 16;. 残留在流缓冲区,光标停在 .。
  • iss >> token2(string):>> 读取 string 只跳过空白,. 不是空白,直接读取 .9;遇到换行 \\n(空白)停止。token2 = ".9",光标跳到 O。
  • iss >> token3(char):跳过空白,读取单个字符 O。token3 = 'O',光标移到 u。
  • iss >> token4(bool):当前字符是字母 u,bool 只能识别 0 / 1,解析失败。流进入错误状态,读取失败,token4 得到垃圾随机值;此后流的读取全部失效。
  • 在这里插入图片描述

    8.3 核心规则
  • 停止读取的两种情况(满足其一即停止):
    • 遇到空白字符(如 \\n、\\t)。
    • 遇到对目标类型无效的字符。
  • 导致停止的字符不会被消耗,保留在流中,交给下一次读取。
  • 完全解析失败时,流置错误标记,之后所有读取不再生效。
  • 8.4 自动转化形式

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    显然在这里我们能清晰地看见:当在内存中开辟了空间之后,任何流的输入输出都会自动转化形式。


    九、istringstream 与 std::string 的区别

    • s 是一个变量储存的容器,直接存放内容。
    • iss 是 istringstream 功能的一个载体/替代品:你必须先"把东西塞进去",之后才能使用 istringstream 的读取功能。
    • 需要分辨清楚 iss 与 s 的本质差别。
    • 实际上我们要明白的是iss和istringstream之间是有很强的关联性的,实际上iss就代表着为了istringstream这个输出流开辟出的空间,s是存储内容是变量这一点不会有错,但是要将东西放入一个区域才能实现不同于C语言中繁琐的强制转化以及开辟空间的过程,直接使用istringstream就能实现流的直接传输

    在这里插入图片描述


    十、状态位(Stream State)

    10.1 什么是状态位
    • 当流解析失败或遇到错误时,会设置对应的状态位。
    • 状态位用于标记流当前的健康状态:正常 / 文件末尾(EOF)/ 读取失败 / 写入失败等。
    • 可以把状态位理解为流给程序的一份**“健康报告”**。

    在这里插入图片描述

    10.2 EOF 与错误信息
    • EOF(End Of File,文件末尾) 实际上可以报出错误信息的具体情况,可以参考之前学过的 C 语言部分。
    • ⚠️ 这一部分还需要多复习一点。

    在这里插入图片描述

    在这里插入图片描述 在这里插入图片描述

    10.3 提取失败的提示
    • 此处增加了一个"是否成功读取出整数"的提示:
      • 如果没有在开头提取出来,就会报错;
      • 然后进入下一个进程,判断后续有没有整数。

    在这里插入图片描述


    十一、异常处理:throw std::domain_error("xxx")

    throw std::domain_error("xxx");

    各部分含义:

  • throw:抛出异常,函数立刻终止,不再往下执行。
  • std::domain_error:标准异常,代表传入的参数不合法,超出函数可处理范围。
  • 引号内:错误描述文本。
  • 头文件:需要 #include <stdexcept>。
  • 行为:

    • 合法输入:不 throw,return 结果。
    • 非法输入:throw 抛出错误,代码停止,错误向上传递。

    ⚠️ 当前代码没有 try‑catch 捕获异常,一旦 throw,程序直接崩溃退出。

    赞(0)
    未经允许不得转载:171主机测评 » CS106L C++斯坦福大学计算机教程详解 一
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址