第四章 函数与程序结构[TCPL]

函数的基本知识

  1. 函数是对一系列计算或操作的过程的抽象

    函数可以把大的计算任务分解成若干个较小的任务,程序设计人员可以基于函数进一步构造程序。函数可以把程序中不需要了解的具体操作细节隐藏起来,从而使整个程序结构更加清晰,并降低修改程序的难度。

    程序可以看成是变量定义和函数定义的集合。函数之间的通信可以通过参数、函数返回值以及外部变量进行。

  2. 函数的定义形式

    返回值类型 函数名(参数声明表)
    {
      声明和语句
    }
    
  3. 例子:打印输入中包含特定字符串的行(grep特例)

    //打印输入中包含特定字符串的行
    
    #include <stdio.h>
    #define MAXLINE 1000  //最行输入行长度
    
    int getline(char line[], int max);
    int stringdex(char source[], char searchfor[]);
    
    char pattern[]="ould"; //带查找的字符串
    
    int main()
    {
     char line[MAXLINE];
     int found = 0; //符合行总数 
     
     while (getline(line, MAXLINE) > 0)
     {
         if (getline(line, MAXLINE) >=0)
         {
             printf("%s\n", line);
             found++;
          } 
     } 
     return found;
     } 
    
    // getline函数:将行保存在s中,并返回该行的长度。lim为行限制长度 
    int getline(char s[], int lim)
    {
     int c; //读取字符
     int l = 0; //存储长度
     
     while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
     {
         s[l++]=c;
      } 
     s[l] = '\0';
     return l;
     
     } 
     
    //strindex函数:返回目标字符串t中s中的位置, 未找到则返回-1
    int strindex(char s[], char t[])
    {
     int i, j, k;
     
     for (i =0; s[i] != '\0'; i++)
     {
         for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
             ;
         if (k > 0 && t[k] == '\0')
         {
             return i;
         }
      } 
      return -1;
    } 
     
    
  4. 例子:atof 函数

      #include <ctype.h>
    
    // atof 函数:把字符串s转换为相应的双精度浮点数 
    double atof(char s[])
    {
     double int_part; //整数部分 
     double fra_part; //小数部分
     int sign; //符号
     int power;
     int i;
     
     for (i = 0; isspace(s[i]); i++) //跳过空白符 
         ;
     sign = (s[i] == '-') ? -1 : 1;
     if (s[i] == '+' || s[i] == '-') //跳过符号 
         i++; 
     
     //整数部分
     for (int_part = 0; isdigit(s[i]); i++)
     {
         int_part = 10.0 * int_part + (s[i] - '0');  
     }
     
     //跳过小数点
     if (s[i] == '.') i++;
     
     //小数部分
     for(power = 1, fra_part = 0.0; isdigit(s[i]); i++)
     {
         fra_part = fra_part * 10.0 + (s[i] - '0');
         power *= 10;
     }
     fra_part = fra_part / power;
     
     return int_part + fra_part;  
    }
    
    main()
    {
     //pass
     } 
    

递归

  1. 递归是指函数可以直接或间接调用自身。

    C语言中的函数可以递归调用,即函数可以直接或间接调用自身。递归调用过程须维护一个处理值得栈,开销较大,执行速度不快;但递归代码比较紧凑,比相应非递归代码更易编写与理解。

  2. 例子:将一个数作为字符串打印

    #include<stdio.h>
    
    //pirntd函数:将一个数作为字符串打印
    void printd(int n)
    {
     if (n < 0)
     {
         putchar('-');
         n = -n;
     }
     if (n / 10)
         printd(n /10);
     putchar(n % 10 + '0');
     } 
    
    //test 
    main()
    {
     int num;
     scanf("%d",&num);
     printd(num);
    }
    

  3. 例子:快速排序

    快速排序算法是C.A.R. Hoare于1962年发明的。对于一个给定的数组,从中选择一个元素,以该元素为界将其余元素划分为两个子集,一个子集中所有元素都小于该元素,另一个子集中所有元素都大于或等于该元素。对这两个子集递归执行这一过程,当某个子集中的元素小于2时,这个子集就不需要再次排序,终止递归。

    // qsort函数:以递增顺序对 v[left] ... v[right]进行排序
    void qsort(int v[], int left, int right)
    {
     int  i;
     int last;
     void swap(int v[], int i, int j);
     
     //递归边界
     if(left >= right)   
         return;
     
     //划分子集  
     swap(v, left, (left + right) / 2);
     last = left;
     for (i = left=1; i <= right; i++)
     {
         if (v[i] < v[left])
             swap(v, ++last, i);
      } 
     swap(v, left, last);
     
     //递归
     qsort(v, left, last-1);
     qsort(v, last+1, right); 
     } 
    
    // swap函数:交换 v[i]与 v[j]的值 
    void swap(int v[], int i, int j)
    {
     int temp;
     
     temp = v[i];
     v[i] = v[j];
     v[j] = temp;
    }
    

变量

  1. 外部变量、内部变量、寄存器变量
  2. 静态变量
    • static声明外部变量和函数,可以将其后的声明对象的作用域限定为被编译源文件的剩余部分,可以达到隐藏外部对象的目的。
    • static也可用于声明内部变量。static内部变量是一种只能贼某个特定函数中使用但一直占据存储空间的变量。

初始化

  1. 在不进行显示初始化的情况下,外部变量和静态变量都将被初始化为0,而自动变量和寄存器变量的处置没有定义。
  2. 外部变量和静态变量的初始化表达式必须是常量表达式。

作用域规则

  1. 名字的作用域指的是程序中可以使用该名字的部分。
  2. 对于在函数开头声明的自动变量,其作用域是声明该变量的函数。
  3. 外部变量或函数的作用域从声明它的地方开始,到其所在的文件的末尾结束。
  4. 如果要在外部变量的定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个源文件中,则必须在相应的变量声明中强制性地使用关键字extern

程序块结构

变量的声明除了可以紧随在函数开始的花括号之后,还可以紧跟在任何其他标识复合语句开始的左花括号之后。

四则运算计算器程序

  1. 实现方法:为了更容易实现,我们使用逆波兰表示法代替中缀表示法。计算器程序的实现过程:每个操作数都被依次压入到栈中;当一个运算符到达时,从栈中弹出相应数目的操作数,把该运算符作用于弹出的操作数,并把运算结果压入到栈中。到达输入行的末尾时,弹出栈顶值并打印。

    中缀表示法: ( 1 - 2 ) * ( 4 + 5 )
    逆波兰表示法:1 2 - 4 5 + *
    

头文件

C预处理

  1. 文件包含
  2. 宏替换
  3. 条件替换
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容