the c programming language second edition 第四章函数与程序结构笔记及练习题上

the c programming language second edition 第四章函数与程序结构笔记

4.1函数的基本认识

  • 编写一个程序它将输入中包含特定模式或字符串的各行打印出来。

    该任务可以明确地划分成下列3部分:
    while(未处理的行)
    if(该行包含指定的模式)
    打印该行

  1. 尽管我们可以都放在主程序main中但更好的做法是利用其结构把每一部分设计成一个独立的函数。因为这样可以把不相关的细节隐藏在函数从而减少了不必要的相互影响的机会并且可以在其他程序中使用
  2. 用getline实现“未处理的行”,我们只需要编写一个判定“该行包含指定的程序”的函数
  3. 编写strindex(s,t)实现该目标。该函数返回字符串t在字符串s中出现的起始位置或索引即当s不包含t时返回值为-1(以此来表示失败的情况)
#include<stdio.h>
#define maxline 1000
int getline(char line[],int max);
int strindex(char source[],char searchfor[]);
char pattern[]="ould";//查找的模式
int getline(char s[],int lim)//将行保存在s中并返回该行的长度
{
    int c,i;
    i=0;
    while(--lim>0&&(c=getchar())!=EOF&&c!='\n')
    s[i++]=c;
    if(c=='\n')
        s[i++]=c;
    s[i]='\0';
    return i;

}
int strindex(char s[],char t[])//返回t在s中的位置若未找到则返回-1
{
    int i,j,k;
    for(i=0;s[i]!='\0';i++)
    {
        for(j=i,k=0;t[k]!='\0'&&t[k]==s[j];k++,j++);//遍历的思想
        if(k>0&&t[k]=='\0')
            return i;
    }
    return -1;
}
main()//返回了一个状态即匹配的数目
{
    char line[maxline];
    int found=0;
    while(getline(line,maxline)>0)//分成一段一段来判断
    {
        if(strindex(line,pattern)>=0)
        {
            printf("%s",line);
            found++;
        }

    }
    return found;
}
  • 函数的定义式如下
    返回值类型 函数名(参数声明表)
    {
    声明和语句
    }
    函数定义中的各构成部分都可以省略。最简单的函数如下所示

    dummy() {}
    该函数不执行任何操作也不返回任何值
    它可以在程序开发期间用以保留位置(留待以后填充代码)
    如果函数定义省略了返回值类型则默认为int类型

  • 程序可以看成事变量定义和函数定义的集合。
    被调用函数通过return语句向调用者返回值

return 表达式;(可以跟任何表达式)
在必要时表达式将被转换为函数的返回值类型。表达式两边可加一对圆括号
调用函数可以忽略返回值并且return语句后面也不一定需要表达式

如果某个函数从一个地方返回时有返回值而从另一个地方返回时没有返回值,该函数并不非法。但可能时一种出问题的征兆。在任何情况下函数若没有成功返回一个值则它的“值”肯定是无用的

  • 在不同的系统中保存在多个源文件中的C语言程序的编译与加载机制是不同的。
练习4-1编写函数strrindex(s,t),它返回字符串t在s中最右边出现的位置。如果不包含则返回-1
strrindex(char s[],char t[]);
strrindex(char s[],char t[])
{
    int i,j,k,num;
    for(i=0;s[i]!='\0';i++)
    {
       for(j=i,k=0;t[k]!='\0'&&t[k]==s[j];k++,j++);
       if(k>0&&t[k]!=='\0')
         num=i;
    }
    return num;
}
strrindex(char s[],char t[]);
strrindex(char s[],char t[])
{
   int i,j,k;
   for(i=strlen(s)-strlen(t);i>=0;i--)
   {
   for(j=i,k=0;t[k]!='\0'&&t[k]==s[j];k++,j++);
       if(k>0&&t[k]!=='\0')
         return i;
   }
   return -1;
}

4.2返回非整型值的函数

  • 通过atof(s)来说明函数返回非整型值的方法。该函数把字符串s转换为相应的双精度浮点数

atof函数是atoi函数的扩展,要处理可选的符号和小数点并要考虑可能缺少整数部分或小数部分的情况

#include <ctype.h>//这版本并不是高质量的一个版本,它占用了过多的空间
double atof(char s[])
{
    double val,power;
    int i,sign;
    for(i=0;isspace(s[i]);i++)//跳过空白符而且局限在第一个遇到的空白符
        ;
    sign=(s[i]=='-')?-1:1;
    if(s[i]=='+'||s[i]=='-')i++;
        for(val=0.0;isdigit(s[i]);val++)val=10.0*val+(s[i]-'0');
        if(s[i]=='.')i++;
        for(power=1.0;isdigit(s[i]);power++)
        {
            val=10.0*val+(s[i]-'0');
            power*=10.0;
        }
        return sign*val/power;//返回的非整型值,为了达到该目的可在调用函数时显式声明atof但函数
                              //的声明与定义必须一致
}

如果没有函数原型则函数将在第一次出现的表达式中被隐式声明
如果先前没有声明过的一个名字出现在某个表达式中并且后面紧跟一个左圆括号那么下文就会认为该名字是一个函数名字且返回值假定为Int类型
如果函数声明不包含参数,那么编译程序不会对参数作任何假设,并会关闭所有的参数检查(void进行声明可以)

//在正确声明atof函数基础上可以利用编写出atoi函数(将字符串转换为Int类型)
int atoi(char s[])
{
   double atof(char s[]);
   return (int) atof(s);//防止这种操作可能会丢失信息某些编译器可能会对此给出警告信息
}

练习4-2 对atof函数进行扩充使他可以处理形如123.45e-6的科学表示方法

double atof(char s[])
{
    double val,power;
    int i,sign,exp;
    for(i=0;isspace(s[i]);i++)//跳过空白符而且局限在第一个遇到的空白符
        ;
    sign=(s[i]=='-')?-1:1;
    if(s[i]=='+'||s[i]=='-')i++;
        for(val=0.0;isdigit(s[i]);val++)val=10.0*val+(s[i]-'0');
        if(s[i]=='.')i++;
        for(power=1.0;isdigit(s[i]);power++)
        {
            val=10.0*val+(s[i]-'0');
            power*=10.0;
        }
     val=sign*val/power; 
   if(s[i]=='e'||s[i]=='E')
   {
     sign=(s[++i]=='-')?-1:1;
     if(s[i]=='+'||s[i]=='-')i++;
     for(exp=0;isdigit(s[i]);i++)exp=10*exp+(s[i]-'0');
     if(sign==1)
     while(exp-->0) val*=10;//防止E或e后面没有数字
     else
      while(exp-->0) val/10;
   }
   return val;
}

猜你喜欢

转载自blog.csdn.net/qq_43233736/article/details/83151023