news 2026/8/31 3:09:41

一些文件操作和数学问题的C库函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一些文件操作和数学问题的C库函数

1.

C 库函数double fmod(double x, double y)返回x除以y的余数。

fmod() 是 C 标准库 <math.h> 中的一个函数,用于计算两个浮点数相除的余数。这个函数返回除法操作的余数,其符号与被除数相同。

声明

下面是 fmod() 函数的声明。

double fmod(double x, double y)

参数

  • x:被除数,一个浮点数。
  • y:除数,一个浮点数。

返回值

  • 返回x除以y的余数,其符号与x相同。
  • 如果y是 0,结果为未定义,可能会产生一个计算错误。

所以求一个double类型数据的小数部分,可以用fmod(double,1.0) !

2.

C 语言对结构体赋值的原生支持,

  • 结构体赋值的本质:当你执行Person temp = arr[start];时,编译器会把arr[start]这个结构体变量的所有成员(name[15]数组、height整数)逐字节复制到temp中;后续的arr[start] = arr[end];arr[end] = temp;也是同理,相当于手动写了 “交换每个成员” 的代码,但编译器帮你简化了。
  • 对比手动交换成员:你手动交换需要写:
    // 手动交换两个Person的所有成员 // 1. 交换name数组 char nameTemp[15]; strcpy(nameTemp, arr[start].name); strcpy(arr[start].name, arr[end].name); strcpy(arr[end].name, nameTemp); // 2. 交换height int heightTemp = arr[start].height; arr[start].height = arr[end].height; arr[end].height = heightTemp;
    而直接赋值的写法是编译器帮你封装了上述逻辑,代码更简洁,且结果完全一致

所以只有结构体成员没有动态分配内存的指针,就可以像交换int类型变量一样交换结构体类型变量的值

3.

以下是几种常用的四舍五入方法:(默认只有1位小数,多位小数时可先*100扩大舍入后再/100.0)

  • **round()函数**:不管有多少位小数,都直接四舍五入为整数,返回浮点数类型。例如,round(2.5)结果为3.0round(2.4)2.0`。
  • printf格式化:使用%.0f输出时,会自动按四舍五入处理。
  • 强制类型转换(取整):使用(int)(x + 0.5)可实现正数的四舍五入到整数。
  • 指定小数位数:若要保留两位小数,可使用round(x * 100) / 100.0

要实现平均数四舍五入返回整数打印:

double average = ((double)total_time) / count; printf("%d %d\n", count, (int)round(average)); }

4.

去掉一个最高分和最低分时,两种思路:

1. 贪心策略求出最高、最低分(无并列),记录下其索引,遍历时跳过该索引位置

2. 用qsort升序排列,遍历索引从1到 len-1位置的元素即可

5.

有一个大小count=5的数组,已经按分数排名1、2、3、4、5排列好,但是要求对分数相同的按排名相同输出,比如输出1、1、3、4、4这种?

思路:

  • 初始化排名变量rank=1,遍历数组从第 2 个元素开始;
  • 对比当前元素与前一个元素的分数:
    • 分数相同 → 当前排名 = 前一个排名,rank不变!
    • // 打印并列排名的思路 ! int rank = 1; printf("%d %s %d %d\n", rank, arr[0].name, arr[0].score, arr[0].count); for (int i = 1; i < count; i++) { if (arr[i].score == arr[i - 1].score) { printf("%d %s %d %d\n", rank, arr[i].name, arr[i].score, arr[i].count); } else { rank = i + 1; printf("%d %s %d %d\n", rank, arr[i].name, arr[i].score, arr[i].count); } }
      分数不同 → 当前排名 = 当前位置(即更新rank=当前索引+1

6.

已经成功把所有不重复的因数存入res数组,现在需要从这个数组中选出 4 个不同的元素求和,核心思路是通过多层循环枚举所有合法的 4 元素组合

假设你的 res 数组长度为 len(且 len >= 4,因为之前已经判断过因数数量≥4),枚举步骤如下: 第一层循环(i):遍历数组第一个元素的下标,范围是 0 到 len-4(因为后面还要留 3 个位置给 j、k、l); 第二层循环(j):遍历第二个元素的下标,范围是 i+1 到 len-3(必须在 i 之后,且留 2 个位置给 k、l); 第三层循环(k):遍历第三个元素的下标,范围是 j+1 到 len-2(必须在 j 之后,且留 1 个位置给 l); 第四层循环(l):遍历第四个元素的下标,范围是 k+1 到 len-1(必须在 k 之后); 对每一组 res[i]、res[j]、res[k]、res[l],计算它们的和,然后判断这个和是否能被原数 N 整除
// 选不同的4个 for (int i = 0; i <= count-4; i++) { for (int j = i+1; j <= count - 3; j++) { for (int k = j+1; k <= count - 2; k++) { for (int l = k+1; l <= count - 1; l++) { int sum = res[i] + res[j] + res[k] + res[l]; if (sum % x == 0) return 1; } } } }

注意题目是若正整数 N 可以整除它的 4 个不同正因数之和

a可以整除b,是b%a==0的意思而不是a%b==0

等价于b可以被a整除,b作被除数,a作除数!

若搞反了整除判断关系,会出现逻辑错误且不好排查!

7.

判断素数的写法,一定要能熟练快速写出:

几个注意点:

1 不是素数,如果x==1直接return 0

2 虽然是偶数,但它是素数(只有1和本身的因数),所以x==2直接return 1

除2以外的偶数都不是素数,直接return 0

从i=3开始遍历每个奇数(i=i+2)直到i<=sqrt(x),如果x能被i整除,不是素数,return 0

若前面都没有return,说明是素数,return 1

int isprime(char* s) { int x; sscanf(s, "%d", &x); if (x == 1) return 0; if (x == 2) return 1; if (x % 2 == 0) return 0; for (int i = 3; i <= sqrt(x); i=i+2) { if (x % i == 0) return 0; } return 1; }

8.

文件操作:

分为文本文件、二进制文件,读/写,截断还是追加

去菜鸟教程截图过来!

另外复习一下fseek、和刷新文件流的用法

通过光标(文件流指针)计算文件长度的方法

常量 描述 SEEK_SET 文件的开头 SEEK_CUR 文件指针的当前位置 SEEK_END 文件的末尾

先fseek(fp, 0, SEEK_END)把光标移动到文件末尾,然后用

int len=ftell(fp)获取当前光标到文件开头的距离,即文件长度

最后建议用fseek(fp, 0, SEEK_SET)把光标移回文件开头方便下一次操作

9.

因式分解用试除法,i从2开始到i=n结束(不要到sqrt(n)就结束),最后可能剩一个大质数,到i=自然会取到这个剩下的大质数!

void main(){ int n; scanf("%d",&n); int i=2; int temp=n; printf("%d=",n); while (i <= temp) { if(temp%i == 0){ printf("%d",i); temp=temp/i; if(temp!=1){ printf("*"); } } else{ i++; } } }

10.

十进制小数转二进制时,用乘2取整法,如:

0.25 → 0.25×2=0.5(取 0) → 0.5(取结果的小数部分,若上一步结果为1.5,也是取0.5)×2=1.0(取 1) → 小数部分为 0,停止 → 顺序取数得 01

11.

对于十六进制,以%X读取或打印,表示是大写字母A-F表示10-15,而%x表示小写字母a-f表示10-15

12.

随机生成不重复的数:

int exsit(int* arr,int x){ for (int i = 0; i < 10; i++) { if(arr[i]==x) return 1; } return 0; } void main(){ srand(time(NULL)); // 需要引入time.h头文件,获取当前系统时间,用于初始化随机数种子 int i=0; int arr[10]={0}; while (i<10) { int temp=rand()%100+1; // rand()生成随机数 if(!exsit(arr,temp)){ arr[i++]=temp; } } for (int j = 0; j < 10; j++) { printf("%d ",arr[j]); } }

13.

复习一下PTA天梯赛第50题,字母(纯小写或纯大写)可以视为数字0-25,对于

字符串aaa可以视为各位数字为0,即000。如果给了一个总数,可以不断除以进制来获取各位数字(相当于字符)

14.

scanf不会跳过,(逗号)!,当输入是逗号时万分注意!

15.

大数加法可以直接反转就输出、不用处理前导零,本质是加法的进位逻辑天然不会产生 “无效的前导零”,而减法的借位逻辑会产生(n1-n2之前,需要先n1-=borrow)

大数加法和减法逻辑类似,可共用一套流程逻辑

除法学内置不断相减,试商法的算法思想,防止填空题!

大数乘法需要注意res[i+j]+=(A[i]-'0'])*(B[j]-'0'),A的个位*B的十位和A的十位*B的个位都是结果的同一位有影响,结果需要累加起来

16.

使用memset快速初始化数组:

void *memset(void *str, int c, size_t n)

参数

  • str-- 指向要填充的内存区域的指针。
  • c-- 要设置的值,通常是一个无符号字符。
  • n-- 要被设置为该值的字节数。

当你申请了一块内存或定义了一个大数组时,可以用它快速将所有位设为 0。

  • 示例memset(arr, 0, sizeof(arr));

17.

计算约数个数,用质因数分解法

把数拆成质数的次方形式,每个次方数 +1,全部乘起来,就是约数总个数

  1. 先质因数分解:90 =2¹ × 3² × 5¹

  2. 每个指数 +1:1+1 = 22+1 = 31+1 = 2

  3. 相乘:2 × 3 × 2 =12

所以90 有 12 个约数

整体思路是因式分解(先找约数2),然后从3开始找奇质数,用数组存不同质因数的出现次数(指数)

#include <stdio.h> #include <stdlib.h> void main(){ int n; scanf("%d",&n); long long mul=1; for(int i=0;i<n;i++){ int temp; scanf("%d",&temp); mul*=temp; } // 分解成质因数 int arr[10000]={0}; 善用开大数组,省去动态分配 if(mul==1){ printf("1\n"); return; } int len=0; int a=0; while(mul%2 == 0){ a=1; arr[len]++; mul=mul/2; } if(a) len++; int m=mul; for(int i=3;i<=m;i=i+2){ int flag=0; while(mul%i ==0){ flag=1; arr[len]++; mul=mul/i; } if(flag){ len++; } } int res=1; for(int i=0;i<len;i++){ res*=arr[i]+1; } printf("%d\n",res); }

18.

求多个数的最大公约数和最小公倍数,核心是两两相求;

比如求:2、3、4 的最大公约数

  1. 先求2 和 3 的 GCD→ 1
  2. 再用结果1 和 4 求 GCD→ 1

所以:gcd(2,3,4) = 1

求:2、3、4 的最小公倍数

  1. 先求 LCM (2,3)LCM = 2×3 ÷ gcd (2,3) = 6 ÷ 1 = 6

  2. 再求 LCM (6,4)gcd (6,4)=2LCM = 6×4 ÷ 2 = 24÷2 =12

所以:LCM(2,3,4) = 12

19.

  • 阶乘末尾尾随零的数量 =n!中 5 的总个数(因为 2 的数量足够多);
  • 统计 5 的总个数需用n//5 + n//25 + n//125 + ...(直到除数 > n),而非仅算能被 5 整除的数;
#include <stdio.h> int count_trailing_zeros(int n) { int zero_count = 0; 下面求n!中含多少个5 // 循环计算5的各次幂的贡献,直到除数超过n while (n >= 5) { n = n / 5; // 等价于整数除法,依次算n//5、n//25、n//125... zero_count += n; // 累加每一轮的5因子数 } return zero_count; } int main() { int n; scanf("%d", &n); printf("%d\n", count_trailing_zeros(n)); return 0; }

20.

向上取整就是取更大的数,正数取绝对值更大,负数取绝对值更小;

向下取整就是取更小的数

C语言默认正数除法是直接丢掉小数部分

round函数可以实现正、负的四舍五入,只看小数部分的绝对值决定是舍去还是进1,不看符号

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 17:19:13

医疗报告智能解读:Kotaemon行业应用案例

医疗报告智能解读&#xff1a;Kotaemon行业应用案例 1. 它能帮你做什么&#xff1f; 想象一下这个场景&#xff1a;一位医生每天需要阅读几十份甚至上百份患者的检查报告、化验单和影像学描述。这些报告专业术语多、数据繁杂&#xff0c;快速准确地抓住关键信息&#xff0c;对…

作者头像 李华
网站建设 2026/7/14 17:19:12

【网络】Socket网络编程

目录 Socket编程基础 理解源网络通信本质 认识端口号 端口号的划分 进程号&端口号 源端口&目的端口 理解socket TCP协议&UDP协议 网络字节序 相关字节序转换系统调用接口 Socket编程接口 常见API sockaddr 结构 Socket 编程 UDP V1版本 --echo server…

作者头像 李华
网站建设 2026/7/14 17:19:13

阿里通义Z-Image-Turbo快速上手:WebUI三大标签页使用详解

阿里通义Z-Image-Turbo快速上手&#xff1a;WebUI三大标签页使用详解 你是不是也对AI绘画感兴趣&#xff0c;但被复杂的参数和命令行劝退了&#xff1f;今天我要介绍的阿里通义Z-Image-Turbo WebUI&#xff0c;就是一个让你零门槛体验AI绘画的神器。这个由科哥二次开发构建的W…

作者头像 李华
网站建设 2026/7/14 17:19:18

vLLM与HuggingFace Pipeline对比:速度提升8倍实测案例

vLLM与HuggingFace Pipeline对比&#xff1a;速度提升8倍实测案例 如果你正在部署大语言模型&#xff0c;肯定遇到过这样的烦恼&#xff1a;模型推理速度太慢&#xff0c;用户等得着急&#xff1b;服务器内存消耗巨大&#xff0c;成本居高不下。传统的推理框架在处理并发请求时…

作者头像 李华
网站建设 2026/7/14 17:19:31

TurboDiffusion性能监控:nvidia-smi实时查看教程

TurboDiffusion性能监控&#xff1a;nvidia-smi实时查看教程 1. 为什么需要监控TurboDiffusion的性能&#xff1f; 如果你用过TurboDiffusion生成视频&#xff0c;肯定遇到过这样的情况&#xff1a;点了生成按钮&#xff0c;然后就是漫长的等待。看着进度条缓慢移动&#xff…

作者头像 李华