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


前言

这一节简单地介绍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、使用自定义函数时,注意是否需要提前声明。

  • 23
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值