-1.愚蠢的行为

0.当你没有输出时,崩溃时,不妨检查下你的scanf有没有加取地址符&

1.for 循环中定义i和j弄混,导致runtime error

1
2
3
4
5
6
7
8
9

for(int i=0;i<len_s;i++){
        for(int j=0;i<len_t;j++){//这里j变成了i
            if(s[i]==t[j]){
                s[i]='0';
                t[j]='0';
            }
        }
    }
2.函数声明变量是中间用逗号, for循环中用分号;
3. 数组类型定义不明

char 与int 混淆,而且还能跑,又找不到问题!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
    int a[201];//这里应该用char,但是用了int也能跑,而且找不到问题
    int count = 0, in = 0, temp = 0, d = 0;
    fgets(a,sizeof(a),stdin);
    int len = strlen(a);
    for (int i = 0; i < len; i++) {
        if (!judge(a[i])) {
            if (!in) {
                in = 1;
                count++;
            }
        }
        else {
            in = 0;
        }
    }
    printf("单词数量: %d", count);
}

4.函数定义

为什么定义了个函数在matrix一大串画线报错呢
哦原来是你个大聪明没定义函数类型

5.代码有问题不要再复用

不要光复用代码,要改就删掉!!重写不用多久
debug更浪费时间

6.char指针指针和地址要分清

指针if(*s1==*s2)
地址自增++s1 s1++
地址加1(不会改变源地址的值)s1+1 递归应该使用这个而非自增,会改变全局的值

7.单引号和双引号括起来是有区别的,一个是字符,另一个是字符串

在单个使用时,比如比较,我们要用单引号,如 '\n' '\t' 'z' 用双引号实际是会报错的

8.指针最好不要乱动,尤其是需要返回的指针,找个替身好吗?

0.审题

不要有坏习惯!

做一切题目先审好题

不要按感觉来

看好样例

把样例理解并考虑周全

(好言难劝该死的鬼)

1.for循环中

    for(int i=0;i<k;i++)

    for(int i=k;i>0;i–)

    注意后者是 i– 否则会越界

2.输入

1.scanf

注意加&,除了%s
    只有string%s在前面不需要加&,别的都需要!

  • 可以读取整行中的空格 %[^\n] %前面加空格可以读取上一行的空格,也可在在结束丢弃缓冲区的换行字符"%[^\n]%*c",其中%*c是读取并丢弃一个字符。

注意数据类型!!###

%lld %d %f %lf

3.分号与逗号

for 循环中用分号
其他一般用逗号
结尾记得带分号

4.数组移动

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

while (*x != 1) {
     arr[*i] = *x; // Store current value of x in arr
     (*i)++;       // Increment index

     if (*x % 2 == 1) {
         *x = *x * 3 + 1;
     }
     else {
         *x /= 2;
     }
     printf("%d\n", *x); // Print the next value in the sequence
 }


 // Store the last value (1) in the sequence
 arr[*i] = *x;
 (*i)++;

代码主要看后面
结尾记得把末尾的也储存进去

用while或者do while 一定要记得头和尾要不要

5.输出

输出数据类型

%lld %d %f %lf

还有保留几位小数  %.2f

当然还有几进制

  • %o:八进制表示。

  • %x:十六进制小写表示。

  • %X:十六进制大写表示。

  • # 修饰符可以用于显示八进制 0 前缀和十六进制 0x0X 前缀。

6.数组定义

C语言C99前不支持定义可变数组

我们可动态分配以方便在落后的ide上调试

1
2
3
4
5
6
int *a=(int *)malloc(n*sizeof(int));//malloc不初始化数组

int *a=(int *)calloc(n,sizeof(int));//calloc初始化数组

double *a=(double *)calloc(n,sizeof(double));

7.执行后的函数

不少函数尤其是以指针为传入函数的,执行函数后会对值直接进行修改并且也返回原来的值。
例如 strlwr(*p);事实上执行后就会对原来的值发生修改,返回的值应该都是小写

1
strcpy(str1,"saBaaG"); strcpy(str2,strlwr(str1)); printf("%s\n",str1); printf("%s\n",str2);

8.结构体

1.结构体指向写法

两种 . 或者-> 其实->是语法糖
是结构体就用点,是指针的话可以用语法糖(这时不用解引用)

  • (*pointer).member 的写法
    当你有一个指针,比如 book1,如果你想访问它所指向的结构体的成员 Price,标准写法是:
    (*book1).Price

  • -> 语法糖
    为了简化写法,C 提供了 -> 运算符,用于指针访问结构体成员:
    book1->Price // 等价于 (*book1).Price

2.结构体的排序

我们使用 <stdlib.h> 中的qsort函数
先写compare函数,需要注意结构体定义应该在更前面,放在全局而非主函数中
将传入的 void指针转化为结构体,弄1,2两个值出来

1
2
3
4
5
6
7
8
9
10
11
int compare(const void* a, const void* b) {
struct BOOK* book1 = (struct BOOK*)a;
struct BOOK* book2 = (struct BOOK*)b;
if (book1->Price > book2->Price) {
return 1;
}
else if (book1->Price < book2->Price) {
return -1;
}
return 0;
}

从小到大就正常,从大到小就反过来。
当然简化版更爽(但相减有个问题就是可能会数值溢出)

1
2
3
4
5
int compare(const void* a, const void* b) {
  struct BOOK* book1 = (struct BOOK*)a;
    struct BOOK* book2 = (struct BOOK*)b;
    return book1->Price - book2->Price;
}

3.语法细节

结构体后面要加分号

1
2
3
4
struct Person{
    char name[10];
    int age;
};

4.输入

scanf传入的应该是地址
%s是可以的,传入的是数组地址

1
2
3
scanf("%d", &pup[0].age);  
scanf("%s", pup[0].name);
scanf("%d", &(p->sex));

5.概念

1
2
3
4
5
typedef struct ST{
long a;
int b;
char c[2];} NEW;
NEW new={1,2,'sd'};

struct ST=NEW结构体类型
ST结构体的标签
new结构体标签

9.多文件

1..h.c都要根据main来写

  • 数据体需要看main中的输入类型,别人是float你就不能写double
  • 看好main函数中传递的值,人家是整个结构体还是指针,这会影响你写的函数的类型
  • 头文件会需要定义一些东西
    结构体重命名typedef struct Student Student;
    一些在main中出现但是未定义的宏SIZE MAX_XX

2..h.c之间的关系

  • .c需要包含头文件
    #include<student.h>
  • 头文件中需要定义函数,然后.c再描述函数

10.qsort函数

排序的大招()
函数原型

1
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

int(*fun)(参数)是函数的指针,返回整型值
使用:

1.我们先写好compare函数,需要注意类型转化

示例:

  • 整数 return (*(int*)a - *(int*)b); // 从小到大排序
  • 结构体
    BOOK* book1
    1
    2
        struct BOOK* book2 = (struct BOOK*)b;
        return book1->Price - book2->Price;
2.对于num size,我们注意类型是size_t

万能的:

1
2
sizeof(array) / sizeof(array[0])
sizeof(int)

很多时候num是已经定下的,我们会用显示转换

1
qsort(arr, (size_t)n, sizeof(int), compare);

11.链表

1.删除链表不能乱删除

先跳线,在炸掉桥,再把现在的由之前的来定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void deleteDuplicates(struct Node* head){

    int* a=(int*)calloc(Max,sizeof(int));

    Node* pre=NULL;

    Node* curr=head;

    while(curr!=NULL){

        if(a[curr->data]==0){

            a[curr->data]=1;

            pre=curr;

            curr=curr->next;

        }

        else if(a[curr->data]==1){

            pre->next=curr->next;  

            free(curr);

            curr=pre->next;            

        }

    }

    free(a);

}

12.常用的库

1. <stdio.h>(标准输入输出库)

用于处理输入输出操作。

常用函数:

  • printf(): 格式化输出到标准输出(屏幕)。

    • 用途:打印各种格式的数据,如整数、浮点数、字符串等。

    • 示例:

      1
      printf("Hello, World! %d\n", 10);
  • scanf(): 从标准输入(键盘)读取数据。

    • 用途:读取用户输入的数据,可以按照指定格式读取。

    • 示例:

      1
      2
      int a;
      scanf("%d", &a);
  • getchar(): 从标准输入读取一个字符。

    • 用途:逐个字符地读取输入。

    • 示例:

      1
      char c = getchar();
  • putchar(): 输出一个字符到标准输出。

    • 用途:打印单个字符。

    • 示例:

      1
      putchar('A');
  • fopen(), fclose(): 打开/关闭文件。

    • 用途:文件的读取、写入操作。

    • 示例:

      1
      2
      FILE *file = fopen("file.txt", "r");
      fclose(file);
  • fscanf(), fprintf(): 从文件读取数据,向文件写入数据。

    • 用途:文件输入输出。

    • 示例:

      1
      2
      fscanf(file, "%d", &a);
      fprintf(file, "%d", a);

2. <stdlib.h>(标准库)

包含动态内存管理、程序控制、转换等功能。

常用函数:

  • malloc(): 动态分配内存。

    • 用途:在堆上分配一块指定大小的内存。

    • 示例:

      1
      int *arr = (int*)malloc(10 * sizeof(int));
  • free(): 释放动态分配的内存。

    • 用途:释放之前通过 malloccallocrealloc 分配的内存。

    • 示例:

      1
      free(arr);
  • calloc(): 分配并初始化内存。

    • 用途:分配内存并将其初始化为零。

    • 示例:

      1
      int *arr = (int*)calloc(10, sizeof(int));
  • realloc(): 重新分配内存。

    • 用途:调整已分配内存的大小。

    • 示例:

      1
      arr = (int*)realloc(arr, 20 * sizeof(int));
  • exit(): 退出程序。

    • 用途:终止程序,并可返回指定的退出状态。

    • 示例:

      1
      exit(0);
  • rand(): 生成随机数。

    • 用途:生成随机数,通常需要 srand() 初始化随机数种子。

    • 示例:

      1
      int r = rand();
  • atoi(), atof(), atol(): 字符串转换为整数、浮点数、长整型等。

    • 用途:将字符串转换为整数、浮点数或长整数。

    • 示例:

      1
      int num = atoi("123");

3. <string.h>(字符串处理库)

提供字符串操作相关的函数。

常用函数:

  • strlen(): 计算字符串长度(不包括结尾的 '\0')。

    • 用途:获取字符串的长度。

    • 示例:

      1
      int len = strlen("Hello");
  • strcpy(): 复制字符串。

    • 用途:将一个字符串复制到另一个字符串。

    • 示例:

      1
      2
      char dest[20];
      strcpy(dest, "Hello");
  • strncpy(): 复制指定长度的字符串。

    • 用途:安全地复制指定长度的字符串。

    • 示例:

      1
      strncpy(dest, "Hello", 5);
  • strcmp(): 比较两个字符串。

    • 用途:比较两个字符串的字典顺序。

    • 示例:

      1
      int result = strcmp("apple", "banana");
  • strcat(): 拼接字符串。

    • 用途:将一个字符串追加到另一个字符串末尾。

    • 示例:

      1
      2
      char str1[20] = "Hello, ";
      strcat(str1, "World!");
  • strchr(): 查找字符。

    • 用途:在字符串中查找第一个指定字符。

    • 示例:

      1
      char *ptr = strchr("Hello", 'e');
  • strstr(): 查找子字符串。

    • 用途:在字符串中查找指定的子字符串。

    • 示例:

      1
      char *ptr = strstr("Hello, World!", "World");

4. <math.h>(数学库)

提供数学计算相关的函数。

常用函数:

  • sin(), cos(), tan(): 三角函数。

    • 用途:计算正弦、余弦和正切值。

    • 示例:

      1
      double result = sin(3.14159);  // 计算π的正弦值
  • sqrt(): 计算平方根。

    • 用途:计算一个数的平方根。

    • 示例:

      1
      double result = sqrt(25);  // 计算25的平方根,结果为5
  • pow(): 计算幂。

    • 用途:计算一个数的指定幂。

    • 示例:

      1
      double result = pow(2, 3);  // 计算2的3次方,结果为8
  • log(), log10(): 对数函数。

    • 用途:计算自然对数和以 10 为底的对数。

    • 示例:

      1
      double result = log(100);  // 计算100的自然对数
  • abs(): 计算整数的绝对值。

    • 用途:返回整数的绝对值。

    • 示例:

      1
      int result = abs(-10);  // 计算-10的绝对值,结果为10
  • ceil(), floor(): 取整函数。

    • 用途:ceil()返回大于或等于参数的最小整数,floor()返回小于或等于参数的最大整数。

    • 示例:

      1
      2
      double result1 = ceil(3.14);  // 结果为4
      double result2 = floor(3.14); // 结果为3
  • fmod(): 计算浮点数的余数。

    • 用途:返回两个浮点数相除的余数。

    • 示例:

      1
      double result = fmod(5.5, 2);  // 结果为1.5
  • exp(): 计算自然常数e的幂。

    • 用途:计算e的x次方。

    • 示例:

      1
      double result = exp(1);  // 计算e的1次方,结果为2.71828
  • fabs(): 计算浮点数的绝对值。

    • 用途:返回浮点数的绝对值。

    • 示例:

      1
      double result = fabs(-3.14);  // 结果为3.14

5. <time.h>(时间日期库)

处理日期和时间。

常用函数:

  • time(): 获取当前时间。

    • 用途:获取从1970年1月1日(Unix纪元)以来的秒数。

    • 示例:

      1
      time_t t = time(NULL);
  • localtime(): 将时间转换为本地时间。

    • 用途:将 time_t 类型的时间转换为本地时间的 tm 结构。

    • 示例:

      1
      struct tm *tm_info = localtime(&t);
  • strftime(): 格式化时间。

    • 用途:将 tm 结构的时间格式化为字符串。

    • 示例:

      1
      2
      char buffer[80];
      strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", tm_info);

6. <ctype.h>(字符处理库)

提供字符分类和转换的函数。

常用函数:

  • isdigit(): 判断字符是否为数字。

    • 用途:判断字符是否是数字(0-9)。

    • 示例:

      1
      if (isdigit('9')) { printf("It's a digit!"); }
  • isalpha(): 判断字符是否为字母。

    • 用途:判断字符是否是字母。

    • 示例:

      1
      if (isalpha('A')) { printf("It's a letter!"); }
  • toupper(), tolower(): 字符大小写转换。

    • 用途:将字符转换为大写或小写。

    • 示例:

      1
      2
      char c = 'a';
      char upper = toupper(c);

鸣谢:GPT4o