c语言

\(updata : 2021.12.24\)

为了 \(c\) 语言考试 , 特意来水一篇博客


switch

\(① :\) 首先没有 default 也可以 , default只是所有的 case 不满足之后 , 才执行 default 之后的语句.
\(② :\) 没有 break .当一个 case 满足条件之后 , 但它的后面没有break , 那它会一直执行下一条case (无视 case 的条件) , 直到遇到一个case后面有 break , 或者运行完所有的 case (包括default ).
\(③ :\) default可以不放最后面 , 但要达到效果的化必须加上break , 不加 break 同理 \(②\) 情况.


赋值为右结合性

例如 a = b = c , 就是 \(c\) 赋值给 \(b\) , \(b\) 再赋值给 \(a\) .


输出格式

int a = 4 , b = 40;
printf("%5d\n%5d",a,b); // 保证右对齐 , 一共5位 , 当数字位数大于5则没有对齐效果.
printf("%-5d\n%-5d",a,b); // 保证左对齐.
printf("%o",) // 8进制
printf("%x",) // 16进制
printf("%u",) // 针对于unsigned
printf("%.nlf") //保留小数点后n位

运算符的优先级

() [] 大于 ++ -- 大于 * / % + - 大于 == !=

\(updata : 2021.12.29\) 突然发现 && 的优先级大于 ||! 的优先级是大于 && .


数组的初始化 :

\(① :\) 一维数组的初始化

可以全部赋初始值

int a[5] = {1,2,3,4,5};

当然如果你数组长度只想定为 \(5\) 的话 , 可以省略成

int a[] = {1,2,3,4,5};

但如果你数组长度想定为 \(10\) , 就不能这样玩

int a[10] = {1,2,3,4,5}; // 给0 ~ 4赋初始值 , 其余为 0

初始值想赋值为 \(0\) 的话 ,

int a[5] = {0,0,0,0,0};
int a[5] = {0};

二维数组的初始化

可以这样 int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

也可以这样

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; //编译系统会根据第二维自动分行

可以这样

int a[3][4] = { {1} , {5} , {9} };
//每行的第一个数才有值 , 其他的为零.

当然也可以这样 , 对一些特定位置赋值 , 其他的位置为零.

int a[3][4] = { {1,1} , {1,1,2} , {3} }
/*
1 1 0 0
1 1 2 0
3 0 0 0 
*/

同样我们可以对行的初始值进行省略

int a[3][4] = {{1},{3,4}};
int a[3][4] = {{1},{},{9}};

同样我们知道第二维可以用来确定第一维的个数

int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; //个数不为4的倍数时,会用零补齐这一行
int a[][4] = {{0,0,3},{},{0,10}} //这里就明确了有3行

选择排序

	for(int i=1;i<=n;++i){
		for(int j=i;j<=n;++j)
			if(a[j] < a[i]) swap(a[j] , a[i]);
	}
	//在剩下区域中选择一个最小的放在first_unsort位置上

冒泡排序

	for(int i=1;i<=n;++i){
		int flag  = 0;
		for(int j=n;j>i;--j){
			if(a[j] < a[j-1]){
				swap(a[j] , a[j-1]);
				flag = 1;
			}
		}
		if(!flag) break;
		//排序时全员参与 , 没有变化时说明已经排好了 , 及时break;
	}

字符

关于字符数组初始化 , 可以参考上文数值数组的初始化 , 注意使用 ' ' .

关于字符常用函数 , 可以参考这里


函数

主要分清楚形参与实参 ,有例子

void Swap(int &a,int &b){
	int t ; 
	t = a , a = b , b = t;
}
void Swap(int a,int b){
	int t ; 
	t = a , a = b , b = t;
}

数组作为函数的参数

用数组名传递函数参数 , 传递的是数组首元素的地址 , 且可以不必申请形参数组的大小

float arr(int a[10])

float arr(int a[])

多维数组名作函数参数

可以说明每一维的大小 , 也可以省略第一维的大小 , 但不能省略第 \(2\) 维以及其他高维的大小.

int max(int a[5][4] , b[][5]) // 二者均合法

int max(int a[5][] , b[][]) // 二者均不合法

同时在第二维相同的情况下 , 形实参数组的第一维大小可以不相同.


局部变量与全局变量

注意变量在复合语句中 ,函数中的有效性 , 脱离后系统会把它内存所占空间释放.


变量的储存方式与生存期

分为 \(auto\) , \(static\) , \(register\) , \(extern\) 四大类别

首先全局变量自动分配在静态区 ,而且不专门申明为 \(static\) , 数据都储存在动态存储区.

\(① : auto\)

\(auto\) 可以忽略不写 , 不写 \(auto\) 则默认自动存储类别 .

int f(int a){
    auto int b , c;
}

\(② : static\)

全局变量属于 \(static\)

函数调用(或一次循环)后内存单元不会释放 , 且会保留上一次函数(循环)调用后的值

个人感觉主要在循环与函数中使用吧 (在主函数 \(main\) 中直接定义 \(auto\) 就好了 , 主函数外的话直接用全局变量即可)

注 : \(static\) 类型只能赋一次初值 , 如果不赋初值的话 , 编译时自动赋值为 \(0\) , 或者空字符 '\0' (对字符而言)

\(③ : register\)

把变量放在寄存器中 , 以前以为在卡常方面有用 ,但大部分编译器在这方面会自动优化.

\(④ : extern\)

针对于多个源程序文件的编译 , 多个文件用同一变量的时候 , 将变量的作用域扩展到文件外.


指针

作为函数参数 , 经典例子

int a , b , *p1 , *p2 ;

scanf("%d%d",&a,&b);

p1 = &a , p2 = &b;

Swap(p1 , p2);

void Swap(int *p1 , int *p2){
	int temp;
	temp = *p1 , *p1 = *p2 , *p2 = temp;
}

在一维数组中的应用

\(① :\) 初始化

int a[10] ;

int *p = &a[0]; //第一种

int *p = a; //第二种

int *p ; p = a 或 p = &a[0]; //第三种

\(② :\) 在循环中的应用

int a[10] , *p;

for(p=a;p<(a+10);++p) printf("%d ",*p);

for(i=0;i<10;++i) printf("%d ",*(a+i));

注意 a 是指针常量 , ++a 是不合法的.

\(③ :\) 注意事项

++ , * 优先级是相同的 , 但是注意结合方向是自右向左的.

*p++ , *++p 是有区别的 , 前者先取 \(*p\) 再自加 , 后者先自加再取 \(*p\) ;

用指针变量作为实参的话 , 必须先使指针变量有确定的值 , 指向一个确定的变量.

在字符串中的应用

前置 :\(c\) 语言中只有字符变量 , 没有字符串变量.

char *string = "I love china!"; // 将字符串的首地址给string

printf("%s\n",string); // 到字符结束标志'\0'为止.

posted @ 2021-12-24 10:38  xqy2003  阅读(123)  评论(0)    收藏  举报