1. 程式人生 > >the c programming language second edition 第四章函式與程式結構筆記及練習題上

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;
}