C++学习笔记(基于learn-cxx)(1)

本文是个人用于学习cpp时的笔记和记录。基于GitHub - InfiniTensor/learning-cxx · GitHub

00_hello_world

参考章节:

stdin, stdout, stderr - cppreference.com

输入/输出操纵符 - cppreference.com

std::format - cppreference.com

1.stdin, stdout, stderr

stdin: 与标准输入流关联,用于读取约定的输入。

stdout: 与标准输出流关联,用于写入约定的输出。

stderr: 与标准错误流关联,用于写入诊断输出。

2.输入/输出操纵符

操纵符是能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。

这里我们先记几个常用的。比如调整浮点数输出、输出换行、控制输出宽度之类的

换行使用endl

3.std::format

c++20引入。可以便捷的格式化字符串。

比如,用变量占位,格式控制

cpp 复制代码
#include <format>
#include <iostream>

int main() {
    // {} 就是"占位符",会被后面的参数替换
    std::string s = std::format("Hello {}!", "world");
    std::cout << s; // 输出: Hello world!

    // 多个占位符,按顺序填入
    std::string s2 = std::format("{} + {} = {}", 1, 2, 3);
    std::cout << s2; // 输出: 1 + 2 = 3

    // 也可以指定顺序(用数字索引)
    std::string s3 = std::format("{1} before {0}", "world", "hello");
    std::cout << s3; // 输出: hello before world
}
cpp 复制代码
// 数字控制
std::format("{:.2f}", 3.14159);  // "3.14"  (保留2位小数)
std::format("{:#06x}", 255);     // "0x00ff"(16进制,补零到6位)

// 字符串对齐
std::format("{:>10}", "hi");     // "        hi"(右对齐,占10格)
std::format("{:*^10}", "hi");    // "****hi****"(居中,用*填充)

// 数字千分位
std::format("{:L}", 1234567);    // "1,234,567"(需要设置locale)

此外,这个会在编译时进行检查,与参数部匹配就报错。

另外,format只能使用常量。若使用运行时变量,请使用std::vformat

cpp 复制代码
std::string user_fmt = "Hello {}!";
// std::format(user_fmt, "world");  // ❌ 编译错误(非常量)
std::vformat(user_fmt, std::make_format_args("world"));  // ✅ 正确

4.练习解析

本章使用cout和操纵符输出和换行即可

cpp 复制代码
int main(int argc, char **argv) {
    // TODO: 在控制台输出 "Hello, InfiniTensor!" 并换行
    std::cout << "Hello, InfiniTensor!" << std::endl;
    return 0;
}

01_variable&add

参考章节:

表达式 - cppreference.com

1.变量定义

前面类型后面变量名。可以赋初值。不赘述

2.表达式

运算符和操作数的序列。可以指定一个计算。

运算符很多种,基础的就**+** , - , * , / 等,比较,位运算等也都是。特殊点的比如new , delete ,sizeof

3.练习解析

用 类型+变量名,定义x变量

cpp 复制代码
 int x = 0;//改这一行
 std::cout << x << " + " << x << " = " << x + x << std::endl;
 return 0;

02_function

参考章节:

​​​​​​​声明 - cppreference.com

解释复杂声明符 | Microsoft Learn

1.函数声明

如果函数在主函数前,,无需声明。在后面,你需要在前面弄上"返回类型 函数名(参数类型)"的声明。

2.返回

return可以返回你要返回的值。注意类型要与定义的类型一样。

3.练习解析

添加声明,返回a + b.

cpp 复制代码
int add(int a, int b);

int main(int argc, char **argv) {
    ASSERT(add(123, 456) == 123 + 456, "add(123, 456) should be 123 + 456");

    auto x = 1, y = 2;
    std::cout << x << " + " << y << " = " << add(x, y) << std::endl;
    return 0;
}

int add(int a, int b) {
    // TODO: 补全函数定义,但不要移动代码行
    return a + b;
}

03_argument&parameter

参考章节:

1.形参和实参

实际传递进函数的值,是实际参数。

跳转到函数内后,你对接收的变量,进行修改,不影响原先传进去的值。

2.主函数的参数

是的,主函数也有形参。

argc --- Argument Count

  • 类型:int

  • 含义:命令行参数的个数(包括程序名本身)

argv --- Argument Vector

  • 类型:char**(字符串数组)

  • 含义:每个命令行参数的内容

你在命令行里,添加参数,就会传进argv数组内。

bash 复制代码
./exercise hello world

那么:

bash 复制代码
argc = 3

argv[0] = "./exercise"   ← 程序名本身
argv[1] = "hello"        ← 第1个参数
argv[2] = "world"        ← 第2个参数

不带参数,也有一个程序名的参数。

bash 复制代码
./exercise
bash 复制代码
argc = 1
argv[0] = "./exercise"

3.练习解析:

原先代码assert内是空的,需要自己填。这里我们理解形参实参,就可以解决了。

cpp 复制代码
// TODO: 为下列 ASSERT 填写正确的值
int main(int argc, char **argv) {
    auto arg = 99;
    ASSERT(arg == 99, "arg should be ?");
    std::cout << "befor func call: " << arg << std::endl;
    func(arg);
    ASSERT(arg == 99, "arg should be ?");
    std::cout << "after func call: " << arg << std::endl;
    return 0;
}

// TODO: 为下列 ASSERT 填写正确的值
void func(int param) {
    ASSERT(param == 99, "param should be ?");
    std::cout << "befor add: " << param << std::endl;
    param += 1;
    ASSERT(param == 100, "param should be ?");
    std::cout << "after add: " << param << std::endl;
}

04_static

存储类说明符 - cppreference.com

这次先看代码:

cpp 复制代码
#include "../exercise.h"

// READ: `static` 关键字 <https://zh.cppreference.com/w/cpp/language/storage_duration>
// THINK: 这个函数的两个 `static` 各自的作用是什么?
static int func(int param) {
    static int static_ = param;
    // std::cout << "static_ = " << static_ << std::endl;
    return static_++;
}

int main(int argc, char **argv) {
    // TODO: 将下列 `?` 替换为正确的数字
    ASSERT(func(5) == ?, "static variable value incorrect");
    ASSERT(func(4) == ?, "static variable value incorrect");
    ASSERT(func(3) == ?, "static variable value incorrect");
    ASSERT(func(2) == ?, "static variable value incorrect");
    ASSERT(func(1) == ?, "static variable value incorrect");
    return 0;
}

1.两个static有啥区别?

函数的static:限制函数只能在本文件内使用。控制可见域。

变量的static:延长生命周期,此变量活到程序结束。并且只初始化一次!(后面的初始化那一行的赋值全无效)

正常的函数内变量,函数结束就回收。而他会一直在。

所以每次++,会一直记得,另外只初始化一次,所以一直增加

2.a++和++a

++是自增,这里是在变量后面,所以是先返回后自增。所以第一个断言是5

3.练习解析:

第一次变成5,返回,自增。然后以此类推。

cpp 复制代码
#include "../exercise.h"

// READ: `static` 关键字 <https://zh.cppreference.com/w/cpp/language/storage_duration>
// THINK: 这个函数的两个 `static` 各自的作用是什么?
static int func(int param) {
    static int static_ = param;
    // std::cout << "static_ = " << static_ << std::endl;
    return static_++;
}

int main(int argc, char **argv) {
    // TODO: 将下列 `?` 替换为正确的数字
    ASSERT(func(5) == 5, "static variable value incorrect");
    ASSERT(func(4) == 6, "static variable value incorrect");
    ASSERT(func(3) == 7, "static variable value incorrect");
    ASSERT(func(2) == 8, "static variable value incorrect");
    ASSERT(func(1) == 9, "static variable value incorrect");
    return 0;
}
相关推荐
YYYing.41 分钟前
【设计模式系列 (七) 】桥接模式
c++·后端·设计模式·桥接模式
喜欢打篮球的普通人1 小时前
MiniMind 学习笔记(十二):Pretrain 实操——从版本梳理到 8GB 显卡上的真实训练
人工智能·笔记·学习
泵管家1 小时前
多泵联动控制器工作原理与应用选型指南
经验分享
高山有多高2 小时前
【Linux笔记】Linux自定义Shell
linux·c++
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(87):VizoMem——把文本历史转化为可检索的视觉记忆
论文阅读·人工智能·学习·开源·github
悠仁さん2 小时前
【C++】vector 类
开发语言·c++
_upupup2 小时前
智能指针的原理及简单模拟实现(C++)
开发语言·c++
l1t2 小时前
DeepSeek总结的OpenZL压缩变换器
c++·算法
郝学胜-神的一滴2 小时前
C++ Templates 01:拨开迷雾,读懂C++模板经典著作
开发语言·c++·程序人生·游戏·游戏引擎·软件构建
坤坤子吖2 小时前
算法学习——高精度加减乘除
c++·笔记·学习·算法