代码随想录-C-笔记

001_704_二分查找

int count = (left + right) / 2; // 当 left + right 的结果是奇数(除以 2 得小数)时,会直接舍弃小数部分,也就是向下取整(向零取整)

  • 正数场景:5/2 = 2(不是 2.5,也不是 3)、7/2 = 3
  • 负数场景:(-5)/2 = -2(同样截断小数,向零取整,不是 - 3)。

002_27_移除元素

for(int i = 0;i < numsSize;i++) 里的 i++在循环体代码执行完毕后才会执行

for 循环的完整执行流程(核心)

for(表达式1; 表达式2; 表达式3) { 循环体 } 的执行顺序是固定的:

  1. 第一步 :执行 表达式1int i = 0)------ 仅在循环开始时执行 1 次,用来初始化变量;
  2. 第二步 :判断 表达式2i < numsSize)------✅ 如果为真:执行循环体代码;❌ 如果为假:直接退出循环;
  3. 第三步 :循环体执行完毕后,执行 表达式3i++)------ 这就是 i 自增 1 的时机;
  4. 第四步:回到第二步,重复判断表达式 2,直到为假。

想了半天只想到

cpp 复制代码
int removeElement(int* nums, int numsSize, int val) {
    int count = 0;
    for(int i = 0;i < numsSize;i++)
    {
        if(nums[i] == val)
        {
            for(int j = i;j < numsSize - 1;j++)
            {
                nums[j] = nums[j+1];
            }
            i--;
        }
        else
        {
            count ++ ;
        }
    }
    return count;
}

但没有想到如何能不让程序死循环--让数组大小-numsSize也 - 1 !!!

003_977_有序数组的平方

不加排序情况下思考的代码

cpp 复制代码
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
    for(int i = 0;i < numsSize;i++)
    {
        nums[i] = nums[i] * nums[i];
    }
    return nums;
}
问题 1:直接修改原数组,不符合 "返回新数组" 的语义

题目要求返回 "新数组",但你直接在传入的nums数组上原地修改,相当于 "破坏了原数组的数据",这是 C 语言编程中非常不规范的做法(调用方可能还需要使用原数组的原始值)。

问题 2:未处理 returnSize 参数

题目中给出的 int* returnSize 是要求你通过这个指针,把新数组的长度返回给调用方(这是这类接口的标准设计),你的代码完全没给它赋值,调用方拿到的会是随机值,无法正确遍历返回的数组。

C语言创建新数组

cpp 复制代码
//动态分配内存,创建新数组(避免修改原数组)
//向操作系统申请一块能存放 numsSize 个int元素的连续内存,把这块内存的起始地址存到 newNums 指针里 //相当于 "创建了一个长度为 numsSize 的空 int 数组,newNums 就是这个数组的名字"。

int* newNums = (int*)malloc(numsSize * sizeof(int));
if (newNums == NULL) {  // 健壮性:检查内存分配是否成功
   return NULL;
}

静态数组

cpp 复制代码
    // 1. 定义时直接初始化(长度可省略,编译器自动计算)
    int nums[] = {1, 2, 3, 4, 5};  // 长度=5,下标0~4
    // 2. 定义时指定长度+初始化(未赋值的元素默认补0)
    int arr[6] = {10, 20};         // arr[0]=10, arr[1]=20, arr[2]~arr[5]=0
    // 3. 字符数组(字符串)
    char str[] = "hello";          // 自动补'\0',长度=6(h e l l o \0)
    
    // 遍历数组
    for (int i = 0; i < 5; i++) {
        printf("nums[%d] = %d\n", i, nums[i]);
    }

变长数组

int arr[n]; // 变长数组,长度由用户输入决定

动态数组

语法数据类型* 数组名 = (数据类型*)malloc(长度 * sizeof(数据类型));

(长度可以是变量,内存分配在堆上,用完必须free

006_203_移除链表元素

原版

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) {
    ListNode *p = head->next;
    while(p != NULL)
    {
        if(p->val == val)
        {
            q = p->next;
            p->next = q->next;
        }
        p = p->next;
    }
    return head;
}

一、错误原因拆解

在 C 语言中,自定义结构体的规则是:

  • 直接定义struct ListNode { ... };后,这个类型的完整名称是struct ListNode,而非ListNode
  • C++ 中可以直接用ListNode,但 C 语言必须加struct关键字,或通过typedef简化。

你的代码第 9 行写了ListNode *p = head->next;,编译器找不到名为ListNode的类型,因此报错 "unknown type name 'ListNode'"。

二、两种修复方案(任选其一)

方案 1:直接加struct关键字(最简单,无需修改结构体定义)

在使用ListNode的地方,都加上struct

方案 2:用typedef给结构体起别名(更简洁,推荐)

提前给struct ListNode定义别名ListNode,后续可直接使用:

007_707_设计链表

cpp 复制代码
typedef struct {
    int val;
    MyLinkedList* next;
} MyLinkedList;

一、错误原因:类型引用顺序问题

  • 编译器处理顺序是「先解析结构体内部内容,再给匿名结构体起别名MyLinkedList」;
  • 当解析到MyLinkedList* next时,MyLinkedList这个别名还没生效,因此会报「unknown type name 'MyLinkedList'」错误。

简单说:"你想用的别名,在定义它之前就被用到了",这是 C 语言结构体自引用的典型坑。

二、正确的两种写法(任选其一)

方案 1:先命名结构体,再 typedef(最清晰,推荐)

先给结构体起一个 "临时名"(比如Node),内部用struct Node引用,最后 typedef 为MyLinkedList

cpp 复制代码
// 第一步:定义带名结构体,内部用struct Node自引用
struct Node {
    int val;
    struct Node* next;  // ✅ 此时struct Node已定义,可正常引用
};
// 第二步:给struct Node起别名MyLinkedList
typedef struct Node MyLinkedList;

方案 2:typedef 和结构体命名合并(更简洁)

把结构体命名和 typedef 写在一起,内部用struct MyLinkedList引用(注意:这里的MyLinkedList是结构体名,不是别名):

cpp 复制代码
// 核心:结构体名MyLinkedList和别名MyLinkedList同名(合法且常用)
typedef struct MyLinkedList {
    int val;
    struct MyLinkedList* next;  // ✅ 先有struct MyLinkedList定义,再引用
} MyLinkedList;

三、为什么这两种写法能生效?

  • 方案 1:struct Node是完整的类型名,在结构体内部引用时已经存在,编译器能识别;
  • 方案 2:struct MyLinkedList是结构体的 "正式名称",内部引用时这个名称已经被声明,后续 typedef 只是给它起了同名别名,逻辑上无冲突。
相关推荐
小白探索世界欧耶!~1 天前
用iframe实现单个系统页面在多个系统中复用
开发语言·前端·javascript·vue.js·经验分享·笔记·iframe
551只玄猫1 天前
新编大学德语1第三版笔记 第3课Studentenleben
笔记·德语·外语·德语a1·德语笔记·自学德语·新编大学德语
老朋友此林1 天前
React Hook原理速通笔记1(useEffect 原理、使用踩坑、渲染周期、依赖项)
javascript·笔记·react.js
Chris_12191 天前
Halcon学习笔记-Day5
人工智能·笔记·python·学习·机器学习·halcon
日更嵌入式的打工仔1 天前
Ehercat代码解析中文摘录<7>
笔记·ethercat
悠哉悠哉愿意1 天前
【嵌入式学习笔记】AD/DA
笔记·单片机·嵌入式硬件·学习
半夏知半秋1 天前
rust学习-循环
开发语言·笔记·后端·学习·rust
阿豪只会阿巴1 天前
【多喝热水系列】从零开始的ROS2之旅——Day5
c++·笔记·python·ubuntu·ros2
WarPigs1 天前
数据库笔记
数据库·笔记