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.表达式

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

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

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;
}
相关推荐
思麟呀2 小时前
C++17(三)if constexpr+折叠表达式
开发语言·c++
ysa0510302 小时前
【板子】ST表
c++·笔记·算法·板子
恣逍信点2 小时前
主观是客观的聚焦
人工智能·学习·程序人生·生活·业界资讯·交友·哲学
CHHH_HHH3 小时前
【C++11】深入解析C++可变参数模板
开发语言·c++·算法·stl·c++11
宏集科技工业物联网3 小时前
宏集EXOR物联网HMI赋能上海易勒篮式研磨机智能化升级
经验分享·物联网·工业4.0·工业自动化·hmi·工控屏
十五年专注C++开发3 小时前
fatal error C1189: #error: WinSock.h has already been included 的解决方案
c++·socket·boost
打球她不香吗3 小时前
本周ALLegro学习内容的总结
学习·allegro
risc1234563 小时前
肌肉收缩会释放大量的肌细胞因子能抑制体内炎症因子
笔记
其实防守也摸鱼4 小时前
蓝队相关知识学习(1)---常用堡垒机和服务器
服务器·功能测试·学习·网络安全·网络攻击模型·攻防对抗·蓝队