038.计导期末复习

计算机导论复习(C语言版)

目录

C语言语法基础

Hello World

#include<stdio.h>
int main(void){
    printf("Hello,World!");
    //return 0;  // C99之后main函数默认返回0
}

语法要点:

  • # - 预处理指令(文本替换)
  • include - 隐式的复制粘贴,将头文件内容包含进来
  • stdio.h - 标准输入输出头文件(Ctrl+左键可查看)
  • int main(void) - C语言标准规定main函数必须返回int类型
  • printf - 格式化输出函数,字符串由""括起来
  • ; - 语句结束标志(预处理指令和语法块{}除外)
  • return 0; - C99之后可省略,默认返回0

基础数据类型

整型

类型 位数 范围
char 8位 [-128, 127]
short 16位 [-32768, 32767]
int 32位 [-2³¹, 2³¹-1]
long 32/64位 平台相关
long long 64位 [-2⁶³, 2⁶³-1]

浮点型

类型 精度 有效位数
float 单精度 7~8位
double 双精度 14~15位
long double 扩展精度 更高精度

字符型

  • char - 存储ASCII码值[-128, 127]
  • char[] - 字符串类型

变量声明与初始化

// 声明需指定类型,使用时不需指定类型
int a = 1, b;
b = 2;
a = a * (b + 1);

// 字符运算
char CH = 'B';
char ch = CH - 'A' + 'a';  // ch = 'b'
char c = 'C';
int index = c - 'A';       // index = 2

// 类型转换与精度
// int与int运算只能得到int
int result = 121 / 10;      // result = 12
double result2 = 121 / 1.0 / 10;  // result2 = 12.1

// 低精度与高精度运算时:低精度先转为高精度,再运算
// int + long long → long long
// long long + double → double

表达式

表达式由一个或多个数据或常量组成,一定返回一个值。

// 表达式示例
1
a
11654 + 10151
a * 15161
a + b

// 表达式的值可以被接收
int res = a + b;
printf("res = %d", a + b);

运算符

算术运算符

+    -    *    /    %    // 加减乘除取模
+=   -=   *=   /=   %=   // 复合赋值

自增自减

a++     // 先调用,再自增(后缀)
++a     // 先自增,再调用(前缀)
a--     // 先调用,再自减
--a     // 先自减,再调用

位运算符

a >> 1      // 二进制右移一位,相当于 a/2
a >>= 1     // 等价于 a /= 2
a << 1      // 二进制左移一位,相当于 a*2
a <<= 1     // 等价于 a *= 2

// 其他位运算
&    // 按位与
|    // 按位或
^    // 按位异或
~    // 按位取反

占位符

类型 占位符 说明
int %i, %d 十进制整数
short %hi, %hd 短整型
long %ld 长整型
long long %lld 长长整型
float %f 单精度浮点
double %lf 双精度浮点
long double %Lf 扩展精度浮点
char %c 单个字符
char[] %s 字符串
- %o 八进制
- %x 十六进制

格式化输入输出

基本输入输出

// 读入两个整数,输出和
int a, b;
scanf("%d%d", &a, &b);  // & 取地址符
printf("%d", a + b);

// 输入2026-1-8,输出2026.1.8
int year, month, day;
scanf("%d-%d-%d", &year, &month, &day);
printf("%d.%d.%d", year, month, day);

位宽控制

printf("%5d", 1);    // "    1"
printf("%5d", 12);   // "   12"
// 宽度不足5时用空格补全

printf("%05d", 1);   // "00001"
printf("%05d", 12);  // "00012"
// 宽度不足5时用0补全

浮点数格式

double pi = 3.1415926;
printf("%.3lf", pi);     // "3.142" 保留三位小数
printf("%06.3lf", pi);   // "03.142" 总宽度6,保留3位小数

高级格式控制

int num = 123;
printf("%+d", num);     // "+123" 显示正负号

printf("%e", 1234.56);  // "1.234560e+03" 科学计数法

printf("%g", 1234.56);  // "1234.56" 自动选择%f或%e

关系表达式

  • 0 表示
  • 非0 表示
int a = (1 != 2);  // a = 1 (真)
a = (1 == 2);      // a = 0 (假)

// 关系运算符
==    // 等于
!=    // 不等于
<     // 小于
>     // 大于
<=    // 小于等于
>=    // 大于等于

// 逻辑运算符
!     // 非(取反)
&&    // 与(两边同为真才为真)
||    // 或(两边同为假才为假)

分支语句

if-else结构

if (condition1) {
    // 条件1为真时执行
} 
else if (condition2) {
    // 条件2为真时执行
} 
else {
    // 以上条件都不满足时执行
}

三目运算符

int max = (a > b) ? a : b;  // 等价于 if(a>b) max=a; else max=b;

循环语句

while循环

int i = 10;
while (i--) {
    printf("%d ", i);
}
//打印9~0

for循环

for (int i = 0; i < 10; i++) {
    printf("%d ", i);
}

循环控制

for (int i = 0; i < 10; i++) {
    if (i == 5) 
        continue;  // 跳过本次,循环剩余部分
    if (i == 8) 
        break;     // 终止本层循环,只能break一层
    printf("%d ", i);
}

数组

一维数组

// 声明与初始化
int arr1[5];                    // 未初始化
int arr2[5] = {1, 2, 3};        // 部分初始化,其余为0
int arr3[] = {1, 2, 3, 4, 5};   // 自动推断大小
int arr4[5] = {0};              // 全部初始化为0

// 访问元素
arr1[0] = 10;      // 第一个元素
int x = arr2[2];   // 获取第三个元素

//数组名 会隐式转换为指针 指向首地址(0下标元素)
int a = arr1[1];
int b = *(arr+1);
//等价

// 数组作为函数参数(传递的是指针)
void printArray(int arr[], int size) {
    for(int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

二维数组

int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 访问元素
int value = matrix[1][2];  // value = 7

字符串

字符串声明

#include <string.h>  // 字符串操作函数头文件

char str1[] = "Hello";           // 自动添加'\0'
char str2[10] = "World";
char str3[] = {'H', 'i', '\0'};  // 手动添加结束符

常用字符串函数

char src[] = "Hello";
char dest[20];

// 字符串复制
strcpy(dest, src);               // dest = "Hello"

// 字符串连接
strcat(dest, " World");          // dest = "Hello World"

// 获取字符串长度
int len = strlen(src);           // len = 5

//读行
char buff[90];
fgets(buff,strlen(buff),stdin);//保留换行符

//去掉'\n'
while(buff[strlen(buff)-1]=='\n'){
    buff[strlen(buff)-1]='\0';
}

// 字符串比较
int cmp = strcmp("abc", "abd");  // cmp < 0 (abc < abd)
int cmp2 = strcmp("abc", "abc"); // cmp2 = 0 (相等)

结构体

结构体定义与使用

// 定义结构体类型
struct Student {
    int id;
    char name[20];
    float score;
};

// 声明结构体变量
struct Student stu1;
struct Student stu2 = {1001, "Alan", 90.5};

// 访问成员
stu1.id = 1002;
strcpy(stu1.name, "DeathSea");
stu1.score = 88.5;

// 结构体指针
struct Student *pStu = &stu1;
pStu->score = 95.0;  // 等价于 (*pStu).score

// typedef简化
typedef struct {
    int x;
    int y;
} Point;

Point p1 = {0, 0};
Point *pPtr = &p1;
pPtr->x = 10;

结构体数组

struct Student class[50];
class[0].id = 1001;
strcpy(class[0].name, "Alice");
class[0].score = 95.5;

函数

函数声明与定义

// 函数声明(原型)
int add(int a, int b);

// 函数定义
int add(int a, int b) {
    return a + b;
}

// 调用函数
int result = add(3, 4);  // result = 7

递归函数

// 阶乘函数
int factorial(int n) {
    if (n <= 1) 
        return 1;
    return n * factorial(n - 1);
}

// 斐波那契数列
int fibonacci(int n) {
    if (n <= 1) 
        return n;
    return fibonacci(n-1) + fibonacci(n-2);
}

math

#include<math.h>
//开方
int a=10;
double b=sqrt(a);

//绝对值
abs(-151);

//次方
pow(2,10);
//2的10次方1<<10

指针

基本指针概念

int a = 10;
int *p = &a;        // p指向a

printf("%d\n", a);   // 直接访问:10
printf("%d\n", *p);  // 间接访问:10(解引用)

// 修改值
*p = 20;            // 相当于 a = 20
printf("%d\n", a);   // 输出:20

指针与数组

int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;      // ptr指向数组首元素

printf("%d\n", *ptr);      // 1
printf("%d\n", *(ptr+1));  // 2
printf("%d\n", ptr[1]);    // 2(等价于*(ptr+1))

// 指针运算
ptr++;  // 指向下一个元素
// arr++; // 错误!数组名是常量指针

多重指针

int b = 10;
int *p1 = &b;
int **p2 = &p1;     // 指向指针的指针

printf("%d\n", b);     // 10
printf("%d\n", *p1);   // 10
printf("%d\n", **p2);  // 10

指针作为函数参数

// 交换两个整数的值
void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

// 调用
int a = 5, b = 10;
swap(&a, &b);  // a=10, b=5

// 交换两个指针
void swapPointer(int **x, int **y) {
    int *temp = *x;
    *x = *y;
    *y = temp;
}

动态内存分配

#include <stdlib.h>  // malloc, free, realloc

// 分配内存
int *arr = (int*)malloc(10 * sizeof(int));

int *arr = (int*)calloc(10 ,sizeof(int)); // 初始化为0

// 使用内存
for (int i = 0; i < 10; i++) {
    arr[i] = i * 2;
    // *(arr+i) = i*2
}

// 重新调整大小
arr = (int*)realloc(arr, 20 * sizeof(int));
arr = (int*)realloc(arr, sizeof(int[20]));

// 释放内存
free(arr);
arr = NULL;

// 动态分配二维数组
int rows = 3, cols = 4;
int **matrix = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
    matrix[i] = (int*)malloc(cols * sizeof(int));
}

// 释放二维数组
for (int i = 0; i < rows; i++) {
    free(matrix[i]);
}
free(matrix);

部分习题汇总

下面进入正题,编号不分先后,想到什么写什么

主要是一些复用性比较强的经典问题和一些个人认为比较有趣的问题

01 闰年与天数

#include<stdio.h>
int check(int year){
    if(year%100==0){
        return year%400==0;
    }
    return year%4==0;
}
int month_to_day(int year,int month){
    if(month==2){
        return check(year)?29:28;
    }
    if(month==4||month==6||month==9||month==11)return 30;
    // 1 3 5 7 8 10 12
    return 31;
}
int main(void){
    int year,month;
    scanf("%d%d",&year,&month);
    //判断闰年
    if(check(year)){
        printf("YES\n");
    }
    else printf("NO\n");

    //获取对应天数
    int day=month_to_day(year,month);
    printf("%d\n",day);
}

02 快速幂

#include<stdio.h>
long long qpow(long long base,long long e){
    long long ans=1;
    long long b=base;
    while(e){
        if(e&1)ans*=b;
        b*=b;
        e>>=1;
    }
    return ans;
}
long long qpow_mod(long long base,long long e,long long mod){
    long long ans=1;
    long long b=base%mod;
    while(e){
        if(e&1)ans=ans*b%mod;
        b=b*b%mod;
        e>>=1;
    }
    return ans;
}
int main(void){
    long long a,b,p;
    scanf("%d%d%d",&a,&b,&p);
    // a^b
    long long ans1=qpow(a,b);
    // a^b % p
    long long ans2=qpow_mod(a,b,p);
}

03 公约数公倍数

求3个数最大公约数:gcd(a,b,c)=gcd( gcd(a,b) , c)
3个数以上同理

最小公倍数同理

//最大公约数
//递归版本
int gcd1(int a,int b){
    return b==0?a:gcd(b,a%b);
}
//迭代版本
int gcd2(int a,int b){
    int c;
    while(b){
        c=b;
        b=a%b;
        a=c;
    }
    return a;
}

//最小公倍数
int lcm(int a,int b){
    int cd=gcd(a,b);
    return a/cd*b;
}

一个有趣的性质

gcd(a,b,c,d)=gcd(a,b-a,c-a,d-a)

04 素数判断

//掌握朴素判断即可
int isp(int x){
    for(int i=2;i*i<=x;++i){
        if(x%i==0)return 0;
    }
    return 1;
}

筛法

05 排序

void swap(int *a,int *b){
    int t=*a;
    *a=*b;
    *b=t;
}
//选择排序
void sort1(int arr[],int size){
    for(int i=0;i<size-1;++i){
        int min=i;
        for(int j=i+1;j<size;++j){
            if(arr[j]<arr[min]){
                min=j;
            }
        }
        swap(&arr[min],&arr[i]);
    }
}
//冒泡排序
void sort2(int arr[],int size){
    for(int i=0;i<size-1;++i){
        for(int j=0;j<size-1-i;++j){
            if(arr[j+1]<arr[j]){
                swap(&arr[j],&arr[j+1]);
            }
        }
    }
}
//插入排序
void sort3(int arr[],int size){
    for(int i=1;i<size;++i){
        for(int j=i;j>0;--j){
            if(arr[j-1]>arr[j]){
                swap(&arr[j],&arr[j-1]);
            }
            else break;
        }
    }
}

更多关于排序

06 二分查找

#include<stdio.h>
#include<stdlib.h>
//在arr[]中查找target,返回下标
int b_serach(int arr[],int size,int target){
    int left=0,right=size-1,mid;
    while(left<=right){
        mid=(right+left)/2;
        if(arr[mid]==target)return mid;
        else if(arr[mid]>target){
            right=mid-1;
        }
        else left=mid+1;
    }
    return -1;
}
//排序
void sort(int arr[],int size){
    for(int i=0;i<size-1;++i){
        for(int j=0;j<size-1-i;++j){
            if(arr[j+1]<arr[j]){
                int t=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=t;
            }
        }
    }
}
int main(void){
    int n,target;
    scanf("%d",&n);
    int *arr=(int*)calloc(n,sizeof(int));
    for(int i=0;i<n;++i){
        scanf("%d",arr+i);
    }
    sort(arr,n);
    scanf("%d",&target);
    int indx=b_serach(arr,n,target);
    if(indx==-1){
        printf("NOT_FOUND--404!");
    }
    else printf("Found %d",arr[indx]);
}

更多关于二分

07 记忆化递归

//斐波那契数列

//递归 
int f(int x){
    if(x==1||x==2)return 1;
    return f(x-1)+f(x-2);
}

//记忆化递归
int F[101]={-1};
int f(int x){
    if(x==1||x==2)return 1;
    if(F[x]!=-1)return F[x];
    return F[x]=f(x-1)+f(x-2);
}

//迭代版本
int f(int n){
    int a=1,b=1;
    int c;
    for(int i=3;i<=n;++i){
        c=a+b;
        a=b;
        b=c;
    }
    return b;
}

08 回文

//将一个数不断除10,得到位数
int dig(int num){
    int t=0;
    while(num){
        t++;
        num/=10;
    }
    return t;
}

// 获取一个数的第k位(个位是第一位)
// ans = num / 10^(k-1) %10
int getk(int num,int k){
    k--;
    if(dig(num)<k)return -1;
    while(k--){
        num/=10;
    }
    return num%10;
}

//翻转
int get_re(int num){
    int re=0;
    int t=num;
    while(t){
        re=re*10+t%10;
        t/=10;
    }
    return re;
}

//判断是否回文
int is_re(int num){
    int re=get_re(num);
    return num==re;
}

09 完全平方数

#include<math.h>
int is_pingfang(int a){
    int t=sqrt(a);
//sqrt(a)返回浮点数,转整形精度丢失,只有完全平方数可以开出整数
    return t*t==a;
}

//我们也可以自己写一个sqrt()
double my_sqrt(double x){
    double l=0.0,r=x,mid,ans;
    while(r-l>1e-8){
        mid=(l+r)/2;
        if(mid*mid-x>1e-8){
            ans=mid;
            r=mid;
        }
        else l=mid;
    }
    return ans;
}

//类似地,可以写出开多次根
double my_pow(double mid,int k){
    double ans=1;
    while(k--){
        ans*=mid;
    }
    return ans;
}
double sqrt_k(double x,int k){
    double l=0.0,r=x,mid,ans;
    while(r-l>1e-8){
        mid=(l+r)/2;
        if(my_pow(mid,k)-x>1e-8){
            ans=mid;
            r=mid;
        }
        else l=mid;
    }
    return ans;
}

10 进制转换(支持负进制)

为了处理'A'~'F'的数,统一使用字符串

C++版

测试链接1
测试链接2

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//0
char zero[]="0"; 
//整形转字符
char dtoc(int d){
    if(d>9)return 'A'+d-10;
    return '0'+d;
}
//字符转整形
int ctod(char c){
    if(c>'a')return c-'a'+10;
    if(c>='A')return c-'A'+10;
    return c-'0';
}
//正进制字符串转十进制
long long pos_to_ten(const char*num,int x){
    long long t=0;
    while(*num){
        t=t*x+ctod(*num);
        num++;
    }
    return t;
}
//负进制字符串转十进制
long long neg_to_ten(const char*num,int x){
    long long t=0;
    long long b=1;
    int len=strlen(num);
    for(int i=len-1;i>=0;i--){
        t+=ctod(num[i])*b;
        b*=x;
    }
    return t;
}
// 十进制转任意进制
char*ten_to_y(long long t,int y){
    if(t==0)return zero;
    //反向存储
    char temp[65];
    int index=0;
    while(t!=0){
        int d=t%y;
        t/=y;
        if(d<0){
            d+=-y;
            t++;
        }
        temp[index++]=dtoc(d);
    }
    temp[index]='\0';
    //反转
    char*ans=(char*)calloc(index+1,sizeof(char));
    for(int i=0;i<index;i++){
        ans[i]=temp[index-1-i];
    }
    ans[index]='\0';
    return ans;
}
// 任意进制转换
char*x_to_y(const char*num,int x,int y){
    if(strcmp(num,"0")==0)return zero;
    long long t=(x<0)?neg_to_ten(num,x):pos_to_ten(num,x);
    return ten_to_y(t,y);
}

int main(void){
    //测试1
    int x,y;
    char num[65];
    scanf("%d%s%d",&x,num,&y);
    printf("%s",x_to_y(num,x,y));

    //测试2
    long long t;
    int y;
    scanf("%lld %d",&t,&y);
    printf("%lld=%s(base%d)",t,ten_to_y(t,y),y);
}

11 质因子分解

//返回质因子个数,ans[]接收质因子
int get_func(int num,int ans[]){
    int p=-1;
    for(int i=2;i*i<=num;++i){
        if(num%i==0){
            ans[++p]=i;
            while(num%i==0)num/=i;
        }
    }
    if(num>1)ans[++p]=num;
    return p;
}

12蛇形矩阵

//从左上到右下,交替沿着副对角线向数组中填充元素,特判边界
#include<stdio.h>
int main(){
  int n;
  scanf("%d",&n);
  int M[n][n];
  int x=0,y=0;
  int t=1;
  int flag=0;
  while(t<=n*n){
        M[x][y]=t++;
    if(flag==0){
        if(y==0||x==n-1){
            if(x==n-1)y++;
            else x++;
            flag=1;
        }
        else x++,y--;
    }
    else {
        if(x==0||y==n-1){
            if(y==n-1)x++;
            else y++;
            flag=0;
        }
        else x--,y++;
    }
  }
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
        printf("%d",M[i][j]);
        if(j==n-1)printf("\n");
        else printf(" ");
    }
  }
}

13字符串匹配

朴素匹配,在母串中枚举起点

//数组版, 母串s 中查找 子串t
// 找到返回 t 在 s 中第一次出现的位置
// 未找到 返回 -1
int find_t_in_s(char s[],char t[]){
    int ls=strlen(s);
    int lt=strlen(t);
    if(lt==0)return 0;
    int start=0;
    int i,j;
    while(start+lt<=ls){
        i=start;
        j=0;
        while(i<ls&&j<lt&&s[i]==t[j]){
            j++;
            i++;
        }
        if(j==lt)return start;
        start++;
    }
    return -1;
}
// 指针版, 母串s 中查找 子串t
// 找到返回 t 在 s 中第一次出现的位置的指针
// 未找到 返回 NULL
char* find_t_in_s(char *s,char *t){
    if(*t=='\0')return s;
    char*p1=s;
    char *p2,*p3;
    while(*p1!='\0'){
        p2=t;
        p3=p1;
        while(*p2!='\0'&&*p3!='\0'&&*p2==*p3){
            p2++;
            p3++;
        }
        if(*p2=='\0')return p1;
        p1++;
    }
    return NULL;
}

14删除字符

//删去 字符串str 中所有的 字符ch
void delet_char(char *str,char ch){
    char *p1=str;
    char *p2=str;
    while(*p1!='\0'){
        if(*p1!=ch){
            *p2=*p1;
            p2++;
        }
        p1++;
    }
    p2='\0';
} 

15结构体排序

核心是根据题意设计cmp函数

typedef struct{
    char * name;
    int chinese;
    int english;
    int math;
}student;

int sum(student*st){
    return st->chinese + st->english + st->math;
}

//定义优先级:
//     分数大靠前,依次比较总分,数学,英语
//     名字字典序小的靠前
//返回 + 优先级 a > b
//返回 - 优先级 a < b
//返回 0  a与b完全相同
int cmp(student*a,student*b){
    int A=sum(a),B=sum(b);
    if(A!=B)return A - B;
    if(a->math != b->math)return a->math - b->math;
    if(a->english != b->english)return a->english - b->english;
    return -strcmp(a->name,b->name);
    //strcmp(char[] a,char[] b)
    //a="abbbb" b="abbcc"  ->   -
    //a="abbbb" b="abbbb"  ->   0
    //a="abbbb" b="aaaaa"  ->   +
}
void swap(student*a,student*b){
    student t=*a;
    *a=*b;
    *b=t;
}
void sort(student arr[],int size){
    for(int i=0;i<size-1;++i){
        for(int j=0;j<size-1-i;++j){
            if(cmp(&arr[j+1],&arr[j])>0){
                swap(&arr[j+1],&arr[j]);
            }
        }
    }
}

16 缓存读入+内存动态分配+指针数组

大致题意:
卓越徽章共5种,分别用英文大写字母A到E表示,普通徽章共21种,分别用英文大写字母F到Z表示。  
到年底,平台会根据同学们解锁徽章的情况来评选年度之星。年度之星评选很简单就是根据规则排名前10的同学就是年度之星。  
现请你写一段程序根据相应规则来为所有使用该平台的学生排序。
putin:
第一行为一个整数n(0<n<6000),代表共n个同学使用了该平台;后面是n行,每行均为一个只包含英文大写字母的字符串(字符串长度小于10000),代表一个同学解锁的全部徽章。
比较规则为先比较卓越徽章。卓越徽章的比较规则为直接比较字符串的大小。由于整个字符串为一个同学解锁的全部徽章,所以你要先把卓越徽章从整个字符串中依次取出来(注意不能改变原次序且测试用例保证每个同学的卓越徽章不超过10个)。  
如果两个同学的卓越徽章一样,则再比较普通徽章。此时的比较规则也为直接比较字符串的大小(注意,此次比较为输入的原字符串的比较,即卓越徽章也在其中)。徽章字符串的比较规则与平时字符串比较规则一致且比较结果大的排名靠前。

putout:
共n行,按排名由高到低每一行一个同学所获得的全部徽章,即输入的原字符串。

此题的内存限制是2MB , 比较苛刻

我们需要缓存读入,而不能直接开10000的字符数组

同时一个malloc对应一个free

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *get_exe(char*s){
    char * t=(char*)malloc(sizeof(char)*11);
    int p=0;
    while(*s!='\0'){
        if(*s>='A'&&*s<='E'){
            t[p++]=*s;
        }
        s++;
    }
    t[p]='\0';
    return t;
}
int cmp(char *a,char *b){
    char *A=get_exe(a);
    char *B=get_exe(b);
    int f=strcmp(A,B);
    free(A);
    free(B);
    if(f!=0)return f;
    return strcmp(a,b);
}
void swap(char **a,char**b){
    char * t=*b;
    *b=*a;
    *a=t;
}
void sort(char*s[],int siz){
    for(int i=0;i<siz-1;++i){
        for(int j=0;j<siz-1-i;++j){
            if(cmp(s[j],s[j+1])<0){
                swap(&s[j],&s[j+1]);
            }
        }
    }
}
int main(void){
    int n;
    scanf("%d",&n);
    char* s[n];
    char buff[10001];
    for(int i=0;i<n;++i){
        scanf("%s",buff);
        int ls=strlen(buff);
        s[i]=(char*)malloc(sizeof(char)*(ls+1));
        strcpy(s[i],buff);
    }
    sort(s,n);
    for(int i=0;i<n;++i){
        printf("%s\n",s[i]);
        free(s[i]);
    }
}

17 分数运算

typedef struct{
    int mo;//分子
    int de;//分母
}f;
int gcd(int a,int b){
    if(a<0)a=-a;
    if(b<0)b=-b;
    int t;
    while(b){
        t=b;
        b=a%b;
        a=t;
    }
    return a;
}
//化简
void simp(f* x){
    if(x->de<0){
        x->de=-x->de;
        x->mo=-x->mo;
    }
    int cd=gcd(x->de,x->mo);
    x->de/=cd;
    x->mo/=cd;
}
f add(f*a,f*b){
    f ans;
    ans.mo=a->de*b->mo+a->mo*b->de;
    ans.de=a->de*b->de;
    simp(&ans);
    return ans;
}
f sub(f*a,f*b){
    f ans;
    ans.mo=a->mo*b->de-a->de*b->mo;
    ans.de=a->de*b->de;
    simp(&ans);
    return ans;
}
f mul(f*a,f*b){
    f ans;
    ans.mo=a->mo*b->mo;
    ans.de=a->de*b->de;
    simp(&ans);
    return ans;
}
f div(f*a,f*b){
    f ans;
    ans.mo=a->mo*b->de;
    ans.de=a->de*b->mo;
    simp(&ans);
    return ans;
}

18 循环数组

一个数组num ,长度为size

int num[],size;
//下标 i
//循环右移  i = (i + 1 + size)% size 
//这样在 size-1 位置右移就到了 0 位置

//循环左移  i = (i - 1 + size)% size
//这样在 0 位置左移就到了 size-1 位置
//如果最多循环一次

//考虑把两个相同数组拼起来
int*arr=(int*)calloc(size*2,sizeof(int));
for(int i=0;i<size;++i){
    arr[i]=arr[i+size]=num[i];
}

//比如 num[]={1,3,5,4,0}
//得到 arr[]={1,3,5,4,0,1,3,5,4,0}

结语

祝考试顺利 !

posted @ 2026-01-08 17:55  射杀百头  阅读(40)  评论(0)    收藏  举报