本文是个人用于学习cpp时的笔记和记录。基于GitHub - InfiniTensor/learning-cxx · GitHub
00_hello_world
参考章节:
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
参考章节:
1.变量定义
前面类型后面变量名。可以赋初值。不赘述
2.表达式
运算符和操作数的序列。可以指定一个计算。
运算符很多种,基础的就**+** , - , * , / 等,比较,位运算等也都是。特殊点的比如new , delete ,sizeof
3.练习解析
用 类型+变量名,定义x变量
cpp
int x = 0;//改这一行
std::cout << x << " + " << x << " = " << x + x << std::endl;
return 0;
02_function
参考章节:
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¶meter
参考章节:
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
这次先看代码:
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;
}