第一周学习笔记

第一周 C语言

第一讲

一、转义序列
  1. 由 \ + 特定字母组成,用于表示无法直接输入的字符。

  2. \n 表示换行。

printf("hello miuc \n hello may");

运行结果:

hello miuc 
hello may
二、占位符
  1. 使用 % 作为标记。

  2. %d 用于 int 类型。

  3. %f 用于 float 类型。

  4. %c 用于 字符 类型。

  5. %n.mf
    

    %n.md
    

    格式详解:

    • n最小栏宽。若数据宽度小于 n,则在左侧补空格;若大于 n,则按实际宽度显示。

    • m(对于 %n.md):显示的最小有效位数。若实际位数少于 m,则在左侧补 0;超过则正常显示。

    • m(对于 %n.mf):小数点后的保留位数。默认为6位。

#include <stdio.h>
#include <stdlib.h>
​
int length = 2, width = 3, high = 4;
int volum;
​
int main(int argc, char *argv[]) {
    volum = length * width * high;
    printf("体积=%d", volum);
    return 0;
}

运行结果:体积=24

三、读取用户输入
scanf("%d", &length); // 注意变量名前需要加 & (取地址符)
scanf("%d", &width);
scanf("%d", &high);
四、宏定义 #define
#define PI 3.14f // 定义常量PI,值为3.14(单精度浮点数)
五、随堂练习
  1. 输入圆半径,计算体积。

  2. 输入两个不同圆的半径,分别计算体积。

  3. 在2的基础上,将圆周率精度提升至3.14159。

#include <stdio.h>
#include <stdlib.h>
#define PI 3.14 // 宏定义
​
int r_1, r_2;
float volum_1, volum_2;
​
int main(void) {
    printf("请输入第一个圆的半径:");
    scanf("%d", &r_1);
​
    printf("请输入第二个圆的半径:");
    scanf("%d", &r_2);
​
    // 注意:使用 4.0f/3.0f 确保浮点数运算
    volum_1 = 4.0f / 3.0f * PI * r_1 * r_1 * r_1;
    volum_2 = 4.0f / 3.0f * PI * r_2 * r_2 * r_2;
​
    printf("第一个圆的体积为:%f\n第二个圆的体积为:%f ", volum_1, volum_2);
​
    return 0;
}

第二讲

一、布尔值 (_Bool)
  • 0 代表“假”(false)。

  • 任何非0值都代表“真”(true)。


第三讲

一、while 循环中的 i----i
  • while(i--) : 先判断 i 是否为真(非0),再执行 i--。因此,若初始 i=5,会循环5次(i值变化:5,4,3,2,1,0结束)。

  • while(--i) : 先将 i 减1,再判断新值是否为真。因此,若初始 i=5,会循环4次(i值变化:4,3,2,1,0结束)。

二、do...while 循环

特点:无论条件是否满足,循环体至少会被执行一次。

其中while(条件),一旦满足括号内条件,将继续循环下去。

// 数字位数判断程序
#include <stdio.h>
#include <stdlib.h>

int num;
int digit_count = 0; // 变量名更清晰

int main(void) {
    printf("请输入一个数字:");
    scanf("%d", &num);

    do {
        num /= 10;
        digit_count++;
    } while (num > 0);

    printf("这个数字为%d位\n", digit_count);

    return 0;
}
三、continue 语句

continue 用于跳过本次循环中剩余的语句,直接开始下一次循环的判断(而不是结束整个循环)。


第四讲

一、浮点数
  • 十进制浮点数:科学记数法,例如 6.324572 * 10^2

  • 二进制浮点数:由符号位、阶码、尾数构成(具体标准如IEEE 754)。

  • 精度丢失问题:由于二进制无法精确表示所有十进制小数,应避免直接使用 ==!= 比较浮点数。推荐使用基于误差范围的方法:

float a = 0.1f;
float epsilon = 0.0000001f; // 定义一个很小的误差范围

int main(void) {
    if ((a - 0.1) < epsilon && (a - 0.1) > -epsilon) {
        // 认为 a 约等于 0.1
    }
    return 0;
}
二、int 类型
  • 大小:通常为 4字节(32位系统)。2字节是旧式16位系统的标准,现代编程环境下应为4字节。请参考后面的“错题”部分。

  • 范围:4字节时,范围为 -2,147,483,648 到 2,147,483,647。

三、char 类型
  1. 有符号 char

    • 字长:1字节

    • 范围:-128 到 127

  2. 无符号 unsigned char

    • 字长:1字节

    • 范围:0 到 255

  3. 占位符%c

  4. 表示方法:用单引号 '' 包裹,如 'a', 'Z'

四、define 惯用法

可以使用 #define 为已有的数据类型起一个简短易记的别名,这在嵌入式开发中尤其常见。

#define u8 unsigned char
#define u16 unsigned int
// 之后就可以用 u8 myVar; 来代替 unsigned char myVar;

第五讲

一、字符与字符串
  • 字符串:用双引号 " " 括起来,如 "hello"。本质是以 \0 结尾的字符数组。

  • 字符:用单引号 ' ' 括起来,如 'a', 'b'

  • 声明方式:

    char string1[3] = {'a', 'b', 'c'}; // 字符数组,未自动添加 '\0'
    char string2[] = "abc";           // 字符串,编译器会自动添加 '\0',大小为4
    
  • 占位符:

    • 字符串:%s

    • 字符:%c

二、指针
  • 概念:指针是一个变量,其值为另一个变量的内存地址

  • 关键点:数组名本身就是一个指向数组首元素的常量指针

#include <stdio.h>
#include <stdlib.h>

int a = 1;
int* p = NULL; // 声明一个指向int类型的指针,并初始化为空

int main(void) {
    p = &a;      // 将变量a的地址赋值给指针p
    *p = 5;      // 通过解引用操作符 *,修改p所指向的内存单元的值,即a的值变为5

    printf("%d", a); // 输出结果为 5
    return 0;
}

第六讲

一、函数传指针(实现交换)

通过传递变量的地址(指针),函数内部可以修改外部变量的值。

#include <stdio.h>
#include <stdlib.h>

int a = 2, b = 3;

void exchange(int* x, int* y) {
    int temp = 0;
    temp = *x;  // 取出x指向的值
    *x = *y;    // 将y指向的值赋给x指向的位置
    *y = temp;  // 将临时值赋给y指向的位置
}

int main(void) {
    exchange(&a, &b); // 传入a和b的地址

    printf("a=%d, b=%d", a, b); // 输出: a=3, b=2
    return 0;
}
二、递归操作

函数调用自身的编程技巧。必须有明确的终止条件,否则会无限递归导致栈溢出。

int fact(int n) {
    if (n <= 1)
        return 1;     // 终止条件:0! 和 1! 都等于1
    else
        return n * fact(n - 1); // 递归调用自身
}

错题整理(附解析)

  1. 题目:在32位计算机上,int型变量常见的大小是(2)字节,(8)位。

    • 正确答案4 字节,32 位。

    • 解析:32位计算机的字长是32位,即4个字节。这是现代C语言标准下最常见的 int 大小。你笔记中写的2字节是16位时代的产物。

  2. 题目:在32位电脑上,一个存放 int型变量的数组 a,其中最后一个元素为 int型变量的数组 a,则该数组占用的内存为(36)字节。

    • 正确答案36 字节。

    • 解析:数组下标从0开始,最后一个元素是 a[8],说明数组共有9个元素(a[0]到a[8])。每个 int 占4字节,所以总大小为 9 * 4 = 36 字节。

  3. 题目:以下变量名合法的是(B)。

    • A. 67num B. _32student C. float D. 32_student

    • 正确答案B

    • 解析:C语言变量命名规则:只能由字母、数字和下划线组成,且不能以数字开头,也不能与C语言关键字(如 float, int, if 等)重名。

  4. 题目:在C语言中,switch 只能测试整型表达式的值。(F)

    • 正确答案T

    • 解析switch 语句的表达式必须是整型(如 int, char, enum 等)或能隐式转换为整型的类型。它不能直接用于判断浮点数或字符串。

  5. 题目:进制转换程序(0-255 → 十六进制 & 二进制)

    #include <stdio.h>
    #include <stdlib.h>
    
    int num;
    int Hex[2];
    int Binary[8];
    
    int main(void) {
    	int i;
    	int temp;
    	
    	do
    	{
    		printf("请输入一个十进制数(0-255):");
    		scanf("%d",&num);
    		if(num>255 || num<0)
    			printf("输入错误!请输入0-255之间的整数\n");
    	}while(num>255 || num<0);//只要输入小于0 或者 大于255,就继续循环(错误点)
    	
    	
    	temp = num;
    	for(i=0;i<2;i++)
    	{
    		Hex[i] = temp % 16;
    		temp /= 16;
    	}
    	
    	temp = num;
    	for(i=0;i<8;i++)
    	{
    		Binary[i] = temp % 2;
    		temp /= 2;
    	}
    	
    	printf("\n16进制:0x");
    	for(i=1;i>=0;i--)
    	{
    		if(Hex[i]<10)
    			printf("%d",Hex[i]);
    		else
    			printf("%c",'A'+Hex[i]-10);
    	}
    	
    	printf("\n2进制:");
    	for(i=7;i>=0;i--)
    	{
    		printf("%d",Binary[i]);
    		if(i==4)
    			printf(" ");
    	}
    	
    	return 0;
    }
    
    • 错误点:

      1. do...while 的条件写反了:原代码 while(num>255 || num<0) 是正确的。你的错误可能是最初写成了 while(num>=0 && num<=255),这会导致输入正确时反而一直循环。正确的逻辑是:“只要输入不合法(小于0或大于255),就继续循环”。

      2. 不会用 %c 显示字符:在将数字(10-15)转换为对应的十六进制字符(‘A’-‘F’)时,使用了 'A' + Hex[i] - 10 这个巧妙的表达式来计算字符的ASCII码,然后用 %c 打印出来。这是一个非常好的技巧,你已经掌握了。