C语言学习记录(三)——Switch、函数定义

C语言学习记录(三)——Switch、函数定义学习足迹前言一、switch用法1.使用语法2.原理二、函数定义及声明1.定义语法2.提前声明总结前言这一节简单地介绍C中两个基础语法1.if…else…的替代方法:switch…case…2


前言

这一节简单地介绍C中两个基础语法

1. if…else…的替代方法:switch…case…
2. 函数function的定义及声明

参考及引用:笨办法学C


一、switch用法

swich是一种选择语法,使用场景是针对不同情况需要做出不同操作。因此它可以代替某些if…else…语句。当不同情况数较多时,就会体现出switch的优势。

1.使用语法

我们直接看一段代码来掌握其语法

#include <stdio.h> int main(int argc, char *argv[]) { 
    if(argc != 2) { 
    printf("ERROR: You need one argument.\n"); // this is how you abort a program return 1; } int i = 0; for(i = 0; argv[1][i] != '\0'; i++) { 
    char letter = argv[1][i]; switch(letter) { 
    case 'a': case 'A': // letter=='a'或'A'时,执行的程序段 printf("%d: 'A'\n", i); break; case 'e': case 'E': // letter=='e'或'E'时,执行的程序段 printf("%d: 'E'\n", i); break; case 'i': case 'I': // letter=='e'或'E'时,执行的程序段 printf("%d: 'I'\n", i); break; case 'o': case 'O': // letter=='o'或'O'时,执行的程序段 printf("%d: 'O'\n", i); break; case 'u': case 'U': // letter=='u'或'U'时,执行的程序段 printf("%d: 'U'\n", i); break; case 'y': case 'Y': // letter=='y'或'Y'时,执行的程序段 if(i > 2) { 
    // it's only sometimes Y printf("%d: 'Y'\n", i); } break; default: // letter取其他值时,执行的程序段 printf("%d: %c is not a vowel\n", i, letter); } } return 0; } 

输入及运行结果如下:

$ ./ex13 aAeOk 0: 'A' 1: 'A' 2: 'E' 3: 'O' 4: k is not a vowel 

从程序中我们提取出关键信息:

switch()的括号中是可以取不同值的变量(必须是广义上的整数,比如字母或者结果为整数的布尔表达式),紧跟在case后面的值是该变量可能的不同取值,case下面的程序段是变量正好等于该值时,要执行的程序;

default指无论何值都可以执行的程序。看到这里可能有个疑问,从程序运行结果看default后面的程序,是在letter不取前面case中的任何值时才会执行,怎么能说无论何值都会执行呢?

这个问题的答案关键在break。我们通过switch的执行原理可以获得答案。

2.执行原理:跳转表

switch实际上是一个跳转表,switch(a)这句话就定义了一个跳转表的起始位置,并且要将这个起始地址加上a的值(因此a必须是整数),得到要跳转到的目的地址。
如果这个目的地址等于下面某个case代表的目的地址,就跳转到这个case处继续向下运行程序。

这时注意:如果没有break,这个程序就从当前case处,一直向下运行。会把下面的case带的代码也执行一遍。因此要使用break来进行隔断! 这样才能保证只执行某个case处的代码。

以上面代码为例具体解释跳转表的跳转过程:

编译器会标记swicth语句的顶端,我们先把它记为地址Y。Y是整张表的起始地址(类似于数组的其起始地址)。
接着对switch中的表达式求值,产生一个数字。在上面的例子中,数字为argv[1]中字母的原始的ASCLL码。
编译器也会把每个类似case ‘A’的case代码块翻译成这个程序中距离语句顶端的地址,所以case ‘A’就在*(Y + ‘A’)处。
接着计算是否Y+letter位于switch语句中,如果距离太远则会将其调整为Y+Default。
一旦计算出了地址,程序就会“跳”到代码的那个位置并继续执行。这就是一些case代码块中有break而另外一些没有的原因。
如果输出了’a’,那它就会跳到case ‘a’,它里面没有break语句,所以它会贯穿执行底下带有代码和break的case ‘A’。
最后它执行这段代码,执行break完全跳出switch语句块。

这时再看上面那个关于default的问题。
如果default前面的case都不带break,那么default后面的代码一定会被执行,它之所以不会被执行,就是因为前面的break!所以说default是变量无论取何值都可以执行的程序。

二、函数定义及声明

1.定义语法

定义时按照下面的格式:

返回值数据类型 函数名(数据类型 参数1, 数据类型 参数2...{ 
    函数体 return 返回值 } 

函数体包含声明部分和语句部分,声明部分用于声明及初始化函数中用到的变量,语句部分就是执行运算等其他操作的语句。

2.提前声明

举一个函数定义的栗子(虽然定义了这么多函数,最终执行的仍是主函数main哦~)

#include <stdio.h> #include <ctype.h> // forward declarations int can_print_it(char ch); void print_letters(char arg[]); void print_arguments(int argc, char *argv[]) { 
    int i = 0; for(i = 0; i < argc; i++) { 
    print_letters(argv[i]); } } void print_letters(char arg[]) { 
    int i = 0; for(i = 0; arg[i] != '\0'; i++) { 
    char ch = arg[i]; if(can_print_it(ch)) { 
    printf("'%c' == %d ", ch, ch); } } printf("\n"); } int can_print_it(char ch) { 
    return isalpha(ch) || isblank(ch); } int main(int argc, char *argv[]) { 
    print_arguments(argc, argv); return 0; } 

其中下面这两行是提前声明函数的语句。就是把要声明的函数,其定义参数的那行复制一遍就行。

int can_print_it(char ch); void print_letters(char arg[]); 

为什么需要提前声明?

可以看到,在下面的程序中,函数print_arguments先被定义,函数体中用到了函数can_print_it和print_letters;然而这两个函数在后面才被定义,因此为了不报错,我们需要在定义print_arguments前,声明这两个函数。

如果我们最后定义函数print_arguments,就不需要提前声明了。


总结

1、switch的本质是跳转表;
2、switch用法中的break很重要,可以用它来实现 if(xxx || xxx)的逻辑,或者其他更复杂的操作;
3、使用自定义函数时,注意是否需要提前声明。

今天的文章
C语言学习记录(三)——Switch、函数定义分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/80123.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注