资讯详情

《C语言速成》

目录

C课前准备语言课程

养成写博客的习惯

github的重要性

一些有假装能力的工具

如何学好C语言?

初识C语言

本章目标:

本章重点:

C语言是什么?

第一个C语言程序

数据类型

变量、常量

字符串 转义字符 注释

选择语句

循环语句

函数

数组

操作符

指针

结构体

分支语句和循环语句

什么是句子?

分支语句(结构选择)

if语句

悬空else

switch语句

循环语句

while循环

for循环

do...while()循环

半查找算法

二分搜索函数:

实现猜数字游戏

goto语句

函数

什么是函数?

库函数:

自定义函数-toc" style="margin-left:80px;">自定义函数

函数的参数

函数的调用

嵌套调用函数和链接访问

声明和定义函数

函数递归

数组

创建和初始化一维数组

使用一维数组

一维数组在内存中的存储

 二维数组的创建和初始化

二维数组的使用

二维数组在内存中的存储

数组作为函数参数

冒泡排序函数的正确设计

C语言实现三子棋

C语言实现一个经典扫雷小游戏

一次性搞定解析GitHub

github是什么?

为什么选择GitHub?

GitHub使用手册

操作符详解

各种操作符的介绍

表达式求值

 指针

指针是什么?

指针和指针类型

野指针

指针运算

指针和数组

二级指针 

指针数组

结构体

结构体的声明

结构体变量的定义和初始化

结构体成员的访问

结构体传参

实用调试技巧

什么是bug?​

调试是什么?有多重要?

Debug和Release的介绍

windows环境调试介绍

最常使用的几个快捷键:

一些调试的实例

如何写出好(易于调试)的代码

编程常见的错误

数据的存储目录

数据类型介绍

整形在内存中的存储:原码、反码、补码

大小端字节序介绍及判断

char相关知识

七道例题加深char理解

浮点型在内存中的存储

指针的进阶目录

字符指针

指针数组

数组指针

数组参数、指针参数

函数指针

函数指针数组

回调函数

冒泡排序

qsort-快速排序任意类型的数据

指针和数组笔试题解析

指针笔试题

赛马问题:36匹马,6个跑道,没有计时器,请赛马确定36匹马的前三名

烧香问题 有一种香材质不均匀,但是每一根这样的香,烧完恰好1小时 给两根香,帮我确定15分钟的时间

字符函数和字符串函数

字符串求长度

strlen字符串求长度

长度不受限制的字符串函数

strcpy字符串拷贝

strcat字符串追加

strcmp字符串比较

长度受限制的字符串函数介绍

strncpy指定个数的字符串拷贝

strncat指定个数的字符串追加

strncmp指定长度的字符串比较

字符串查找

strstr字符串查找

strtok字符串删除分隔符函数

错误信息报告

strerror翻译错误码的函数

字符分类函数

字符转化函数:

内存操作函数

memcpy不重叠内存拷贝

memmove重叠内存拷贝

memcmp内存比较函数

memset内存设置函数

动态内存管理

为什么存在动态内存分配

动态内存函数的介绍

malloc动态内存开辟函数

free动态内存的释放回收函数

calloc动态内存开辟数组函数

realloc调整开辟动态内存大小函数

 常见的动态内存错误

几个经典的笔试题

C/C++程序内存分配的几个区域:

柔性数组-C99

自定义类型:结构体,枚举,联合

结构体

结构的自引用

结构体变量初始化

结构体内存对齐

结构体传参

位段

枚举    即为一 一列举

 联合(共用体)

C语言文件操作

本章重点

什么是文件

文件名

文件类型

 ​​文件缓冲区

文件指针

文件的打开和关闭

文件的顺序读写

文件的随机读写

fseek 根据文件指针的位置和偏移量来定位文件指针

文件结束判定

程序的编译(预处理操作)+链接

程序环境和预处理

本章重点:

程序的翻译环境和执行环境

图解编译+链接

详解编译+链接

翻译环境

运行环境

预处理详解

预定义符号

预处理指令

#define定义标识符

#define 定义宏

#define 替换规则

#和##

带副作用的宏参数

宏和函数对比

命令行定义

条件编译

常见的条件编译指令:

文件包含

<---- To Be Continued


C语言课程课前准备

养成写博客的习惯

博客的重要性: 1. 自己写博客,是对所学知识的总结 2. 写博客可以记录你学习的一个过程和心得,给面试官更多了解你的机会,同时增加面试的谈资。 3. 写博客说明你是一个愿意分享的人。 CSDN 博客园 51CTO-比较推荐 开源中国 自己搭建(服务器+域名; github博客)

https://github.com/ 1. 大公司喜欢的东西 2. 了解git --->我是教程 3. 下去先了解,再注册一下github账号

一些有逼格的工具

印象笔记(有道云笔记)-笔记可以检索,笔记丢不了,随时随地方便复习。 xmind-思维导图,整理一门课程学完后的框架。

如何学好C语言

1.鼓励你,为你叫好。

C生万物 编程之本 长远IT职业发展的首选 C语言是母体语言,是人机交互接近底层的桥梁 学会C/C++,相当于 掌握技术核心 知识点一竿子打通。 IT行业,一般每10年就有一次变革 40年间,在TIOBE 排行榜中,C/C++位 置长期霸占前三名,没有丝毫撼动,可谓经典永不过时!

2.学习不能叫苦叫累,抱怨没时间 欲戴王冠,必承其重。 如果你总是和别人走一样的路怎么才能保证超越别人,那就得付出不一样的努力。 时间就像乳沟,只要你肯挤,就一定会有

3.拒绝做伸手党 遇到问题,先尝试自己解决

4.学好编程,不仅仅是学好C语言 必须要学好: 语言、算法和数据结构、系统调用(操作系统)和计算机网络。 学习语言: 选择一门好的语言,深入学习,完成所有的课后作业。 学习算法、数据结构: 课堂上一定注意听讲,下课注重实践。 学习操作系统和网络 课堂认真听讲+课后实践+看几本好书。

初识C语言

本章目标:

基本了解C语言的基础知识,对C语言有一个大概的认识。 每个知识点就是简单认识,不做详细讲解,后期课程都会细讲。

本章重点:

什么是C语言 第一个C语言程序 数据类型 变量、常量 字符串+转义字符+注释 选择语句 循环语句 函数 数组 操作符 常见关键字 define 定义常量和宏 指针 结构体

什么是C语言?

C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程 语言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及 超级电脑等作业平台。 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8 日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标 准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉 字编程。 C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。

第一个C语言程序

#include <stdio.h>

int main()
{
   printf("hello bit\n");
   printf("he he\n");
   return 0;
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个

数据类型

char        //字符数据类型 short       //短整型 int         //整形 long        //长整型 long long   //更长的整形 float       //单精度浮点数 double      //双精度浮点数 //C语言有没有字符串类型?

为什么出现这么的类型? 每种类型的大小是多少?

#include <stdio.h>
int main()
{
   printf("%d\n", sizeof(char));
   printf("%d\n", sizeof(short));
   printf("%d\n", sizeof(int));
   printf("%d\n", sizeof(long));
   printf("%d\n", sizeof(long long));
   printf("%d\n", sizeof(float));
   printf("%d\n", sizeof(double));
   printf("%d\n", sizeof(long double));
   return 0;
}

注意:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。 类型的使用:

char ch = 'w'; int weight = 120; int salary = 20000;

变量、常量

生活中的有些值是不变的(比如:圆周率,性别(?),身份证号码,血型等等) 有些值是可变的(比如:年龄,体重,薪资)。 不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。

定义变量的方法

int age = 150; float weight = 45.5f; char ch = 'w';

局部变量 全局变量

#include <stdio.h>

int global = 2019;//全局变量
int main()
{
   int local = 2018;//局部变量
   //下面定义的global会不会有问题?
   int global = 2020;//局部变量
   printf("global = %d\n", global);
   return 0;
}

上面的局部变量global变量的定义其实没有什么问题的! 当局部变量和全局变量同名的时候,局部变量优先使用。

 

#include <stdio.h>
int main()
{
   int num1 = 0;
   int num2 = 0;
   int sum = 0;
   printf("输入两个操作数:>");
   scanf("%d %d", &a, &b);
   sum = num1 + num2;
   printf("sum = %d\n", sum);
   return 0;
}
//这里介绍一下输入,输出语句
//scanf
//printf

作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的 而限定这个名字的可用性的代码范围就是这个名字的作用域。 1. 局部变量的作用域是变量所在的局部范围。 2. 全局变量的作用域是整个工程。

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段 1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。 2. 全局变量的生命周期是:整个程序的生命周期。

C语言中的常量和变量的定义的形式有所差异。 C语言中的常量分为以下以下几种: 字面常量 const 修饰的常变量 #define 定义的标识符常量 枚举常量

#include <stdio.h>
#define MAX 100            //#define的标识符常量    
//举例
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
   3.14;//字面常量
   1000;//字面常量
   const float pai = 3.14f;   //const 修饰的常量
   pai = 5.14;//ok?
   return 0;
}

字符串+转义字符+注释

"hello bit.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。 注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串 内容。  

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
   char arr1[] = "bit";
   char arr2[] = {'b', 'i', 't'};
   char arr3[] = {'b', 'i', 't', '\0'};
   printf("%s\n", arr1);
   printf("%s\n", arr2);
   printf("%s\n", arr3);
   return 0;
}

加入我们要在屏幕上打印一个目录: c:\code\test.c 我们该如何写代码?

#include int main() { printf("c:\code\test.c\n");    return 0; }

实际上程序运行的结果是这样的:

这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。 下面看一些转义字符。   转义字符    释义 \?    在书写连续多个问号时使用,防止他们被解析成三字母词 \'    用于表示字符常量' \“    用于表示一个字符串内部的双引号 \\    用于表示一个反斜杠,防止它被解释为一个转义序列符。 \a    警告字符,蜂鸣 \b    退格符 \f    进纸符 \n    换行 \r    回车 \t    水平制表符 \v    垂直制表符 \ddd    ddd表示1~3个八进制的数字。 如: \130 X \xdd    dd表示2个十六进制数字。 如: \x30 0

 

#include <stdio.h>
int main()
{
   //问题1:在屏幕上打印一个单引号',怎么做?
   //问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
   printf("%c\n", '\'');
   printf("%s\n", "\"");
   return 0;
}

//程序输出什么?
#include <stdio.h>

int main()
{
   printf("%d\n", strlen("abcdef"));
   // \32被解析成一个转义字符
   printf("%d\n", strlen("c:\test\328\test.c"));
   return 0;
}

1. 代码中有不需要的代码可以直接删除,也可以注释掉 2. 代码中有些代码比较难懂,可以加一下注释文字 比如:  

#include <stdio.h>

int Add(int x, int y)
{
   return x+y;
}
/*C语言风格注释
int Sub(int x, int y)
{
   return x-y;
}
*/
int main()
{
   //C++注释风格
   //int a = 10;
   //调用Add函数,完成加法
   printf("%d\n", Add(1, 2));
   return 0;
}

C语言风格的注释 /*xxxxxx*/ 缺陷:不能嵌套注释 C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行

选择语句

如果你好好学习,校招时拿一个好offer,走上人生巅峰。 如果你不学习,毕业等于失业,回家卖红薯。 这就是选择!

#include <stdio.h>
int main()
{
   int coding = 0;
   printf("你会去敲代码吗?(选择1 or 0):>");
   scanf("%d", &coding);
   if(coding == 1)
{
prinf("坚持,你会有好offer\n");
}
   else
{
printf("放弃,回家卖红薯\n");
}
   return 0;
}

循环语句

有些事必须一直做,比如我日复一日的讲课,比如大家,日复一日的学习。

C语言中如何实现循环呢? while语句 for语句 do ...     while语句

//while循环的实例
#include <stdio.h>
int main()
{
   printf("加入比特\n");
   int line = 0;
   while(line<=20000)
{
       line++;
       printf("我要继续努力敲代码\n");
}
   if(line>20000)
       printf("赢取白富美\n");
   return 0;
}

 

#include <stdio.h>
int main()
{
   int num1 = 0;
   int num2 = 0;
   int sum = 0;
   printf("输入两个操作数:>");
   scanf("%d %d", &a, &b);
   sum = num1 + num2;
   printf("sum = %d\n", sum);
   return 0;
}

#include <stdio.h>
int Add(int x, int y)
{
int z = x+y;
return z;
}
int main()
{
   int num1 = 0;
   int num2 = 0;
   int sum = 0;
   printf("输入两个操作数:>");
   scanf("%d %d", &num1, &num2);
   sum = Add(num1, num2);
   printf("sum = %d\n", sum);
   return 0;
}

函数的特点就是简化代码,代码复用。

数组

要存储1-10的数字,怎么存储? C语言中给了数组的定义:一组相同类型元素的集合

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素  

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    for(i=0; i<10; i++)
    {
    printf("%d ", arr[i]);
    }
    printf("\n");
   return 0;
}

操作符

简单介绍 + - * / % >> <<

二进制向左右移动n位 a<<2不改变a的值 &   按位与 ^    按位异或 |    按位或 = += -= *= /= &= ^= |=   

>>=

<<=

!           逻辑反操作 -           负值 +           正值 &           取地址 sizeof      操作数的类型长度(以字节为单位) ~           对一个数的二进制按位取反 --          前置、后置-- ++          前置、后置++ *           间接访问操作符(解引用操作符) (类型)       强制类型转换

> >= < <= !=  用于测试“不相等” ==      用于测试“相等”

&&    逻辑与 ||          逻辑或

exp1 ? exp2 : exp3

exp1, exp2, exp3, …expN

[] () . ->

auto  break   case  char  const   continue  default  do   double else  enum  
extern float  for   goto  if   int   long  register    return   short  signed
 sizeof   static struct  switch  typedef union  unsigned   void  volatile  while

注:关键字,先介绍下面几个,后期遇到讲解。

typedef 顾名思义是类型定义,这里应该理解为类型重命名。 比如:

//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名
typedef unsigned int uint_32;

int main()
{
   //观察num1和num2,这两个变量的类型是一样的
   unsigned int num1 = 0;
   uint_32 num2 = 0;
   return 0;
}

在C语言中: static是用来修饰变量和函数的 1. 修饰局部变量-静态局部变量 2. 修饰全局变量-静态全局变量 3. 修饰函数-静态函数 修饰局部变量

//代码1
#include <stdio.h>
void test()
{
   int i = 0;
   i++;
   printf("%d ", i);
}
int main()
{
int i = 0;
   for(i=0; i<10; i++)
{
       test();
}
   return 0;
}
//代码2
#include <stdio.h>
void test()
{
   //static修饰局部变量
   static int i = 0;
   i++;
   printf("%d ", i);
}
int main()
{
int i = 0;
   for(i=0; i<10; i++)
{
       test();
}
   return 0;
}

对比代码1和代码2的效果理解static修饰局部变量的意义。 结论: static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束, 生命周期才结束。

//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
   printf("%d\n", g_val);
   return 0;
}
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
   printf("%d\n", g_val);
   return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。 结论:

//代码1
//add.c
int Add(int x, int y)
{
   return c+y;
}
//test.c
int main()
{
   printf("%d\n", Add(2, 3));
   return 0;
}
//代码2
//add.c
static int Add(int x, int y)
{
   return c+y;
}
//test.c
int main()
{
   printf("%d\n", Add(2, 3));
   return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误. 结论:

剩余关键字后续陆续会讲解。

#define 定义常量和宏
//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))

#include <stdio.h>

int main()
{
   int sum = ADD(2, 3);
   printf("sum = %d\n", sum);
   sum = 10*ADD(2, 3);
   printf("sum = %d\n", sum);
   return 0;
}

指针

内存是电脑上特别重要的存储器,计算机中所有程序的运行都是在内存中进行的 。 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。

变量都有地址,取出变量地址如下:  

int main()
{
int num = 10;
&num;//取出num的地址
printf("%p\n", &num);//打印地址,%p--以地址的形式打印
return 0;
}

  那地址如何存储,需要定义指针变量。

int num = 10;
int *p;//p为一个整形指针变量
p = &num;

指针的使用实例:

#include <stdio.h>
int main()
{
int num = 10;
int *p = &num;
*p = 20;
   return 0;
}

以整形指针举例,可以推广到其他类型,如:

#include <stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'q';
printf("%c\n", ch);
   return 0;
}

指针变量的大小

#include <stdio.h>
int main()
{
   printf("%d\n", sizeof(char *));
   printf("%d\n", sizeof(short *));
   printf("%d\n", sizeof(int *));
   printf("%d\n", sizeof(double *));
   return 0;
}

结论:指针大小在32位平台是4个字节,64位平台是8个字节。  

结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。 比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。 这里只能使用结构体来描述了。 例如:

struct Stu
{
   char name[20];//名字
   int age;      //年龄
   char sex[5];  //性别
   char id[15]; //学号
};

 

//打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps->id);

分支语句和循环语句

分支语句 if switch 循环语句 while for do while goto语句

C语言中由一个分号 ; 隔开的就是一条语句。 比如:

printf("hehe");
1+2;

如果你好好学习,校招时拿一个好offer,走上人生巅峰。 如果你不学习,毕业等于失业,回家卖红薯。 这就是选择!

那if语句的语法结构是怎么样的呢?语法结构:

if(表达式)
   语句;

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

演示代码:

#include <stdio.h>
//代码1
int main()
{
   int age = 0;
   scanf("%d", &age);
   if(age<18)
   {
       printf("未成年\n");
   }
   return 0;
}

//代码2
#include <stdio.h>
int main()
{
    int age = 0;
    scanf("%d", &age);
    if (age < 18)
    {
        printf("未成年\n");
    }
    else
    {
        printf("成年\n");
    }
}

//代码3

#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");
    }
    return 0;
}

解释一下: 如果表达式的结果为真,则语句执行。 在C语言中如何表示真假? 0表示假,非0表示真。   如果条件成立,要执行多条语句,怎应该使用代码块。

#include <stdio.h>
int main()
{
    if (表达式)
    {
        语句列表1;
    }
    else
    {
        语句列表2;
    }
    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;
}

改正: //适当的使用{}可以使代码的逻辑更加清楚。 //代码风格很重要

#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
if (condition) {
   return x;
}
return y;

//代码2
if(condition)
{
   return x;
}
else
{
   return y;
}

//代码3
int num = 1;
if(num == 5)
{
   printf("hehe\n");
}

//代码4
int num = 1;
if(5 == num)
{
   printf("hehe\n");
}
 

代码2和代码4更好,逻辑更加清晰,不容易出错。

1. 判断一个数是否为奇数 2. 输出1-100之间的奇数  

switch语句

switch语句也是一种分支语句。 常常用于多分支的情况。 比如: 输入1,输出星期一 输入2,输出星期二 输入3,输出星期三 输入4,输出星期四 输入5,输出星期五 输入6,输出星期六 输入7,输出星期七 那我没写成 if...else if ...else if 的形式太复杂,那我们就得有不一样的语法形式。 这就是 switch 语句。

switch(整型表达式)
{
   语句项;
}

而语句项是什么呢?

//是一些case语句: //如下: case 整形常量表达式:    语句;

在switch语句中的 break 在switch语句中,我们没法直接实现分支,搭配break使用才能实现真正的分支。 比如:

#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” 所以我们的代码就应该这样实现了:

#include <stdio.h>
//switch代码演示
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;
}

break语句的实际效果是把语句列表划分为不同的部分。 编程好习惯 在最后一个 case 语句的后面加上一条 break语句。 (之所以这么写是可以避免出现在以前的最 后一个 case 语句后面忘了添加 break语句)。   如果表达的值与所有的case标签的值都不匹配怎么办? 其实也没什么,结构就是所有的语句都被跳过而已。 程序并不会终止,也不会报错,因为这种情况在C中并不认为适合错误。 但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢? 你可以在语句列表中增加一条default子句,把下面的标签

写在任何一个case标签可以出现的位置。 当 switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行。 所以,每个switch语句中只能出现一条default子句。 但是它可以出现在语句列表的任何位置,而且语句流会像贯穿一个case标签一样贯穿default子句。 编程好习惯 在每个 switch 语句中都放一条default子句是个好习惯,甚至可以在后边再加一个 break 。 练习

#include <stdio.h>

int main()
{
    int n = 1;
    int m = 2;
    switch (n)
    {
    case 1:
        m++;
    case 2:
        n++;
    case 3:
        switch (n)
        {//switch允许嵌套使用
        case 1:
            n++;
        case 2:
            m++;
            n++;
            break;
        }
    case 4:
        m++;
        break;
    default:
        break;
    }
    printf("m = %d, n = %d\n", m, n);
    return 0;
}

循环语句

  • while
  • for
  • do while  

我们已经掌握了,if语句:

if(条件)     语句;

当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。 但是我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。 那我们怎么做呢? C语言中给我们引入了:while语句,可以实现循环。  

//while 语法结构
while(表达式)
循环语句;

比如我们实现: 在屏幕上打印1-10的数字。

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}

这个代码已经帮我了解了while语句的基本语法,那我们再了解一下: while语句中的break和continue break介绍

//break 代码实例
#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{

		if (i == 5)
			break;
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}

这里代码输出的结果是什么? 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 1 2 3 4 6 7 8 9 10 总结: break在while循环中的作用: 其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的 break是用于永久终止循环的。

//continue 代码实例1

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}

这里代码输出的结果是什么? 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 1 2 3 4 6 7 8 9 10

//continue 代码实例2

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		i = i + 1;
		if (i == 5)
			continue;
		printf("%d ", i);
	}
	return 0;
}

这里代码输出的结果是什么? 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 1 2 3 4 6 7 8 9 10 2 3 4 6 7 8 9 10 总结: continue在while循环中的作用就是: continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接 跳转到while语句的判断部分。进行下一次循环的入口判断。 再看几个代码: /

/ 代码什么意思?
//代码1
#include <stdio.h>
int main()
{
    int ch = 0;
    while ((ch = getchar()) != EOF)
        putchar(ch);
    return 0;
}

//代码2
#include <stdio.h>
int main()
{
    while ((ch = getchar()) != EOF)
    {
        if (ch < ‘0’ || ch > ‘9’)
            continue;
        putchar(ch);
    }
    return 0;
}

for循环

我们已经知道了while循环,但是我们为什么还要一个for循环呢? 首先来看看for循环的语法: 语法

for(表达式1;表达式2;表达式3)
循环语句;

表达式1 表达式1为初始化部分,用于初始化循环变量的。 表达式2 表达式2为条件判断部分,用于判断 循环时候终止。 表达式3 表达式3为调整部分,用于循环条件的调整。 实际的问题: 使用for循环 在屏幕上打印1-10的数字。

#include <stdio.h>
int main()
{
	int i = 0;
	//for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

现在我们对比一下for循环和while循环。

int i = 0;
//实现相同的功能,使用while
i = 1;//初始化部分
while (i <= 10)//判断部分
{
	printf("hehe\n");
	i = i + 1;//调整部分
}

//实现相同的功能,使用while
for (i = 1; i <= 10; i++)
{
	printf("hehe\n");
}

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离 较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。 break和continue在for循环中 我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。 但是还是 有些差异:

//代码1
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			break;
		printf("%d ", i);
	}
	return 0;
}

//代码2
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
	}
	return 0;
}

一些建议: 1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。 2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。

int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}

//两边都是闭区间
for(i=0; i<=9; i++)
{}

#include <stdio.h>
int main()
{
    //变种1
    for (;;)
    {
        printf("hehe\n");
    }
    //变种2
    int x, y;
    for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
    {
        printf("hehe\n");
    }
    return 0;
}

//请问循环要循环多少次?
#include <stdio.h>
int main()
{
    int i = 0;
    int k = 0;
    for (i = 0, k = 0; k = 0; i++, k++)
        k++;
    return 0;
}

do...while()循环

do语句的语法:

do{
循环语句;
}while(表达式);

循环至少执行一次,使用的场景有限,所以不是经常使用。

#include <stdio.h>
int main()
{
	int i = 10;
	do
	{
		printf("%d\n", i);
	} while (i < 10);
	return 0;
}

 

#include <stdio.h>
int main()
{
    int i = 10;
    do
    {
        if (5 == i)
            break;
        printf("%d\n", i);
    } while (i < 10);
    return 0;
}

#include <stdio.h>
int main()
{
    int i = 10;
    do
    {
        if (5 == i)
            continue;
        printf("%d\n", i);
    } while (i < 10);
    return 0;
}

1. 计算 n的阶乘。 2. 计算 1!+2!+3!+……+10! 3. 在一个有序数组中查找具体的某个数字n。 编写int binsearch(int x, int v[], int n); 功能:在v[0] <=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x. 4. 编写代码,演示多个字符从两端移动,向中间汇聚。 5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则 提示登录成,如果三次均输入错误,则退出程序。

//代码1
//编写代码,演示多个字符从两端移动,向中间汇聚
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main()
{
    char arr1[] = "welcome to bit...";
    char arr2[] = "#################";
    int left = 0;
    int right = strlen(arr1) - 1;
    printf("%s\n", arr2);
    //while循环实现
    while (left <= right)
    {
        Sleep(1000);
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        left++;
        right--;
        printf("%s\n", arr2);
    }
    //for循环实现
    for (left = 0, right = strlen(arr1) - 1;
        left <= right;
        left++, right--)
    {
        Sleep(1000);
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n", arr2);
    }
    return 0;
}


//代码2

int main()
{
    char psw[10] = "";
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; ++i)
    {
        printf("please input:");
        scanf("%s", psw);
        if (strcmp(psw, "password") == 0)
            break;
    }
    if (i == 3)
        printf("exit\n");
    else
        printf("log in\n");
    return 0;
}

折半查找算法

比如我买了一双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜? 答案:你每次猜中间数。

实现在主函数内:  

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;
	int key = 7;
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else
			break;
	}
	if (left <= right)
		printf("找到了,下标是%d\n", mid);
	else
		printf("找不到\n");

}

如果实现一个

二分查找函数:

 

int bin_search(int arr[], int left, int right, int key)
{
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) >> 1;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else
			return mid;//找到了,返回下标
	}
	return -1;//找不到
}

猜数字游戏实现

参考代码:

#include <stdio.h>
#include <stdlib.h>

标签: m52c集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台