ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

大一C语言学习记录-2

大一C语言学习记录-2 预备知识先补一下上一篇没提到的编程前基础知识吧这部分穿插我自己的理解以及AI-generated content进制转化除基取余用带余除法除以基数二进制基数为2商进行同样操作最后得到的所有余数倒序读即是二进制数乘积取整遇到小数的情况字面意思乘以基数2之后去整数部分新的小数部分采取同样操作知道没有小数部分最后得到的整数部分正序读但是不是所有小数都能转尽如0.1八二互转1位八进制数可以转为3位二进制数二进制表示方式原码、反码与补码 | 浮点数 | 字符编码原码首位表示正负规定0为正1为负那么用8位来表示一个数字可以如下5 0000 0101-5 1000 0101 ← 最高位变 1其余不变缺点1.有两个0正负各一个2.符号位不能直接参与运算得单独判断符号、比较大小、决定做加法还是减法电路复杂反码正数同原码负数取其相反数的全反如下5 0000 0101-5 1111 1010优点减法可以用加法替代了缺点还是有两个0且多了循环进位如5-51 1111 1111补码现代计算机所使用的码正数同原码负数为反码15 0000 0101-5 1111 1011优点1.只有一个02.加减法完全统一溢出位直接舍弃如5-500000 01011111 10111 0000 0000 ← 最高位溢出丢弃浮点数本质是科学计数法的二进制版由符号指数尾数组成如1.0101*10²其中符号为正0指数为2尾数为1.0101| 1 位 | 8 位 | 23 位 | ←float32精度| 符号 | 指数 | 尾数 |S E M| 1 位 | 11 位 | 52 位 | ←double64双精度| 符号 | 指数 | 尾数 |S E M指数位 E指数不能直接存要加一个偏移量biasfloat偏移 127实际指数 E - 127double偏移 1023实际指数 E - 1023为什么加偏移为了让指数也能表示负数且方便比较大小避开全0和全1尾数位 M这里有个隐含的 1二进制科学计数法规范化后尾数总是 1.xxxxx所以开头的 1 不用存只存小数点后的部分。float 存 23 位实际精度是 24 位隐含的 1 23 位。double 存 52 位实际精度是 53 位。浮点数并不精确很多十进制小数无法用二进制精确表示如上面提到的0.10.1 的二进制是 0.0001100110011… 无限循环只能截断存储所以有误差That’s why:if(0.10.20.3)// ❌ 结果是 falseprintf(相等\n);right way:if(fabs(a-b)1e-9)// 差小于误差范围就算相等printf(相等\n);编程中的实际影响1.scanf 读 double 必须用 %lf2.浮点数不能用 比较3.大数 小数会吃掉小数如double x 1e20 ; x x 1.0;x的值还是1e204.0.0有正负之分1.0 / 0.0 // ∞1.0 / -0.0 // -∞字符编码字符也是数字用编码表把字符和数字对应起来如’A’对应65常用ASCⅡ编码表char就是按ASCⅡ存的需要记忆‘A’ 65‘a’ 97两者差 32‘0’ 48缺点1.只有 128 个字符只够英语用。2.存不下中文、日文、阿拉伯文、emoji 等。3.各国自己扩展比如中文 GBK但互相冲突同一串字节在不同编码下意思不同乱码由此而来。另外的编码表还有Unicode统一码、万国码关键点1.Unicode 只是一张巨大的表规定「哪个字符对应哪个编号」。2.它不规定怎么存储这是最容易搞混的地方。3.编号范围U0000 到 U10FFFF能容纳 100 多万个字符。4.兼容ASCⅡ前128个码点与其相同常见误区1.「Unicode 是 2 字节」——错2.Unicode 只是编号表不是存储格式。怎么存要看 UTF-8、UTF-16 等具体方案。常用的UTF-8 是 Unicode 的一种具体存储/编码方式乱码的根源用 A 编码存用 B 编码读。比如 UTF-8 的中文用 GBK 打开就成了「锟斤拷」之类冯·诺伊曼系统运算器控制器储存器输入设备输出设备别的懒得写的查AI吧指令、程序与程序设计语言指令指令CPU 能直接识别并执行的最小操作命令通常包含操作码与操作数指令在内存里也是二进制一台 CPU 能执行的所有指令的集合叫指令系统也叫指令集架构ISA指令系统是硬件和软件的接口。编译器生成代码时必须按目标 CPU 的指令系统来生成。常见指令系统x86、x86-64、ARM、RISC-V、MIPS程序程序 指令 数据按一定顺序排列用来完成某个任务程序在内存里地址 内容1000 指令11004 指令21008 指令3…2000 数据12004 数据2程序 数据结构 算法这是经典说法数据结构数据怎么组织数组、链表、树算法怎么处理数据步骤程序设计语言机器语言第一代直接是二进制10110000 00000001优点CPU 直接执行最快。缺点人看不懂、写起来痛苦、不可移植。汇编语言第二代用助记符代替二进制优点比机器语言好读。缺点还是和具体 CPU 绑定可移植差。需要汇编程序翻译成机器码。高级语言第三代及以后接近自然语言和数学优点好写、好读、可移植。缺点需要翻译成机器码。例子C、C、Java、Python、Go、JavaScript。按执行方式分类编译型 整体翻译成机器码运行快 C、C、Go解释型 逐行解释执行灵活但慢 Python、JavaScript混合型 先编译成中间码再解释/JIT Java、C#按范式分类面向过程C、Pascal面向对象C、Java、Python函数式Haskell、Lisp逻辑式Prolog从源程序到可执行程序hello.c → [预处理] → hello.i→ [编译] → hello.s→ [汇编] → hello.o→ [链接] → hello (可执行文件)预处理Preprocessing工具预处理器做什么展开 #include把头文件内容贴进来展开 #define 宏处理 #ifdef 等条件编译去掉注释输入hello.c → 输出hello.i还是文本编译Compilation工具编译器做什么词法分析、语法分析、语义分析优化生成汇编代码输入hello.i → 输出hello.s汇编文本汇编Assembly工具汇编器做什么把汇编代码翻译成机器码生成目标文件。输入hello.s → 输出hello.o二进制目标文件注意.o 文件已经是机器码了但还不能运行因为里面调用的 printf 等还没接上。链接Linking工具链接器做什么把多个 .o 文件和库文件合并解决函数、变量的地址引用生成最终可执行文件输入hello.o 库 → 输出hello可执行文件上课时遇到的一些题目判断以下均为正确1.在 C 程序运行过程中其值不能被改变的量称为常量其值可以改变的量称为变量2.在 C 程序中APH 和 aph 代表不同的变量3.实型数据不可以进行求余数运算 %4.任何表达式语句都是表达式加分号组成的5.合法的用户自定义标识符不能与 C 语言关键字重名但可以和库函数名重名但是会覆盖库函数名不推荐6.数据类型限定了变量的取值范围超出范围会出现数据溢出问题如int只有32位7.C 语言标识符只能由字母、数字、下划线构成不能含有空格且数字不能放在首位8.赋值表达式a5本身有值表达式的值就是 59.C 语言中变量必须先定义、后使用未经定义的变量无法直接参与运算和赋值虽然也可以用但是规范如此不声明会warning10.C 语言中空白字符空格、换行不可以随意添加有时会影响程序语法正确性例如int a b;就是语法错误11.算法可以没有输入但是一定要有输出输入可以在内部规定但是没有输出算法就没有意义12.else 的个数不能多于 if 的个数且else对应的是上面距离它最近的未与else配对的if13.C程序由函数组成14.‘D’ - ‘A’ ‘d’ - a’的值为1选择题目以下不属于 C 语言基本数据类型作用的是__D____。A. 规定变量内存占用大小B. 限定变量取值范围C. 确定数据存储精度D. 提高程序运行速度作业计算油费现在90号汽油6.95元/升、93号汽油7.44元/升、97号汽油7.93元/升。为吸引顾客某自动加油站推出了“自助服务”和“协助服务”两个服务等级分别可得到5%和3%的折扣。本题要求编写程序根据输入顾客的加油量a汽油品种b90、93或97和服务类型cm - 自助e - 协助计算并输出应付款。输入格式输入在一行中给出两个整数和一个字符分别表示顾客的加油量a汽油品种b90、93或97和服务类型cm - 自助e - 协助。输出格式在一行中输出应付款额保留小数点后2位。#includestdio.hintmain(){inta,b;charc;doubleprice,unit;scanf(%d %d %c,a,b,c);switch(b){case90:unit6.95;switch(c){casem:pricea*0.95*unit;break;casee:pricea*0.97*unit;}break;case93:unit7.44;switch(c){casem:pricea*0.95*unit;break;casee:pricea*0.97*unit;}break;case97:unit7.93;switch(c){casem:pricea*0.95*unit;break;casee:pricea*0.97*unit;}break;}printf(%.2f,price);return0;}知识点碎碎念1.getchar与putchargetchar() 从标准输入键盘读入一个字符返回它的 ASCII 码int 类型不是char没有参数getchar 是行缓冲的你输入的内容会先存在缓冲区按回车后才真正被读取且会读取缓冲区最前面的字符FIFO先进先出的队列putchar() 把一个字符写到标准输出屏幕括号里面可以填单字符如’A’可以填int转换为ASCⅡ所对应的字符经典用法1.回显输入intc;while((cgetchar())!EOF){putchar(c);}2.统计字符数intc,count0;while((cgetchar())!EOF){count;}printf(共 %d 个字符\n,count);3.清空缓冲区while(getchar()!\n);//空循环体常见错误1.getchar 返回值用 char 接 → 可能无法正确判断 EOF用 int。2.忘记 EOF 判断 → 读到结束还在处理。3.scanf 后直接 getchar → 读到残留的 ‘\n’。4.putchar 传字符串 → putchar(“A”) 是错的要传字符 putchar(‘A’)。5.getchar 一次只读一个字符 → 想读整行要循环2.switch形式switch (表达式) {case 值1:语句;break;case 值2:语句;break;…default:语句;break;}注意switch只能判断整型数case后面只能是常量执行逻辑算出 表达式 的值然后跳转到匹配的 case 开始执行直到遇到 break 或 switch 结束break 用来结束整个 switch。如果没有 break会穿透到下一个 case 继续执行易错漏写break导致穿透。但是要可以故意不写break以执行多重判断default分支default 处理所有 case 都不匹配的情况相当于 else可以不加default但是推荐加应对考虑外情况与if的区别判断等于某个具体值且分支多 → 用 switch。判断范围、复杂逻辑 ||→ 用 if。3.%ndn为某个数字如果数字本身位数 指定宽度 2左边补空格凑够 2 位printf(“%2d”,5); → 输出 5前面有 1 个空格如果数字本身位数 指定宽度 2不受 2 限制原样全部输出不会截断printf(“%2d”,123); → 输出1233 位 2直接输出只是最小宽度数字长于宽度就原样输出区分%2d最小宽度 2不够左边补空格%-2d负号 左对齐不够宽度右边补空格printf(“%-2d”,5); → 5 5 后面带空格4.测试用例一组“输入数据 预期输出结果”的组合用来测试程序是否符合期望
返回列表