c语言基础知识

ASCII码

字符A~Z的ASCII码值从65~90
• 字符a~z的ASCII码值从97~122
• 对应的⼤⼩写字符(a和A)的ASCII码值的差值32
• 数字字符0~9的ASCII码值从48~57
• 换⾏ \n 的ASCII值是:10
• 在这些字符中ASCII码值从0~31这32个字符是不可打印字符,⽆法打印在屏幕上观察

ASCII码表

字符串和\0(双引号括起来的⼀串字符)

对于字符串"abcdef",我们实际上看到了6个字符:a,b,c,d,e,f,但是实际上在末尾还隐藏⼀个 \0 的转义字符, \0 是字符串的结束标志。所以我们在使⽤库函数 printf() 打印字符串或者
strlen() 计算字符串⻓度的时候,遇到 \0 的时候就⾃动停⽌

#include <stdio.h>
int main()
{
char arr1[] = {'a', 'b', 'c', '\0'};
char arr2[] = "abc";
char arr3[] = {'a', 'b', 'c', '\0'};
printf("%s\n", arr1);//abc
printf("%s\n", arr2);//abc
printf("%s\n", arr3);//abc烫烫烫?^&%*
printf("%s\n", "abc\0def");
return 0;
}

 转义字符

\? :在书写连续多个问号时使⽤,防⽌他们被解析成三字⺟词,在新的编译器上没法验证
• \' :⽤于表⽰字符常量'
• \" :⽤于表⽰⼀个字符串内部的双引号
• \\ :⽤于表⽰⼀个反斜杠,防⽌它被解释为⼀个转义序列符。
• \a :警报,这会使得终端发出警报声或出现闪烁,或者两者同时发⽣。
• \b :退格键,光标回退⼀个字符,但不删除字符。
• \f :换⻚符,光标移到下⼀⻚。在现代系统上,这已经反映不出来了,⾏为改成类似于 \v 
• \n :换⾏符。
• \r :回⻋符,光标移到同⼀⾏的开头。
• \t :制表符,光标移到下⼀个⽔平制表位,通常是下⼀个8的倍数。
• \v :垂直分隔符,光标移到下⼀个垂直制表位,通常是下⼀⾏的同⼀列。
• \ddd :ddd表⽰1~3个⼋进制的数字。如:\130表⽰字符X
• \xdd :dd表⽰2个⼗六进制数字。如:\x30表⽰字符0
\0 :null字符,代表没有内容, \0 就是 \ddd 这类转义字符的⼀种,⽤于字符串的结束标志,其ASCII码值是0.

注释会被替换

编译时,注释会被替换成⼀个空格,所以 min/* 这⾥是注释*/Value 会变成 min Value ,⽽不
是 minValue

数据类型

 字符型                              

char                               
[signed] char
unsigned char

整型
//短整型
short [int]
[signed] short [int]
unsigned short [int]
//整型
int
[signed] int
unsigned int
//⻓整型
long [int]
[signed] long [int]
unsigned long [int]
//更⻓的整型
//C99中引⼊

long long [int]
[signed] long long [int]
unsigned long long [int]

浮点型
float(单精度浮点)
double(双精度浮点)
long double(精度更高的浮点型)

布尔类型
Bool
头⽂件 <stdbool.h>
布尔类型变量的取值是:true或者false

sizeof操作符

⽤来计算sizeof操作符数的类型⻓度的,单位是字节

sizeof( 类型 )
sizeof 表达式            

--------sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出⼤⼩
--------size_t 类型(无符号整数,打印时用%zd)

sizeof 运算符的返回值,C语⾔只规定是⽆符号整数,并没有规定具体的类型,⽽是留给
系统⾃⼰去决定

sizeof中表达式不计算(sizeof 在代码进⾏编译的时候,就根据表达式的类型确定了,类型的常⽤,⽽表达式的执⾏却要在程序运⾏期间才能执⾏,在编译期间已经将sizeof处理掉了,所以在运⾏期间就不会执⾏表达式了)

printf("%zd\n", sizeof(3 + 3.5));//8

short s = 2;
int b = 10;
printf("%d\n", sizeof(s = b+1));//2    字节存储在short被截断

#include <stdio.h>
int main()
{
	printf("%zd\n", sizeof(char));//1
	printf("%zd\n", sizeof(_Bool));//1
	printf("%zd\n", sizeof(short));//2
	printf("%zd\n", sizeof(int));//4
	printf("%zd\n", sizeof(long));//4
	printf("%zd\n", sizeof(long long));//8
	printf("%zd\n", sizeof(float));//4
	printf("%zd\n", sizeof(double));//8
	printf("%zd\n", sizeof(long double));//8
	return 0;
}

signed和unsigned

C语⾔使⽤ signed 和 unsigned 关键字修饰字符型和整型类型的。
signed 关键字,表⽰⼀个类型带有正负号,包含负值;
unsigned 关键字,表⽰该类型不带有正负号,只能表⽰零和正整数。
对于 int 类型,默认是带有正负号的,也就是说 int 等同于 signed int 。
由于这是默认情况,关键字 signed ⼀般都省略不写,但是写了也不算错

int 类型也可以不带正负号,只表⽰⾮负整数。这时就必须使⽤关键字 unsigned 声明变量
整数变量声明为 unsigned 的好处是,同样⻓度的内存能够表⽰的最⼤整数值,增⼤了⼀倍
C语⾔规定 char 类型默认是否带有正负号,由当前系统决定。
这就是说, char 不等同于 signed char ,它有可能是 signed char ,也有可能是
unsigned char 。
这⼀点与 int 不同, int 就是等同于 signed int

全局变量:在⼤括号外部定义的变量就是全局变量
        全局变量的使⽤范围更⼴,整个⼯程中想使⽤,都是有办法使⽤的。
局部变量:在⼤括号内部定义的变量就是局部变量
        局部变量的使⽤范围是⽐较局限,只能在⾃⼰所在的局部范围内使⽤的

1.局部变量是放在内存的栈区
2. 全局变量是放在内存的静态区
3. 堆区是⽤来动态内存管理的

 % (计算时的正负号)

返回两个整数相除的余值。这个运算符只能⽤于整数,不能⽤于浮点数

负数求模的规则是,结果的正负号由第⼀个运算数的正负号决定

#include <stdio.h>
int main()
{
printf("%d\n", 11 % -5); // 1
printf("%d\n",-11 % -5); // -1
printf("%d\n",-11 % 5); // -1
return 0;
}

 占位符

• %a :⼗六进制浮点数,字⺟输出为⼩写。
• %A :⼗六进制浮点数,字⺟输出为⼤写。
• %c :字符。
• %d :⼗进制整数。
• %e :使⽤科学计数法的浮点数,指数部分的 e 为⼩写。
• %E :使⽤科学计数法的浮点数,指数部分的 E 为⼤写

• %i :整数,基本等同于 %d 。
• %f :⼩数(包含 float 类型和 double 类型)。
• %g :6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 e
为⼩写。
• %G :等同于 %g ,唯⼀的区别是指数部分的 E 为⼤写。
• %hd :⼗进制shortint类型。
• %ho :⼋进制shortint类型。
• %hx :⼗六进制shortint类型。
• %hu :unsignedshortint类型。
• %ld :⼗进制longint类型。
• %lo :⼋进制longint类型。
• %lx :⼗六进制longint类型。
• %lu :unsignedlongint类型。
• %lld :⼗进制longlongint类型。
• %llo :⼋进制longlongint类型。
• %llx :⼗六进制longlongint类型。
• %llu :unsignedlonglongint类型。
• %Le :科学计数法表⽰的longdouble类型浮点数。
• %Lf :longdouble类型浮点数。
• %n :已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中。
• %o :⼋进制整数。
• %p :指针。
• %s :字符串。
• %u :⽆符号整数(unsignedint)。
• %x :⼗六进制整数。
• %zd : size_t 类型。
• %% :输出⼀个百分号。

输出格式(限定宽度)

允许限定占位符的最⼩宽度

#include <stdio.h>
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
return 0;
}


//%5d 表⽰这个占位符的宽度⾄少为5位。如果不满5位,对应的值的前⾯会添加空格。输出的值默认是右对⻬,即输出内容前⾯会有空格;如果希望改成左对⻬,在输出内容后⾯添加空格,可以在占位符的 % 的后⾯插⼊⼀个-号


printf("%-5d\n", 123); // 输出为 "123 "

 对于⼩数,这个限定符会限制所有数字的最⼩显⽰宽度 

// 输出 " 123.450000"
#include <stdio.h>
int main()
{
printf("%12f\n", 123.45);
return 0;
}


//%12f 表⽰输出的浮点数最少要占据12位。由于⼩数的默认显⽰精度是⼩数点后6位,所以 123.45 输出结果的头部会添加2个空格

 显示正负号

printf() 不对正数显⽰ + 号,只对负数显⽰ - 号。如果想让正数也输出 + 号,可
以在占位符的 % 后⾯加⼀个 +

#include <stdio.h>
int main()
{
printf("%+d\n", 12); // 输出 +12
printf("%+d\n", -12); // 输出 -12
return 0;
}

 限定小数位数

⼩数点后⾯只保留两位,占位符可以写成 %.2f

最⼩宽度和⼩数位数这两个限定值,都可以⽤ * 代替,通过 printf() 的参数传⼊

#include <stdio.h>
int main()
{
printf("%*.*f\n", 6, 2, 0.5);
return 0;
}
// 等同于printf("%6.2f\n", 0.5);

输出部分字符串

%s 占位符⽤来输出字符串,默认是全部输出。如果只想输出开头的部分,可以⽤ %.[m]s 指定输出的⻓度,其中 [m] 代表⼀个数字,表⽰所要输出的⻓度(占位符 %.5s 表⽰只输出字符串“hello world”的前5个字符,即“hello”)

scanf

scanf() 处理数值占位符时,会⾃动过滤空⽩字符,包括空格、制表符、换⾏符等

⼀个或多个空格不影响 scanf() 解读数据
解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌
scanf() 的返回值是⼀个整数,表⽰成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回 0 。如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量EOF

占位符

• %c :字符
• %d :整数。
• %f : float 类型浮点数。
• %lf : double 类型浮点数。
• %Lf : long double 类型浮点数。
• %s :字符串。
• %[] :在⽅括号中指定⼀组匹配的字符(⽐如 %[0-9] ),遇到不在集合之中的字符,匹配将会停⽌。

上⾯所有占位符之中,除了 %c 以外,都会⾃动忽略起⾸的空⽩字符。 %c 不忽略空⽩字符,总是返回当前第⼀个字符,⽆论该字符是否为空格。
如果要强制跳过字符前的空⽩字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上⼀个空格,表⽰跳过零个或多个空⽩字符。
下⾯要特别说⼀下占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
因为 %s 不会包含空⽩字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也味着,scanf() 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。另外, scanf() 遇到 %s 占位符,会在字符串变量末尾存储⼀个空字符 \0 。
scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防⽌这种情况,使⽤ %s 占位符时,应该指定读⼊字符串的最⻓⻓度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表⽰读取符串的最⼤⻓度,后⾯的字符将被丢弃
 

赋值忽略符

#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
return 0;
}


//如果⽤⼾输⼊ 2020-01-01 ,就会正确解读出年、⽉、⽇。问题是⽤⼾可能输⼊其他格式,⽐如 2020/01/01 ,这种情况下, scanf() 解析数据就会失败

//只要把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃
//scanf("%d%*c%d%*c%d", &year, &month, &day);

分支语句

if语句

如果表达式的结果为真,则语句执行。


在C语言中如何表示真假?
0表示假,非0表示真。

语法结构:
if(表达式) 语句;
if(表达式) 
    语句1;
else
    语句2;


//多分支
if(表达式1)
    语句1;
else if(表达式2)
    语句2;
else
    语句3;


//如果条件成立,要执行多条语句
#include <stdio.h>
int main()
{
if(表达式)
{
语句列表1;
}
else
{
语句列表2;
}
return 0;
}
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("少年\n");
}
else if(age>=18 && age<30)
{
printf("青年\n");
}
else if(age>=30 && age<50)
{
printf("中年\n");
}
else if(age>=50 && age<80)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}

悬空else(else是和它离的最近的if匹配的)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)//当满足该条件才会进入下一个if语句
		if (b == 2)
			printf("hehe\n");
		else
			printf("haha\n");
	return 0;
}

//改进:加大括号
#include <stdio.h>
int main()
{
    int a = 0;
    int b = 2;
if(a == 1)
{
    if(b == 2)
    {
        printf("hehe\n");
    }
}
else
{
    printf("haha\n");
}
    return 0;
}

练习
1. 判断一个数是否为奇数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	size_t n = 0;
	scanf("%zd", &n);
	if (n % 2 == 0)
	{
		printf("%zd是偶数", n);
	}
	else
	{
		printf("%zd是奇数", n);
	}
}

2. 输出1-100之间的奇数 

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	for (int i = 1; i <= 100; i++)
	{
		if (i % 2 != 0)
		{
			printf("%d ", i);
		}
	}
}

switch语句

switch(整型表达式)
{
    case 整形常量表达式:
    语句;
}

break语句 的实际效果是把语句列表划分为不同的分支部分
在最后一个 case 语句的后面加上一条 break语句。
(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句)

不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,每个switch语句中只能出现一条default子句
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int day = 0;
	switch (day)
	{
		case 1:
			printf("星期一\n");
			break;
		case 2:
			printf("星期二\n");
			break;
		case 3:
			printf("星期三\n");
			break;
		case 4:
			printf("星期四\n");
			break;
		case 5:
			printf("星期五\n");
			break;
		case 6:
			printf("星期六\n");
			break;
		case 7:
			printf("星期天\n");
			break;
	}
	return 0;
}



//改进
//1. 输入1-5,输出的是“weekday”;
//2. 输入6-7,输出“weekend”

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int day = 0;
	switch (day)
	{
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
					printf("weekday\n");
					break;
				case 6:
				case 7:
					printf("weekend\n");
					break;
	}
	return 0;
}

循环语句


while

while(表达式)
循环语句;
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);//1 2 3 4 5 6 7 8 9 10
i = i+1;
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);//521

	while (n)
	{
		printf("%d ", n % 10);//1 2 5
		n = n / 10;
	}

	return 0;
}

while语句中的break和continue

break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的

continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值