C语言
C语言易错难懂知识
一些基础知识
1.进制
二进制:0b开头
八进制:0开头
十六进制:0X开头(09,AF)
2.float 4字节 有效数字6
double 8字节 有效数字15
不同类型数据运算时,除强制类型转换外,结果都为double型
在一个整数末尾加L/l表示长整型
eg. int b=5;
float a=2.0;
b=b/2*a; //b=5
3.素数中:不必被2(n-1)整除,只需被2✓n即可,j*j<i
4.a%b结果由a的正负性决定,只要a为负数,结果为负数
5.常量和常变量
常变量:在定义变量时,加一个const
eg.const int a=3;
变量:
(1)整型变量 1000
(2)实型变量 12.34e3
(3)字符常量(只能为一个字符,’ \42 ‘为一个字符)
1)普通字符:以ASCII码存储
常见的ASCII:’A’ =65 ‘a’ =97 0 =48
2)转义字符:以’ \ ‘开头,将’ \ ‘后的字符转化为另外意思
eg.’ \x41 ‘表示16进制41的ASCII字符,即’ A ‘
3)字符串常量:“boy”
4)符号常量(不能对其赋新值):#define PI 3.1416
6.标识符:只由字母,数字,下划线组成;第一个字符必须是字母或下划线
7.unsigned int =>无符号整型 输出用%u
(充分利用变量的值的范围(数据范围只有正值))
8.逗号表达式结果取后面的值
eg.i=(a=6,a*5),a+6;//>i=30
9.要输出%应该连续使用2个%
10.字符变量
1 | char c=' ? '; |
11.i++和++i
i=3;
j=i++(i=4,j=3)//先赋值后自加
j=++i(i=4,j=4)//先自加在赋值
12.输出:
用%f得到6位小数
%-m.nf :
-号为左对齐
m为最小宽度:输出的总宽度(包括小数点、小数部分和整数部分)如果实际数据长度小于 m,将用空格填充;如果数据长度超过 m,则按实际长度输出,不截断
n为小数小数位数:如果实际小数位数超过 n,会进行四舍五入;如果不足n,会用0补足
%e指定以指数形式输出实数,自动给出数字部分小数位数为6位,指数部分占5列
eg.1.234560 e+002
13.运算符优先级
14.字符(一个)输入输出:
getchar putchar(c)
15.在判断一个量是否为真时,0为假,非0为真
a&&b//a和b都非0(只有a为真时,才需要判别b的值)
a||b//a和b至少一个非0(只有a为假时才需要判别b的值)
16.判断非闰年:
!((year%4==0&&year%100!=0)||year%400==0)
17.两个数乘积=两个数最大公约数 x 最小公倍数
选择结构
?:表达式(代替复杂的if)
max=(a>b)?a:b;//a>b为真的话,max=a,否则为b
switch
switch(表达式){
case 常量1:语句1;
……
default:……;
}
循环结构
while语句
只要循环条件表达式为真时,就执行
eg.while(i–)//每次循环开始先检查i当前值是否为真,若为真,循环继续,每次循环结束时i值减少一
do while语句
先无条件执行,再判断循环条件是否成立
for语句
for(…;…[只要值为真,就执行循环];…)
break和continue
break:提前终止循环
continue:提前结束本次循环,接着执行下次循环
数组
a[3][4]
=>3行4列
字符数组
字符串结束标志
一个字符串以字符'\0'
作为结束标志(c语言在字符数组储存字符串常量市会自动加一个’\0’作结束符)
字符数组的输入输出
%s =>整个字符串
%c =>一个字符
输出时遇到’\0’就停止输出
scanf输入项如果是字符数组名,不加&
scanf读取字符串时,会在遇空白字符时停止读取
单行字符串
1 | while((ch=getchar())!='\n'){ |
1 | char string[100]; |
n行字符串
1 | scanf("%d",&n); |
1 | scanf("%d",&n); |
字符串处理函数
记得加#include<string.h>
puts
输出的字符串中可以包含转义字符
e.g
1 | char str[]={"abc \n def"}; |
gets
从终端输入一个字符串到字符数组,并且得到一个函数值,该函数值是字符数组的起始地址
注:gets和puts函数只能输入/输出一个字符串
strcat
把两个字符数组中字符串连接起来
strcat(str1,str2);
strcpy和strncpy
字符串复制函数
strcpy
将字符串2复制到字符数组1中
注:赋值语句只能将一个字符赋给一个字符型变量/字符数组元素
strncpy
将字符串2中前n个字符复制到字符数组1中
strncpy(str1,str2,2);//将str2前2个取代str1原有的2个
strcmp
字符串比较:2个字符串从左到右逐个比较(ASCII值),直到出现不同字符或遇到’\0’为止
字符串1=字符串2 函数值为0
字符串1>字符串2 函数值为正整数
字符串1<字符串2 函数值为负整数
strlen
测字符串长度
strlwr
转换为小写
strupr
转换为大写
<ctype.h>头文件
isalpha判断一个字符是否是字母
isdigit判断一个字符是否是数字
islower判断一个字符是否是小写字母
isupper判断一个字符是否是大写字母
isspace判断一个字符是否是空白字符
tolower将字符大写变小写
toupper将字符小写变大写
函数
函数的定义与声明
在定义函数时要指定函数的类型
函数类型决定返回值类型
用函数原型(函数首部)作函数声明
e.g int add(int a,int b);
函数的嵌套
1 | int max4(int a,int b,int c,int d){ |
局部与全局变量
注:全局变量开头一般用大写字母,来区别局部变量
static
静态局部/全局变量
函数中局部变量的值在函数调用结束后不消失而继续保留本次调用结束后的值
e.g static int f=1;
extern
外部变量声明
在一个文件内扩展外部变量的作用域
将外部变量的作用域扩展到其他文件
e.g extern A,B,C; \ \可省略int等类型
指针
指针变量
指针是一个地址,而指针变量是存放地址的变量
指针变量中只能存放地址(指针),不要将一个整数给指针变量
p=&a;
*p=1;\ \将1赋值给p所指向的变量即把1赋给a
定义:类型名 * 指针变量名
int* point;
point=&a;\ \等价于int* point=&a;
函数调用时不加*
e.g swap(point_1,point_2);
为使在函数中改变的变量能被main所用,应该用指针变量做函数参数
e.g
1 | void swap(int *p1,int *p2){ |
通过指针引用数组
一维数组
1 | int *p; |
1 | p=&a[0]; |
如果指针元素p指向数组中的一个元素,则p+1指向同一数组的下个元素,p-1指向同一数组的上个元素
如果p的初值为&a[0],则p+i/a+i即a[i]的地址,*(p+i)/ *(a+i)是p+i/a+i所指向的数组元素即a[i]
两个地址不能相加
若指针变量p1、p2都指向同一数组中的元素,p2-p1结果为(p2-p1)的值(地址之差)
1 | int i,a[10]; |
若a[0]=3,++(*p) =>a[0]=4
fun(int arr[],int n) = fun(int* arr,int n)
二维数组
*(a[i]+j)
或 *(*(a+i)+j)
是a[i][j]
的值
对于a是二维数组,则a[i]是一位数组名,他是一个地址,并不代表一个储存单元/其中的值
int (*p)[4]定义包含4个元素的一维数组的指针变量
e.g 有一个二维数组int arr[3][4]
,可用int (*p)[4]来声明一个指针p指向这个二维数组某一行
1 | int arr[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; |
通过指针引用字符串
通过字符数组名/字符指针变量可以输出一个字符串
1 | char* a,str[10]; |
数组名虽代表地址,但它是常量,其值不可改变
字符指针变量指向的字符串常量中的内容是不可被取代
指向函数的指针
函数名是一个指针(地址)
1 | int (*p)(int,int) |
char* p[6]包含6个指针的数值
用户自己建立数据类型
结构体
struct 结构体名{
成员表列(类型名 成员名);
};
引用结构体变量中成员的值:结构体变量名.成员名 e.gstudent1.num=10010;
不能通过输出结构体变量名来达到输出结构体变量所有成员的值
若p指向一个结构体变量stu
则 stu.num <=> (*p).num <=> p->num
结构体数组读入不用加&
共用体
union 共用体名{
成员表列(类型名 成员名);
};
typedef声明新类型名
C语言经典例题
统计一个字符串中每个单词的字符数
1 | #include<stdio.h> |
统计3个字符串,并找出其中最大值
1 | #include<stdio.h> |
字符串的复制(指针)
1 | void copy_string(char* from,char* to){ |
1 | void copy_string(char* from,char* to){ |
1 | void copy_string(char* from,char* to){ |
选择排序
1 | void selectSort(int arr[],int n){ |
人数过半
输入N个数,求出现次数超过总数一半的数。数据保证存在这个数。
输入格式:
第一行输入一个正整数N(N<1000);
第二行输入N个数,每个数的绝对值不超过1e9。
输出格式:
输出一个数,即出现次数超过总数一半的数。
1 | #include<stdio.h> |
n个数字中选出数字和最大的连续一段
1 | int sum1=0,sum=-1000; |
结尾不输出空行
1 | int flag=1; |
数组元素右移
n个数,第i个数向右移m个整数变为a[(i+n-m)%n]
单词翻转
1 | #include<stdio.h> |
10进制数n转化成m进制
1 | int cnt=1,sum=0; |
求n的素数因子和
1 | for(int i=1;i<sqrt(n);i++){ |
求a,b的最大公约数
1 | m=a; |
将一个n位数反转
1 | int number,res=0,rem; |
杨辉三角
1 | #include<stdio.h> |