# C语言学习 **Repository Path**: l-ewis/c-language-learning ## Basic Information - **Project Name**: C语言学习 - **Description**: 转专业自学的C语言 根据mooc上翁恺老师的《程序设计入门——C语言》 url:https://www.icourse163.org/course/ZJU-199001?from=searchPage&outVendor=zw_mooc_pcssjg_ 其中有我根据课内的代码,以及我自己做的笔记 定期做更新,直到学完为止 - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-12-03 - **Last Updated**: 2023-04-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 185.199.109.133 raw.githubusercontent.com 185.199.110.133 raw.githubusercontent.com 199.232.28.133 raw.githubusercontent.com # 1、数据类型 ```c++ char //字符数据类型 short //短整型 int //整型 long //长整型 long long //更长的整型 float //单精度浮点数 double //双精度浮点数 #include int main() { //字符类型 char ch = "a"; //整型 int age = 10; //单精度浮点数 float num = 0.1 return 0 } ``` ```c++ #include int main() { printf("%d", sizeof(char))//打印整型的所占空间大小 } //sizeof 计算类型或者变量所占空间的大小 //在C语言中sizeof(long) >= sizeof(int) ``` ### 计算机中的单位: - bit - 比特位 ​ 计算机中识别二进制: 1、0,其中1和0占一个bit - byte - 字节 = 8bit - KB -1024 byte - MB - 1024 KB - GB - 1024 MB - TB -1024 GB - PB - 1024 TB # 2、常量变量 ### 常量 - 不能改变的量 ### 变量 - 能被改变的量 - <类型名称><变量名称>; - 变量的名字是一种标识符,标识符只能由字母、数字、下划线组成 - 数字不可以出现在第一个位置上 - C语言的关键之,不能用作标识符 ```c++ #include int main() { //创建一个变量 //类型 变量的名字 = 0 int age = 20; double weight = 75.3; age = age + 1 weight = weight -10 printf("%d", age); printf("%lf", weight); return 0; } ``` ### 格式化: //%d - 整型 //%f - float //%lf - double - 变量的分类 ```c int main() { int a = 10;//局部变量 - {}内被定义的 } a = 100 //全局变量 - {}外部被定义的 //当局部变量和全局变量名字冲突的情况下,局部优先 //不建议把全局变量和局部变量的名字写成一样 ``` //scanf()函数是一个输入函数 - const:const 是一个修饰符,加在int的前面,用来给这个变量加上一个const(不变的)的属性。这个const一旦初始化,就不能在进行改变了。 - int change = AMOUNT - price # 3、运算符 ![image-20221201194446924](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20221201194446924.png) - 在C语言中赋值”=“是一个运算符 - 赋值也是运算,也有结果 - a = 6,也是被赋值 - a = b = 6 ----> a = (b=6) 自又向左 # 4、交换变量 - 当我们需要交换两个变量的值的时候需要用一个新的量给其中的一个变量储存数据 ```c int a = 10; int b = 1; int t; a = t; a = b; b =t; ``` # 5、复合赋值 - 五个运算符中,+-*/%可以和=结合起来使用形成复合运算符:例如+= - total += 10 - total = total + 10 - 两个运算符中间不要有空格 - 递增递减运算符 - ++,--,就是给这个变量+1或者-1 - count++ - count += 1 - ++和-- 可以放在变量的前面,叫做前缀形式,放在后面叫做后缀形式 - a++以后是a以前的值,++a是a以后的值,无论是哪一个a都加一了 ![image-20221201203808133](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20221201203808133.png) ```c #include int main() { int a ; a = 10; printf("a++= %d\n",a++); printf("%d\n", a); printf("++a= %d\n",++a); printf("%d\n", a); return 0; } ``` # 6、判断语句 ```c if(条件成立){ ... } ``` C语言提供了六个关系运算符: - == 相等 - != 不相等 - \> 大于 - \>= 大于或等于 - < 小于 - <= 小于或等于 True = 1;False = 0 - 所有的关系运算符比算术运算符低,但是比赋值运算符高 - 判断时候相等和不等的优先级比其他的都低,连续的运算关系是从左到右进行的 - 5>4>3 # 7、循环语句 ### while while(条件){ ​ ... } - 当条件满足时,会不断的重复语句 - 循环体执行前会判断是否可以继续循环 ### do - while do{ ​ <循环体语句> }while(<循环条件>); ![image-20221202150602430](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20221202150602430.png) ps: 左是do- while循环体 右是while循环 ### for循环 - for循环像一个计数循环:设定一个计数器,初始化它,当计数器达到某一个值之前,重复执行循环体,每执行一轮循环,计数器以一定步骤进行调整,比如I++或i-- - for(count=10;count>0;count--) - 读成:”对于一开始的count=10,当count>0时,重复做循环体,每一轮循环在昨晚循环体内语句后,使得count--" - 当我们要做求和的程序时,记录结果的变量应该初始化为0,而做求积的变量时,记录结果的初始化为1 所有的for循环都可以改成while循环 - for(;条件;) == while(条件) Tips for loops: - 如果有固定次数,用for循环 - 如果必须执行一次,用do_while循环 - 其他情况用while # 8、逻辑类型 ### bool - #include - 之后就可以使用bool和true、false ```c #include #include int main(){ bool b = 6>5; bool t = true; t = 2; printf("%d\n",b);//没有特别的方式输出布尔量 } ``` ### 逻辑运算 - 逻辑运算是对逻辑运算符进行运算,结果只有0和1 - 逻辑量是关系运算或逻辑运算的结果 ![image-20221204040812227](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20221204040812227.png) Tips: - 如果再c语言之中需要表达4x && x <6 ,因为x<4的逻辑值只能是1和0,当其比较时是自左向右的 - 当我们要判断一个字母的大小写,需要用 c>= "A" && c<="Z" ### 逻辑运算符的优先级 - !> && > ||![image-20221204041846703](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20221204041846703.png) ### 短路 - 逻辑运算是自左向右的,如果左边的运算已经可以决定结果,就不会做右边的计算 - a ==6 && b += 1 - 对于&&,左边是false时就不做右边的 - 对于||,左边是true就不做右边的 ### 条件运算符 - count = (count > 20)? count -10 : count+ 10 - 条件满足时和不满足时的值 ```c if (count > 20){ count -= 10 }else{ count += 10 } ``` - 条件运算符的优先级高于赋值运算符,但是低于其他的运算符 # 9、级联和嵌套的判断 ### 嵌套的判断 - 当if的条件满足或者不满足的时候要执行的语句也可以时一条if或if-else语句,这就是嵌套的if语句 ```c if(code == READY) if (count < 20){ printf("一切正常") } else{ printf("继续等待") } ``` ### else的匹配 - else总是和最近的那个if匹配 - 但是如果在"}"的外面,则要小心 tips: - 在使用if和else时候搭配{}使用 - 即使在只有一条执行语句的时候 ### 级联的if-else if ```c if(exp1) { str1; }else if (exp2){ str2; }else{ str3; } ``` 当写级联的时候最好使用单一出口 # 10、多支分路 ### switch-case ```c switch(type){ case 常量: 语句 ... default: 语句 ... } ``` - 控制表达式的只能是整数型的结果 - 常量可以是常数,也可以是常数计算的表达式 - switch语句可以看作一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的case(分支标号)处。分支标号只能说明switch内部的位置的路标,在执行完分支中的最后一句话,如果后面没有break,就会顺序执行刀下面的case里面去,直到遇见一个break或者switch结束为止 # 11、循环计算 计算前先保存原始的值,后面可能有用 tips: - 如果模拟循环运行一个很大次数的循环,可以模拟较少的循环次数,然后做出判断 ### 随机数 - 每次召唤rand()就得到一个随机的整数 - x % n 的结果就是得到一个[0, n-1]的整数 标准库定义了一组随机数的引擎类和适配器,使用不同数字方法生成伪随机数。标准库还定义了一组分布模板,更具不同的概率生成随机数。标准库还定义了一组分布模板,更具不同的概率随机生成随机数。 - srand(time(0));//先设置随机种子 - rand();//然后随机产生随机数 srand是种下随机种子数,每回种下的种子不一样,用rand得到的随机数就不一样,time(0)就是得到当前的时间值 ```c #include #include #include void mian(void){ int i; srand(time(0)) //输出10个随机数 for (i = 0;i<10;i++){ printf("%6d\n",rand()) } } ``` # 12、整数的分解 - 一个整数是由1至多位数组成的,如何分解出整数的各个位上的数字,然后加以计算 - 对一个整数做%10的操作,就可以得到他的个位数 - 在对其/10的操作,就可以去除他的个位数 - 然后在对其做%10,就得到原来的十位数了 - 以此类推 # 13、循环控制 - break - continue - 只能对它所在的那层循环去做 # 14、循环的嵌套 - 循环里面还是循环 ### 从嵌套的循环中跳出: ```c //如何用1角,2角,5角以下的硬币凑出10元以下的金额 #include #include int main() { int exit = 0; int x,y,z; int num; printf("请输入金额"); scanf("%d",&num); for (x=1 ; x < 10*num ;x++){ for (y=1 ; y < 10*num / 2; y++){ for (z=1; z < 10*num / 5;z++){ if (x + 2*y + 5*z==10*num){ printf("可以凑出由%d个1角,%d个2角,%d个五角构成%d元\n",x,y,z,num); exit = 1; break; } }if (exit ==1 ) break; }if (exit == 1) break; } system("pause"); return 0; } ``` // 接力break ### goto - 当我们在多重循环中需要跳出所有的循环时就要用到goto goto ..; out: - goto不要乱用,不利于后期的延展 # 15、数组 ### 定义数组 - <类型>变量名称[元素数量]; - int grades [100]; - double weight[20]; - 元素数量必须是整数 - C99之前:元素数量必须是编译时刻确定的字面量 数组是一种容器,特点是: - 所有的元素具有相同的数据类型; - 一旦创建不能改变大小 - 数组中的元素在内存中是连续一次排列的 ### 数组的单元 - grades[0] - 使用数组时放在[]中的数字叫做下标或者索引,下标从0开始计数 ### 二维数组 - int a[3] [5]; - a是一个三行五列的矩阵![image-20230220232945366](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20230220232945366.png) #### 二维数组的初始化 ```c int a[ ] [5] = { {0,1,2,3,4,5}, {2,3,4,5,6}, }; ``` - 列数必须给出,行数可以由编译器来数 - 每行一个{},逗号分隔 - 最后的逗号可以存在 ## 数组的初始化 ```c int a[]={2,3,4,6,7,11}; ``` - 直接用大括号给出数组的所有元素初始值 - 不需要给出数组的大小,编译器替你数 ## 集成初始化时的定位 ```c int a[10] = { [0] = 2, [2] = 1, 7, } ``` - 在[n]在初始值数据中给出定位 - 没有定位的数据接在前面的位置后面 - 其他位置的值补零 - 可以不给出数组的大小,让编译器算 - 适合初始数据稀疏的数组 ## 数组的大小 - sizeof给出整个数组所占据的大小,单位是字节 - sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数: ​ sizeof(a) / sizeof(a[0]) - 这样的代码,一旦修改数据中的初始数据,就不需要修改遍历的代码 ## 数组的赋值 int a[ ]={2,4,6,7,1,32}; int b[ ]=a; 在数组中不可以这样赋值 - 数组变量本身不能被赋值 - 要把一个数组的所有元素交给另一个数组,必须采用遍历 当数组作为函数参数时,往往必须在用另一个函数来传入数组大小 - 不能在[ ]中给出大小 - 不能再用sizeof来计算数组的元素个数 ## 数组的循环 - 通常都是使用for循环,让循环变量i从0到<数组长度,这样循环体内最大的i正好是数组最大的有效下标 # 16、函数的定义与使用 - 函数是一块代码,接收零个或者多个参数,做一件事情,并返回零个或者一个值 - 函数名(参数值) - ()起到了表示函数调用的重要作用 - 即使没有参数也需要加() ### 函数中的返回值 - return停止函数的执行,并返回一个值 - return 表达式; - return; 一个函数可以用多个return,但是不符合单一出口原则 ### 没有返回值的函数 - void 函数名(参数表) - 不能使用带值的return - 可以没有return - 调用的时候不能返回值的赋值 ### 函数的前后关系 - C的编译器自上而下分析你的代码 ### 函数原型 - 函数头,以分号“;”结尾,就构成了函数原型 - 函数原型的目的是告诉编译器这个函数长什么样子 - 名称 - 参数(数量和类型) - 返回类型 ### 调用函数 - 如果函数有参数,调用函数时必须传递给他数量、类型正确的值 - 可以传递给函数的值时表达式的结果,包括: - 字面量 - 变量 - 函数的返回值 - 计算结果 ### 函数传值 C语言在调用函数时,永远只能传值给函数 - 每个函数有自己的变量空间,参数也位于这个独立的空间中,和其他函数没有关系 - 在函数参数表里的参数为“形参”,调用函数给的值为“实参” ### 本地变量 局部变量 - 函数的每次运行,就产生了一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的,称作本地变量 - 定义在函数内部的变量就是本地变量 - 参数也是本地变量 ### 变量的生存期和作用域 - 生存期:什么时候这个变量开始出现了,到什么时候他就消亡了 - 作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以起作用) - 对于本地变量,这两个问题的答案是统一的:大括号内——块 ### 本地变量的规则 - 本地变量是定义在块内的 - 它可以是定义在函数块内 - 也可以定义在语句的块内 C语言不允许函数嵌套定义 # 17、二分查找 ![image-20230221233601554](C:\Users\Lazzy\AppData\Roaming\Typora\typora-user-images\image-20230221233601554.png)