一.起步阶段需要注意养成基本的编程思路
遵循计算机的模型:输入、处理、输出
输入----->CPU----->输出
数据 处理 数据
准备数据:准备变量
处理数据:通过代码对数据进行操作
输出数据:输出
在操作阶段要遵循“高内聚,低耦合”的编程逻辑。具体含义为:
在模块化编程时,关联性强的内容集中处理,关联性弱的内容分别处理。
具体在编程过程中的体现为,处理数据时只对数据进行处理;输出数据时只进行输出。避免在输出时对数据进行处理。
为了遵循“高内聚,低耦合”的原则,编程前可以通过绘制流程图的方式来整理思路,明确每一步操作的内容,避免不同层次之间的操作出现交叉。
二.20240724补充
转义字符
ascii码的0~32编码位存放的是不可见字符,即控制字符。其中包含一些特殊字符(转义字符)需要留意:
常规字符用单引号进行表示,如小写字母n的字符形式为' n '。在n前添加一个反斜杠' \ ',组成新的字符' \n ',这种用反斜杠和字符组成的新字符我们称之为转义字符,在代码中有特殊的用途。
' \n '
换行符,将当前光标位置移到下一行开头处
printf("1234\nABCD"); //输出结果: 1234 ABCD
' \t '
水平制表,跳转到下一个tab位置
类似于excel表格,每个tab可以抽象为一个表格,每个表格由八位构成。按一个tab等同于光标右移8位。
printf("12345678ABCD\n"); printf("X\tXX"); //输出结果: 12345678ABCD X XX
' \b '
退格,将当前光标位置移到前一位(区别于插入操作)
printf("1234\bABC\n"): //输出结果: 123ABC
' \r '
回车,将光标移动至本行开头处
printf("abc*\t123456\rA\tBCD"); //输出结果: Abc* BCD456
' \\ '
反斜杠
printf("abc\\ABC\\123\n"); //输出结果: abc\ABC\123
' \' '、' \" '
单引号、双引号
printf("123\'aaa\'123\n123\"bbb\"123\n"); //输出结果: 123'aaa'123 123"bbb"123
转义字符特殊表示方式
转义字符除用十进制ascii值表示外,还可以通过两位十六进制和三位八进制表示
例如大写字母A:十进制ascii编码值表示为' 65 ' ;如果用十六进制表示则为' x41 ';用八进制表示为' 101 '。不过这种方法不直观,较复杂,使用偏少。
三.算数运算
运算符:
加减乘除(+ - * /)
与常规数学计算无差别,均为双目运算符,加减优先级低于乘除。
需要注意两个整数做除法,小数部分被舍去。
取余(%)
13 % 5 = 3
只能对整数对整数取余,小数参与取余运算会报错。取余运算的结果只与左值(%左边的值)有关。取余结果的符号也只与(左值)有关。
计算技巧:对一个正整数X取余,得到的结果的取值范围为0 ~ X - 1。用这个方法,可以将随机数等较大值,在一定范围内取值。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void)
{
int i = 0;
srand(time(NULL));
for(i=0;i < 5;++i)
{
printf("%d\n",rand() % 50 + 49);
}
return 0;
}
//运行结果
64
88
79
68
89
运算符的属性
优先级:运算符有固定优先级,高优先级运算符优先运算。
结合性:同一优先级的运算符在混合运算时按照结合性进行结合。
1 + 2 * 3 - 4 =>=>= 1 + (2 * 3) - 4 =>=>= (1 + (2 * 3)) - 4
类型转换
强制类型转换
在编程时手动完成。
//强转
int a = 10;
float f = 12.345;
printf("%f\n%d\n",(float)a,(int)f);
//运行结果:
10.000000
12
隐式类型转换
由程序自动进行的过程,遵循低精度与高精度混合运算时,自动转为对应高精度;float自动转为double,short、char自动转为int。
int a = 10;
float f = 12.345;
printf("%f\n",a * f);
printf("%f\n",a * 2.0);
//输出结果
123.45
20.000000
自增(++)的两种形式:i++、++i
区别在于i++先取值参与运算,再加一;++i 先加一,再取值参与运算。
共同点为只有在参与运算时才能体现出加一先后的区别,在不参与运算时两者效果均为加一。
从内存空间角度分析二者区别:
i++:自加之前,在内存空间中开辟一片新空间,用于存放自加后的值,但此时如果调用i的值,得到的仍为原值;只有当完整运算过程结束后,新空间中的值才会赋给原空间中的值,赋值结束后,新空间中的内容被释放。
++i:在自加时,直接改变内存空间中 i 的值,无论何时调用 i 的值,都将得到自加后的 i 值。
因此,从内存空间分析可以得知,++i的方式避免了新内存空间的使用,效率更高。
//++i
int i = 0;
a = ++i;
printf("a = %d i = %d\n",a,i);
//运行结果
a = 1 i = 1
//i++
int i = 0;
a = i++;
printf("a = %d i = %d\n",a,i);
//运行结果
a = 0 i = 1
此处涉及到另一个知识点:左值、右值
左值:可被定位的值,即有具体地址的值。
右值:不可被定位的值,即无法取地址的值。
在i++的过程中使用到了一片临时内存空间,在运算结束时内存被释放,因此也被称为匿名变量。匿名变量的地址不明确,无法进行取地址操作。所以 i++也可以成为右值,无法被赋值。
在混合运算中,编译器会将相邻的各种运算符进行分隔,此处用到的知识是贪心法则。贪心法则是编译器处理符号的一种方式:编译器处理的每个符号应尽可能多的包含字符;编译器以从左向右的顺序一个一个尽可能多的读入符号;当读入的字符不可能和已经读入的字符组成合法字符为止。
eg:
a + + + + + b =>=>=> a ++ ++ + b =>=>=> (a++) ++ + b =>=>=> ((a++)++) + b
注意!i++先调值使用,后自加,但与额外代码共同执行时,何时自加是不明确的,无法确定 i 的值何时变化。因此建议最好将 i++运算过程单独进行.
//问题写法
printf("%d %d\n",i,i++);
//建议写法
a = i;
b = i++;
printf("%d %d\n",a,b);
赋值运算(+=、*=、=)
赋值运算的结果就是被赋值的变量的值;赋值运算的类型就是被赋值变量的类型。
a = b = c = d = 10;
==> d = 10;
==> c = 10;
==> b = 10;
==> a = 10;
//每一次赋值数值为上一赋值过程变量的值;类型为上一赋值过程变量的类型
逗号运算(a = 1,10 + 2,b = 12 + 6)
逗号运算又称顺序求值,按照从左到右的顺序,挨个运算,执行每一个运算式。
逗号运算的结果为最后一个运算式的结果。
不同类型变量混合赋值
高精度向低精度赋值,会出现精度丢失
int a = 12.345;
printf("a = %d\n",a);
//运算结果
a = 12
低精度向高精度赋值
float a = 123;
printf("a = %f\n",a);
//运算结果
a = 123.000000
长数值向短数值赋值,会出现高位截断
short a = 0x12345678;
printf("a = %#x\n",a);
//运算结果
a = 0x345678
短数值向长数值赋值
有符号短数值向长数值赋值:高位补0;
无符号短数值向长数值赋值:高位补符号位(符号位扩展)。
int a = 0x1234;
int b = 0x8234;
printf("a = %#x b = %#x\n",a,b);
//运算结果
a = 0x1234 b = 0xffff8234