理解C语言——从小菜到大神的晋级之路(5)——程序流程控制

2023-11-23 04:38

本文主要是介绍理解C语言——从小菜到大神的晋级之路(5)——程序流程控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   本期视频点击这里

        C语言中的控制流语句用于决定代码中各个语句的执行顺序。通常程序的运行次序的结构有顺序结构、选择结构和循环结构。


1、顺序结构


        在正常情况下,C程序都是从main函数的起始位置开始,按由上到下顺序执行。程序执行以语句为单位。通常一个表达式之后加一个分号“;”构成一条语句,如赋值表达式“x = 1”加一个分号就构成了赋值语句“x = 1;”。除了单条的语句之外,使用一对大括号{}组合的多条语句可以构成一条复合语句。在语法上,复合语句和单条语句等价,只是不以分号结尾。

输入输出函数:

        C语言中最简单的输入输出函数有printf和scanf函数,分别实现向控制台格式化输出和从控制台格式化输入数据。
(1)printf的原型为:

int printf ( const char * format, ... );


        传入该函数的是可变参数,作用是将参数format所指向的C字符串输出到标准输出stdout中。参数format中可以包含显式字符和格式标识符,格式标识符通常由%开头,并用不同的字符表示数据应该以怎样的格式写入format字符串中并输出。其中常用的有:

10进制有符号整数:%d
10进制无符号整数:%u
8进制无符号整数:%o
16进制无符号整数:%x, %X, (小写/大写表示)
10进制浮点数(小数点表示):%f
10进制浮点数(科学计数法):%e,%E
字符型数据:%c
字符串数据:%s

        除了表示数据类型外,格式标识符还可以附带其他信息。完整的格式标识符原型为:
%[flags][width][.precision][length]specifier

        其中的可选部分包含多种信息,如:
  • flag:可取值为:+、-、#、0和空格
  • width:可取某个数值或*。数值表示输出数据的最小宽度,*表示宽度不表示在标识符中而由后续的参数指定。
  • .precision:表示数据输出的精度。对于整型数据表示数据输出的位数,对于浮点数则用于表示小数点后输出的位数(默认为6)
  • length:改变数据类型的长度。常用取值有hh、h、l、ll、和L等。

        当printf执行成功后,函数返回输出的总字符个数;若执行失败,则返回错误信息。例子:
/* printf example */
#include <stdio.h>int main()
{printf ("Characters: %c %c \n", 'a', 65);printf ("Decimals: %d %ld\n", 1977, 650000L);printf ("Preceding with blanks: %10d \n", 1977);printf ("Preceding with zeros: %010d \n", 1977);printf ("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);printf ("Width trick: %*d \n", 5, 10);printf ("%s \n", "A string");return 0;
}

(2)scanf函数的声明为
int scanf ( const char * format, ... );

        该函数从命令行窗口中读取输入的数据,并根据format参数保存到对应的内存地址中。保存数据的内存地址必须是已经有效分配好的、有写入权限的内存区域。
        同printf函数类似,format也是一个字符串格式。在内容上,format字符串中可以包含三种内容:
  • 空字符:在遇到第一个非空字符之前,所有的空字符都将被忽略。
  • 非空字符(除格式标识):函数将读取输入的字符同format中的这个字符进行比较,如果一致那么将丢弃该字符并读取下一个,如果不一致则会失败,不会继续读取后续的输入。
  • 格式标识:同printf类似,格式标识指定了输入数据的类型。每一个格式标识同后面的参数指定的内存地址一一对应。
        格式标识符的原型为:
%[*][width][length]specifier

  • *:表示字符从输入数据流中读取,但是被忽略,不被存入格式标识符对应的内存中。
  • width:读入当前格式标识符对应位置变量的最大字符数量。
  • lengh:同printf中的lengh类似,改变对应存储位置的数据类型

例子:

/* scanf example */
#include <stdio.h>int main ()
{char str [80];int i;printf ("Enter your family name: ");scanf ("%79s",str); printf ("Enter your age: ");scanf ("%d",&i);printf ("Mr. %s , %d years old.\n",str,i);printf ("Enter a hexadecimal number: ");scanf ("%x",&i);printf ("You have entered %#x (%d).\n",i,i);return 0;
}

2、选择结构


        选择结构是程序的基本结构之一,实现了根据不同条件实现不同代码的功能。选择结构是由实现逻辑判断的选择语句实现的。根据逻辑判断的结果不同,选择结构执行的流程也不同。实现选择结构通常有两种语句:if语句和switch语句。

(1)if语句
        C语言的if语句是最简单的选择语句,if关键字后面的括号中表示判断条件表达式,后面接一条语句或复合语句。当判断条件表达式为真(即表达式的值为非0)时,执行下面的语句;如果判断条件表达式为假(即表达式的值为0),则跳过后面的语句不执行。 其实现方法是
if(a == 0/*判断条件*/)
{printf("True");   //执行语句
}

        if还可以接else实现二选一的操作,在if-else选择语句中,else部分是非必须的,应根据需要选择是否添加else部分。 实现方法是

if(a == 0)
{printf("True"); //表达式成立时执行
}
else
{printf("False");//表达式不成立时执行
}


        另外,为了保持良好的编程风格,我们推荐无论是if还是else后面都是用大括号构成的符合语句,即使里面只有简单的一条语句也不例外。如果不适用大括号,则可能会面临if和else关键字匹配的混乱,如

if(x == 0)if(y == 1)a = n;elsea = m;

        在该段程序中,else部分一定是同if(y == 1)部分匹配的,二者共同构成一条if-else语句。如果希望else同更外层的if匹配,则必须使用大括号{}:

if(x == 0)
{if(y == 1)a = n;
}
elsea = m;

             if和else匹配的原则是,逐条语句(包括复合语句)向上查找,与找到的第一个if匹配。


        在实际使用的过程中,经常会遇到多级判断的情况。此时如果使用多层嵌套的if-else语句则会相当繁琐。所以C语言提供了else if语句实现级联的判断。在级联的判断中,每个判断条件都会被依次求值,只要有一个满足条件,就会执行对应的程序,并终止整个选择过程。使用方法如下:
if( x == 0)a = 2;
else if(x == 1)a = 4;
else if(x == 3)a = 6;
else if(x == 4)a = 8;
elsea = 10;

(2)switch语句
        有时候当多级判断的条件相近时(比如上例),多层的if-else也显得比较繁琐。在测试表达式是否与一些常量数值中的某一个匹配并执行相应的分支动作时,switch语句是一个更好的选择。switch语句的使用方法如下:
switch(表达式)
{
case 常量值1: 执行语句;
case 常量值2: 执行语句;
case 常量值3: 执行语句;
default:执行语句;
}

        在执行switch语句时,首先计算表达式的值。当表达式的某一个值与某个分支匹配,那么语句将从该分支开始执行;如果没找到任何匹配,则从default分支开始执行;如果没有default分支且没有任何匹配,则该switch语句不执行任何操作。各个分支的排列没有任何影响。
        需要注意到一点是,switch语句通常不会只执行一个分支,而是以某一个分支作为切入点依次执行。如果我们需要只执行某一个分支,那么需要在每一个分支的执行语句中包含break;来跳出。

3、循环结构


        循环结构实现将一段代码反复循环运行多次的功能。有了循环结构,我们就没有必要在将需要重复执行的代码反复拷贝粘贴多次,既简单又方便。C语言中实现循环结构总共有三种语句,即while、do-while和for。

(1)while

        while结构实现方式如:
while(表达式)
{循环体;
}

        while循环在每次执行前先计算表达式的值。当表达式的值非0,则执行循环体的语句,完成后继续计算表达式的值,如此循环,直到表达式的值为0,此时跳出循环执行后续部分。

(2)do-while

        do-while结构的实现方式如:
do
{循环体;
}while(表达式);

        在使用上,do-while循环同while循环类似,只是执行顺序上稍有不同:do-while循环首先会执行循环体,然后判断表达式是否成立。也就是说,无论表达式是否成立,循环体至少会被执行一次。

(3)for循环

        for循环通常是这三种循环结构中最为常用的一种。实现方式如:
for(表达式1; 表达式2; 表达式3)
{循环体;
}

        执行时,首先计算表达式1的值,再计算表达式2的值,如果表达式2为假,则直接跳出循环。如果表达式2为真,则执行循环体,然后计算表达式3,再次计算表达式2并判断,如此循环往复,直到表达式2的值为0。
一般在使用时,通常将表达式1用作初始化循环变量,表达式2用于控制循环流程,表达式3用于修改循环变量,如:
for(int x = 0; x < 10; x++)
{printf("Number x: %d\n", x);
}

(4)异常循环
       通常异常循环主要有以下几种:
  • 中止本次循环:在某一次循环中触发了某种条件,导致本次循环不再继续执行,而是重新判断条件并执行下一次循环。实现该功能需在循环体中包含continue语句,当程序执行到continue时,本次循环将中止,随后开始执行下一次循环。
  • 中止整个循环:在某一次循环中触发了某种条件,导致整个循环过程中止,不再执行后面的循环。该功能需要在循环体中使用break语句实现。当程序执行到break时循环直接跳出,执行循环后面的语句。
  • 死循环:死循环指的是退出条件永远无法满足,始终在执行的循环过程。死循环通常由代码的错误产生,并且会导致程序的bug。不过在某些场合中会特别定义死循环来实现一些特殊的场景,如Windows开发中的消息循环,在没有接收到退出消息是将作为一个死循环一直执行。


4、无条件跳转语句

C语言中可以为任何语句前面加上标号用于定义语句的位置。格式为:
flag: printf("这是一条语句.\n");

        定义了标号之后,就可以使用无条件跳转语句跳转到该标号所在的位置。无条件跳转语句goto是一个比较特殊的语句,当执行到goto语句时,程序将无条件跳转到标号的位置:
goto flag;

        goto语句可以完全改变程序的执行流程。如果滥用将极大破坏程序的结构和可读性,因此应尽量避免直接使用,而优先选择上述三种常用的结构实现流程控制。不过在某些特殊情况下,使用goto可以大大简化代码的结构和流程,此时也不应该对goto语句过分排斥。

这篇关于理解C语言——从小菜到大神的晋级之路(5)——程序流程控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/415393

相关文章

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st