前面几篇都在讲”怎么写对”. 但真实情况是: 代码写完, 编译过了,
一跑结果不对. 这时候该怎么办
这篇不按知识点排, 按报错的形状排 ——
从”编译器直接骂你”到”编译一声不吭但结果错了”, 难度递增.
每一节都是”看到什么现象 → 往哪儿想 → 怎么查”
0 综述
123456789101112131415161718程序跑不对怎么办├── 1 先分清楚三类错误├── 2 基础: 编译器报错怎么读├── 3 基础: 中英文标点├── 4 基础: 少分号、多分号├── 5 基础: 大括号不配对├── 6 基础: scanf 忘了 &├── 7 基础: 格式符和类型不匹配├── 8 基础: 数组越界├── 9 进阶: 编译过了但结果不对├── 10 进阶: 变量没初始化├── 11 进阶: 整数除法与精度├── 12 进阶: 死循环怎么找├── 13 进阶: 打印式调试├── 14 提高: 学会看警告├── 15 提高: 二分定位法├── 16 提高: 崩溃了怎么查└── 17 提高: 查错清单
1 先分清楚三类错误
看到程序不对劲, 第一步不是改代码,
而 ...
流程控制那篇里,
猜数字游戏最多让用户猜 5 次. 要是把 max_try 改成 100,
循环本身没问题, 但”把用户猜过的数都存下来”这件事就做不到了 —— 总不能写
100 个变量 guess1 到 guess100
数据类型讲过,
一个变量就是一个盒子. 现在需要的是一排编好号的盒子,
用的时候拿编号去取. 这个东西就是数组
0 综述
123456789101112数组与字符串├── 1 从"存100个数"说起├── 2 一维数组: 定义、初始化、引用├── 3 数组在内存里是连续的├── 4 二维数组├── 5 字符数组与字符串├── 6 字符串的结束标志 \0├── 7 字符串处理函数├── 8 输入输出: gets / puts / fgets├── 9 数组作函数参数├── 10 一个完整的例子: 统计与排序└── 11 拓展: 数组名到底是什么
1 从”存100个数”说起
回到猜数字那个需求. 现在想让它记录每一次猜的数,
最后一起打印出来. 按数据类型的写法:
1int guess1, guess2, guess3, gu ...
运算符与表达式最后那个计算器,
里面已经出现了 if 和 else if.
当时用得理所当然, 没解释为什么写成那样. 那篇的重点是”怎么算”,
这篇要解决的是”算完之后, 程序该往哪儿走”
到目前为止写过的所有程序都有一个共同点: 从上到下,
一行一行执行到底, 中间不会拐弯. 哪怕计算器里有五个分支,
走的也是一条直线的形状——写完一个 else if 就轮到下一个
真实程序不能这么死板. 输入密码要判断对错, 分数要分等级,
菜单要等用户选. 这些都需要程序能拐弯,
甚至回头重做. 让程序拐弯的语法, 就叫流程控制
0 综述
12345678910111213141516流程控制├── 1 顺序结构: 默认的走法├── 2 if: 让程序拐第一个弯├── 3 条件表达式与"非零即真"├── 4 if 的嵌套与悬空 else├── 5 switch: 多路分支├── 6 循环: 让程序回头├── 7 while├── 8 do-while├── 9 for├── 10 三种循环怎么选├── 11 break 与 continue├── 12 ...
这是 F401 这一半的事. 接收 G431 吐过来的波形, 采下来, 认出是什么波,
再画到屏幕上
工程叫 Wave2, 代码都在 Core/Src 下
这块板子在干嘛
F401 拿到的是 G431 送过来的模拟信号. 它要干四件事
用 ADC 采下来, 每帧 500 点
从这 500 点里算出几个特征
靠特征判断这是什么波形
画到 OLED 上, 屏幕得能同时看到波形形状和识别结果
采集和 G431 是硬件同步的, 两边都用 100 kHz 触发,
所以采样率和信号频率是严格的整数比
1231 kHz 的信号, 100 kHz 采样每周期点数 = 100000 / 1000 = 100 点一帧 500 点 = 正好 5 个完整周期
5 个整周期这个数很舒服, 不整周期的话做频谱要加窗, 现在直接就能用
文件清单
文件
角色
关键内容
waveid.c
识别算法全部实现
特征提取 + 顺序判定, 不依赖任何 HAL 类型
app.c
业务逻辑
采集, 识别, 多 ...
本文只写 G431 这一半的事. 波形怎么造出来, 怎么发出去
F401 那边的采集和识别另开一篇
工程叫 Wave1, 代码都在 Core/Src 下
G431功能综述
G431 在这套系统里是个”信号源”. 它的活儿很单纯:
吐波形, 而且要用一种接收端能对得上的方式吐.
最后定了 5 种: 正弦、方波、三角、锯齿、阶梯. 前四种是常规操作,
阶梯波是特意加的, 后面会说为什么.
最初的方案不是这样. 一开始正弦走 DAC, 方波走 TIM3 的硬件 PWM 从 PA6
出来, 两种波形两个引脚, 各走各的. 这个方案被我自己毙掉了,
原因在下面「所有波形都挤到一个引脚上」那一节.
文件清单
文件
角色
关键内容
wavegen.c
波形表生成
5 种波形, 全走 PA4, 改表即换波形
main.c
主入口
按键切波、串口命令、justfloat 打包发送
dac.c
DAC1 配置
G4 特有, 外设侧必须 WORD 对齐
adc.c
ADC1 配置 ...
数据类型那篇里,
我们让 5/2 得出了 0.000000 这个莫名其妙的结果,
当时说”格式符和类型不匹配”. 但还有个更基础的问题, 考虑如下代码:
12345678#include <stdio.h>int main() { int a = 5, b = 2; double c = a/b; printf("%lf", c); // 输出 2}
上面这段代码里, c 是 double,
printf 也用 %f 输出, 按理说该打印
2.5. 可实际结果是 2.000000 —— 问题出在
5/2 这一步, 它根本没算出 2.5
这就轮到运算符了
1 C 的运算符
打开任何一本教材的运算符表, 密密麻麻几十行,
第一反应是这牛魔要背到什么时候. 其实它们分成几类,
而且大部分早就会用, 只是不知道名字:
类别
运算符
干什么
算术
+ - * / %
加减乘除取余
关系
> < >= <= == !=
比大小 ...
准备操作那篇里敲过一段代码,
当时说”目前不用知道原理”. 现在该把那段代码拆开看一看了
这篇不打算先讲什么数据类型、什么运算符,
因为脱离代码去记这些名词没什么意义. 我们直接盯着一个能跑的程序,
一行一行搞清楚它在干什么. 等有了”一个C程序大概长什么样”的印象,
后面的东西才好往这个框架里塞
0 综述
123456789第一个程序├── 1 最小程序逐行拆解├── 2 头文件与 #include├── 3 main 函数: 程序的出入口├── 4 函数的形状: 首部 + 函数体├── 5 语句、分号与注释├── 6 输出: printf 初步├── 7 输入: scanf 初步└── 8 其他猎奇题目
1 最小程序逐行拆解
把准备操作里的那段拿来:
123456#include <stdio.h>int main() { printf("type in whatever you want to print"); return 0;}
四行代码, 去掉空行其实就四件事:
行
代码
...
观前提醒: 本章干货极多, 书中以表格展现为主, 本人认为这样反人类反直觉,
且极难学习, 故在本篇笔记中穿插了大量具体实例辅助理解,
同时对于一些结论性的内容辅以具体推算, 不要一口气吃完, 读读写写才有效
第一个程序里我们用
int age; 存过一个年龄, 但没解释那个 int
是什么意思. 这篇就来说清楚”数据往哪儿放、能放什么”
0 综述
1234567891011121314数据类型├── 1 为什么需要变量├── 2 变量的三个要素: 类型、名称、值├── 3 命名规则与标识符├── 4 基本数据类型├── 5 类型修饰符├── 6 各类型占多少字节: sizeof├── 7 常量├── 8 转义字符├── 9 类型转换├── 10 printf/scanf 格式符├── 11 单字符 IO: putchar 与 getchar├── 12 一个完整的例子└── 13 拓展: 数据在内存中的存储形式
1 为什么需要变量
第一个程序最后的那个例子是这样的:
1234int age;printf("Input your age:" ...
上一篇历史知识里提到存储器时只说了句”分内存、外存”.
但真到算容量、算地址、看八进制常量的时候, 这些概念是绕不开的,
所以单独开一篇.
这一篇在卷面上的权重不低: 进制转换几乎年年有,
地址与容量的计算题也常出.
而”各类存储介质的特点”这种纯背诵的内容近年考得很少, 书上却写得极多,
下面会明确标出哪些看一眼就行.
计算部分(地址与容量、进制互转)是必考的,
建议连例题一起动手算一遍; 概念部分只需记结论
0 综述
1234567891011存储器与进制├── 1 存储器基础(★★★★)│ ├── 存储单元与存储地址│ ├── 存储单位(bit/B/KB/MB/GB/TB)│ └── 内存与外存的区别├── 2 地址与容量计算(★★★★★)│ └── 地址总线根数 → 寻址范围├── 3 进制转换(★★★★★)│ ├── 十 ↔ N│ └── 二 ↔ 八 ↔ 十六(不必过十进制)└── 4 各类进制的用途与优缺点(★★)
1 存储器基础(★★★★)
1.1 存储单位
从小到大共六层. 相邻两级之间除 ...
开始学 C 之前, 大多数教材都要先铺一堆计算机发展史.
问题是这部分内容在书里动辄写几十页,
而真正会出现在卷子上的可能就两三个空.
所以这篇笔记的写法是: 先按框架把该懂的讲清楚,
再把”书上写了一大堆但根本不考”的挑出来,
最后单独开一节写”书上没细讲但真题考过”的.
凡是我觉得不值得深究的, 则仅贴出应试所需背诵的结论
部分内容部分教材不作涉及可跳过
关于进制转换、存储容量计算这些偏计算的内容见后续笔记
0 综述
这章的知识点只有五块, 而且彼此是并列关系
12345678C语言概念知识├── 1 冯·诺依曼体系结构 ← 最常考, 必须记牢│ └── 程序存储思想├── 2 电子计算机发展历程 ← 只考"名称的先后顺序"├── 3 程序设计语言的种类 ← 略懂即可├── 4 C语言的优势 ← 选择题常出└── 5 C语言的开发过程 ← 最常考, 必须记牢 └── 编辑 → 编译 → 链接 → 运行
按重要度排, 大概是这样:
板块
重要度
...
博客快捷键
shift K
关闭快捷键功能
shift A
打开/关闭中控台
shift M
播放/暂停音乐
shift D
深色/浅色显示模式
shift S
站内搜索
shift R
随机访问
shift H
返回首页
shift F
友链鱼塘
shift L
友链页面
shift P
关于本站
shift I
原版/本站右键菜单
数据库加载中
通知
你好呀











