栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言学习笔记

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言学习笔记

C语言学习笔记
  • 废话
  • hello world
    • 规范性
      • 写作格式
      • 命名
      • 注释
  • 变量与赋值
    • 简单类型
      • 数值型
      • 字符型
    • 运算符号说明
      • 赋值运算符
      • 算数运算符
      • 关系运算符
      • 逻辑运算符
  • 简单结构
    • 顺序结构
    • 分支结构
      • if~else
      • switch~case
    • 循环结构
      • while
      • for
      • do~while
      • break及continue
  • 数组
    • 一维数组
      • 创建及初始化
    • 二维数组
      • 创建及初始化
  • 指针
    • 一阶指针
      • 创建及初始化
      • 多变的*号
      • 指针的算术运算
      • 指针与数组
    • 二阶指针
      • 创建及初始化
  • 函数
    • 常用函数的介绍
    • 创建自己的函数
      • 函数调用
      • 形参与实参
  • 结语

废话 hello world

打开你的C语言编译器,输入以下代码,成为你的第一条代码。

#include
int main(void)
{
printf("hello world");
return 0;
}

其中以.h结尾的叫做头文件,我们一般用#include包含头文件。
main()为函数主体,int 为main函数的返回类型,若main前面没有指定返回类型,则默认为int,为了增强代码规范性,我们一般不省略。

#include
 main(void)···

void为main函数的输入类型,当输入类型为void时可省略。
printf()为头文件stdio.h定义的输出函数,在显示屏输出信息。
return 0中的0与main的返回类型int相对应都为整形。

规范性

一个大型程序的开发往往都是一个团队,代码良好的规范性就是两人之间交流的桥梁。规范的代码也可以帮助自己处理bug。

写作格式

1.缩进
缩进是最常用的调整格式的方法。合适的缩进可以展现代码的层次感,提高代码的可读性。
需要注意的是因为电脑的差异tab键产生的空格会不同,因此建议使用四个空格进行缩进。
2.大括号
在if、for等结构后有大量代码时,将代码用{}括起来。
不使用大括号

#include
int main()
{
	for(int i=0;i<5;i++)
		if(i==3)
			break;
		else
			printf("还不如用大括号n");
	return 0	
}

使用大括号

#include
int main()
{
   for(int i=0;i<5;i++)
   {
   	if(i==3)
   	{
   		break;
   	}
   	else
   	{
   		printf("有括号很明显for、if的作用范围n");
   	}
   }
   return 0;
}

当代码多起来的时候不用大括号很难判断for、if等语句的作用范围。

命名

C语言的标识符除了关键字,用户还可以自己定义。例如上面我们定义的i就是。自定义标识符要遵守以下几个规则才能被编译器识别,1.自定义标识符只能由英文字母、阿拉伯数字、下划线_组成。2.自定义标识符不能与C语言提供的关键字相重复。3.自定义标识符一般不超过32个字符。
建议自定义标识符能见字知意,例如show_all_info表示"show all infomation"展示所有的信息。

注释

良好的注释往往可以提高程序的可读性,是沟通的桥梁,因此注释是非常有必要的。
在C语言中,单行注释使用"//“,多行注释使用”",例如

#include

int main()
{
	for(int i=0;i<5;i++)
	{
		if(i==3)//如果i等于3,则执行break语句
		{
			break;
		}
		else
		{
			printf("有括号很明显for、if的作用范围n");
		}
	}
	return 0;
}

需要注意的是注释在代码编译的时候,编译器会自动略过,对程序不产生影响。

变量与赋值

在C语言中包括常量如1、2、3、'ch’等,我们无法改变。还包括变量,例如上面的i就是变量,它的值随着程序的运行从0变到5。

简单类型 数值型

用于储存数值的变量即为数值型变量,不同数值类型由不同的关键字定义,其能储存的数值范围也不同,自然其储存占用的空间也不同。

数据类型类型标识符占用内存/B数值范围
有符号短整型[signed] short [int]2 − 2 15 ∼ 2 15 − 1 -2^{15} {}sim 2^{15}-1 −215∼215−1
有符号整型[signed] [int]4 − 2 31 ∼ 2 31 − 1 -2^{31}sim2^{31}-1 −231∼231−1
有符号长整型[signed] long [int]4 − 2 31 ∼ 2 31 − 1 -2^{31}sim2^{31}-1 −231∼231−1
无符号短整型unsigned short [int]2 0 ∼ 2 16 − 1 0sim 2^{16}-1 0∼216−1
无符号整形unsigned int4 0 ∼ 2 32 − 1 0sim 2^{32}-1 0∼232−1
无符号长整型unsigned long [int]4 0 ∼ 2 32 − 1 0sim 2^{32}-1 0∼232−1
单精度浮点float4 − 2 38 ∼ 2 38 − 1 -2^{38}sim 2^{38}-1 −238∼238−1
双精度浮点double8 − 2 308 ∼ 2 308 − 1 -2^{308}sim 2^{308}-1 −2308∼2308−1

备注:float的有效位是7,double的有效位是16
特别要注意的是当数值不在所定义的类型的范围的时候,会发生数据溢出的情况,此时编译器不会报错。

#include
int main()
{
	short a=32768;//short的范围为-32768~32767
	short b=32769;
	printf("a=%d,b=%d",a,b);//本应该为32768,32769的,但结果不是。可以推断出C语言的计数方式是循环的。
	return 0;
}

结果如下

字符型

1.字符型常量与字符串常量

顾名思义,一个字符的为字符型常量,多个字符的为字符串常量
字符型常量:‘x’,‘X’,’ ',‘0’等用’'引起来的以及转义字符序列n等
字符串常量:“nwafu"等用”"引起来的
以下为转义字符序列及其功能

转义字符功能转义字符功能
b退格\反斜线字符
f换页’单引号字符
n换行"双引号字符
r回车ddd1~3位八进制数表示的字符
t水平跳格xdd1或2位十六进制树表示的字符

2.字符型变量

使用关键字char创建字符型变量和字符串变量,在C语言中,用字符变量储存字符型常量,用字符数组储存字符串变量。

#include
int main()
{
	char a='o';//创建字符变量储存字符型常量
	char b[]="nwafu";//创建字符数组储存字符串常量
	printf("%ct%s",a,b);
	return 0;
}
运算符号说明 赋值运算符

赋值运算符为“ = = =”,还有许多复合赋值符——算术运算符与等号结合,例如 a + = b a+=b a+=b与 a = a + b a=a+b a=a+b的效果一致,其他复合赋值符作用以此类推。使用复合赋值付可以使代码更紧凑。需注意赋值符的左边只能是变量,不能为常量。
当赋值符号左右两边变量的类型不同时,会强制转化为符号左侧变量的类型
例如:想将double类型的b赋值给int型的a,得到的将会是int型

#include
int main()
{
	int a=10;
	double b=10.0;
	a=b;
	printf("%lf",a);
	return 0;
}

其结果为0.000000,当printf的输出类型为%d时,结果为10。

算数运算符

算数运算符包括“ + + +”、“ − - −”、“ ∗ * ∗”、“ / / /”。
需注意的是当不同数值型变量进行运算时,会进行隐形的强制类型转换:
char、short → rightarrow →int → rightarrow →unsigned → rightarrow →long → rightarrow →float → rightarrow →double。
例如下面的例子,将int型的变量a与double型的变量b相加并打印,我们比较不同的输出格式对结果的影响。

#include
int main()
{
	int a=10;
	double b=10.0;
	printf("%d",a+b);
	return 0;
}

其结果是0;
但当printf处的输出格式为%lf时,其结果为20.000000。

关系运算符

关系运算符有 < < <、 > > > = = == ==、 ! = != !=、 < = <= <=、 > = >= >=,用于比较数的大小。

逻辑运算符

逻辑运算符有“ ! ! !”、“ ∣ ∣ || ∣∣”、“ & & && &&”,其含义分别为非、或、且,他们的含义都比较简单。
注意当多个关系运算符复合使用时,需添加“()”改变运算顺序。
例如:你想表达1小于2小于,那么他的代码应该是1<2&&2<3而不应该是1<2<3

简单结构 顺序结构 分支结构 if~else

if ∼ sim ∼else的基本用法为if(表达式)语句;当表达式的值不为0时执行语句,当表达式的值为0时,不执行该语句。
例如:

if(1<2)a=1;

此处的表达式为 1 < 2 1<2 1<2,语句为 a = 2 a=2 a=2,此时 1 < 2 1<2 1<2的值为真即 1 < 2 1<2 1<2的值为1,故执行语句 a = 1 a=1 a=1。
需注意if及下面将要介绍的while等结构后的语句表示if后第一个“;”前的语句,若想执行多条语句,则需要使用“{}”构成复合语句。
例如:

#include
int main()
{
	int a=0;
	int b=0;
	if(1>2)a=1;b=2;
	printf("%dn%d",a,b);
	return 0;	
}

我们想如果 1 > 2 1>2 1>2,那么a=1,b=2;否则a=0,b=0。然而结果是a=0,b=2;原因是当if的表达式为0时,不执行a=1。然后if语句结束。即无论if中的表达式为何值,都会执行b=2;如果想实现“如果 1 > 2 1>2 1>2,那么a=1,b=2;否则a=0,b=0。”那么代码应该改为

if(1>2){a=1;b=2;}

形成复合语句。
多分支选择结构
if(表达式1)语句1;
if(表达式2)语句2;
if(表达式3)语句3;
… dots …
多分支选择结构除了以上表达方式,还可以用接下来要介绍的swith ∼ sim ∼case结构。

switch~case

其常见结构如下,可以较方便的实现多分枝选择结构

swith(表达式)
{
	case 常量表达式1:语句1;
	case 常量表达式2:语句2;
	case 常量表达式3:语句3;
	...
	case 常量表达式n:语句n;
	default:语句n+1
}

使用swith ∼ sim ∼case需注意的是swith(表达式)中的表达式类型只能是int。
其执行顺序:从第一个case分别比对,若case的常量与表达式相同,则执行对应语句,直到遇到break,否则跳过该语句,进行下一个case的比对。直至所有case完成比对。
case后的常量表达式不能用来进行比较。
default可以放在任意位置,但我们习惯上放在最后

#include
int main()
{
	int x=3;//x为int型
	switch(x)
	{
		case 1:printf("x=1");//分别比对1,2,跳过
		default:printf("I don't know x");//将default放在任意位置都可以
		case 2:printf("x=2");
		case 3:printf("x=3");break;//比对x,相等,打印出x=3,在遇到break时跳出switch~case结构
	}
	return 0;
}
循环结构 while

while的原型while(表达式)循环体;
当表达式为真进入循环体,表达式为假跳过循环体。与if类似,循环体是while后第一个";“前的句子,若想执行多个语句,可以使用一个”{}"构成复合语句。

#include
int main()
{
	while(2<3)//对表达式进行判断,为真,进入循环体,循环体由复合语句
	//循环体由两个句子组成复合语句
	{
		printf("2<3");
		printf("It is right");
	}
	return 0;
}
for

原型:for(表达式1;表达式2;表达式3)循环体;
表达式1通常为循环变量的初始化,表达式2通常用于判断是否进入循环体,表达式3通常用于循环变量的运算。
先执行表达式1,然后执行表达式2,若表达式2为真,则进入并执行循环体,然后再执行表达式3,若表达式2为假则跳过循环体。
for的3个表达式都可以省略,但表达式之间的";"不可以省略。

#include
int main()
{
	for(int i=0;i<3;i++)//对循环变量i进行初始化,并判断i是否小于3,最后对i进行自增处理
	{
		printf("%d",i);
	}
	return 0;
}

使用如下代码也可实现上面的功能

#include
int main()
{
	int i=0;//循环变量的初始化
	for(;;)
	{
		printf("%d",i);
		if(i>=2)break;//判断i是否小于3
		i++;//循环变量的自增处理
	}
	return 0;
}

但第二种表达方式我们不常用,它没有第一种紧凑、直观。

do~while

原型:do{循环体}while(表达式);
do~while是先执行一次循环体再进行表达式的判断,表达式为真则再次进入循环体,否则跳过循环体。
需注意while后的";"不可省略。

break及continue 数组

数组是包含多个数据的有序(位序)的集合。也就是说将一些类型相同的数据排成排放在储存空间中。

一维数组 创建及初始化

数组的创建与变量相同,例如int arr[5];char str[5];分别创建了一个储存int变量的数组和char变量的数组。
数组的初始化与变量也有相同之处,例如int arr[5]={1,2,3,4,5};数组的初始化是将初始化的内容放在{}中并用","分隔。当{}中的个数大于数组大小时,编译器会报错,当{}中的个数小于数组大小时,将{}中的值赋给数组前面的,其余补成0或对应空值。
数组的命名与上面介绍的变量的命名是一样的

#include
int main()
{
	int arr[5]={1,2,3};
	//{}内个数小于数组大小,仅对前面几个进行初始化即arr[0]=1,arr[1]=2,arr[2]=3;
	//其余都初始化为0,即arr[3]=0,arr[4]=0;
	for(int i=0;i<5;i++)printf("%d",arr[i]);
	return 0;
}

数组的引用:我们用数组名[下标]对数组进行引用,如上面代码中的arr[0],arr[1]。

二维数组 创建及初始化

二维数组是在一维数组的基础上多加了一维。二维数组的创建及初始化与一位数组相类似,例如int arr[4][4];char str[4][4]分别创建了横纵都为4的数组分别储存着int,char类型的数据。
int arr[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; char str[4][4]={"how","are","you"};
二维数组的初始化与一位数组也类似,当{}内个数大于数组大小时,编译器将会报错,当{}内个数小于数组大小时,其余都被赋0或对应空值。

指针

在前面申明一个变量时,每个变量都会在内存中申请一个地址用于储存变量。在C语言中我们用指针去储存变量的地址。

一阶指针 创建及初始化

原型:数据类型 *指针变量名;
例如int *p=NULL;创建了一个名为p的int型的指针。
指针的初始化:int a=0;int *pa=&a;对指针pa进行初始化,将a的地址赋给pa。其中的&为寻址符号。
在我们刚学C语言时,指针往往难以理解,其实我们可以将变量比作酒店的房间,指针就是房间的门牌号,是一个储存房间位置的变量。

多变的*号

在数值运算时*号是数学中乘的含义,在指针创建时是指针标志的含义。
*还有一个含义是间接寻址运算符,int a=0,*pa;pa=&a;创建并初始化指针pa,对指针pa进行间接寻址运算*pa=2;其作用与a=2是一样的。

指针的算术运算

在上面我们介绍了数组,其实数组名就储存着这个数组第一个变量的地址。

int arr[5]={1,2,3},*pa_begin,*pa_end;//数组、指针的创建
pa_begin=arr,pa_end=&arr[4];//将数组第一个位置赋给pa_begin,将数组最后一个位置赋给pa_end。
//我们也可以用pa_end=pa_begin+5将数组最后一个位置赋给pa_end。

C语言支持指针相减的,如pa_end-pa_begin其表示pa_begin到pa_end之间有多少个数。

指针与数组

在数组部分我们用下标的方式对数组进行引用,其实我们也可以用指针的方式对数组进行引用。

#include
int main()
{
	int arr[5]={1,2,3},*pa;
	pa=arr;
	*(pa+1)=2;//对数组arr[1]赋值2;
	printf("%d",arr[1]);
}
二阶指针 创建及初始化

原型:数据类型**指针名
例如int**ip,char**cp。分别创建了一个名为ip,类型为int和一个名为cp,类型为char的二阶指针。
初始化方式为:

int a=10;
int *p=&a;
int **ip=&p;

他们用于存储一个指针的地址,当然此处的&a可以为取一个一维数组名的地址。

函数 常用函数的介绍

函数由函数名、函数返回类型、传入参数、函数体,返回值,五部分组成,函数可以帮助我们将有特殊功能需重复使用的代码进行封装,以提高代码的高效使用。在一开始我们就已经学习了一个不可或缺的函数——main函数,我们第一个程序就是由main函数实现的。

#include
int main()
{
	printf("hello world");
	return 0;
}

其中main为函数名,int为函数返回类型,()内的为传入参数,此处传入空,printf(...)为函数体,returnn 0为返回值。
我们在前面已经学习了的printf(),scanf()等函数均为前人为了方便使用已经封装好的函数,并将其储存在在stdio.h头文件中,我们仅需要了解该函数怎么用、有什么用就可以了,不必要理解它具体是怎么实现的。

创建自己的函数

在开发程序过程中,靠前人写好的函数是不够的,往往需要我们根据具体问题编写具体的函数。
函数的原型:

数据类型 函数名(传入参数)
{
	函数体
	[return 返回值]
}

我们创建一个以下简单函数

void swap(int a,int b)//用于将a,b的值进行交换
{
	int c;
	c=a,a=b,b=c;
}

该函数的作用为将两个int型的数据相加并返回。
需注意的是return返回值的类型必须与函数返回类型一致。

函数调用

调用自己写的函数与调用printf函数是差不多的。

#include
int main()
{
	int a=10,b=5;
	swap(a,b);//使用c接受a+b的返回值。
	printf("a=%d,b=%d",a,b);
	return 0;
}
形参与实参

我们考虑如下两个函数的不同。

void swap1(int a,int b)
{
	int c;
	c=a,a=b,b=c;
}
void  swap2(int *a,int *b)
{
	int *c;
	c=a,a=b,b=c;
}

很明显我们从形式上看就发现swap1传入两个int值,swap2传入两个int值的地址。我们将代码运行发现,swap1并未将a,b的值进行交换,而swap2则将a,b的值进行了一个交换。
其中的原因很简单,swap1函数出入的为形参,仅仅将a,b的值在swap1函数作用范围内将值进行了交换,而swap2函数是将a,b的地址传入,我们是将a,b的地址进行了交换。

结语

以上简单的仅介绍了C语言的基础内容,C语言的内容远不及这些,在学完以上内容后,希望大家继续在C语言领域深耕学习更高阶的内容。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/928046.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号