程序設計入門-C語言基礎知識-翁愷-第五週:函數-詳細筆記(五)

第五週:函數

5.1 函數

什麼是函數?測試

  • 函數是一塊代碼,接受零個或多個參數,作一件事情,並返回零個或一個值。
  • 函數聲明語法
    返回值 函數名(參數列表){
    函數體
    }
  • 咱們前面列子中常用的printf和scanf都是函數

調用函數code

  • 函數(參數值);
  • ()小括號起到了表示函數調用的重要做用,及時沒有參數也須要()
  • 若是有參數,則須要給出正確的數量和順序
  • 這些值會被按照順序依次來初始化函數中的參數
  • 調用函數時給的參數叫作實際參數,在函數體內接受到的參數叫形式參數
  • 函數知道每一次是哪裏調用它,會返回到正確的地方
  • 能夠傳遞給函數的值是表達式的結果,這包括:
    • 字面量
    • 變量
    • 函數的返回值
    • 計算的結果
  • 調用函數時給的值與參數的類型不匹配是C語言傳統上最大的漏洞
  • 編譯器老是悄悄替你把類型轉換好,可是這極可能不是你所指望的
  • 後續的語言,C++/Java在這方面很嚴格

從函數中返回值ip

  • return中止函數的執行,並返回一個值
  • return;
  • return 表達式;
  • 一個函數中能夠有多個return語句
  • 不推薦給一個函數多個return不符合單一出口原則,多個return咱們再作修改時須要去找全部的出口

沒有返回值的函數作用域

  • void 函數名(參數表)
  • 不能使用呆值的return,也能夠沒有return
  • 調用的時候不能作返回值的賦值
  • tips:若是是有返回值的函數,則必須使用帶值的return

5-2 使用函數

  • 把函數的原型聲明寫在main函數前是由於c的編譯器自上而下順序分析你的代碼
  • 函數能夠先作原型聲明,再定義;
  • 函數的聲明和定義必須一致

函數原型get

  • 函數頭,以分號";"結束,就構成了函數原型
  • 函數原型的目的是告訴編譯器這個函數長什麼樣子
    • 名稱
    • 參數(數量及類型)
    • 返回類型
  • 舊的標準習慣把函數原型寫在調用它的函數裏面,如今通常寫在調用它函數的前面。
  • 原型裏能夠不寫參數的名字,可是通常仍然要寫上,便於閱讀。

參數的傳遞原型

  • c語言的函數的參數的傳遞是對值的傳遞
  • 每一個函數有本身的變了空間,參數也位於這個獨立的空間中,和其餘函數沒有關係
  • 過去,對於函數參數表中的參數,叫作「形式參數」,調用函數時給的值,叫作「實際參數」
  • 因爲容易讓初學者誤會實際參數就是實際在函數中進行計算的參數,誤會調用函數的時候把變量而不是值傳進去了,因此咱們不建議繼續用這種種古老的方式稱呼它們。
  • 調用參數的時候,咱們就叫把值傳遞進去了,而在函數內部咱們就稱爲參數。

本地變量編譯器

  • 函數的每次運行,就產生了衣蛾獨立的變量空間,在這個空間中的變量,是函數此次運行所獨有的,稱爲本地變量。
  • 做用域:在(代碼的)什麼範圍內能夠訪問這個變量(這個變量能夠)起做用
  • 對於本地變量,這兩個問題的答案是統一的——大括號內(塊)

本地變量的規則it

  • 本地變量時定義在塊內的
    • 塊能夠是函數的塊內
    • 也能夠是語句的塊內
    • 甚至能夠隨便拉一大括號定義變量
  • 程序運行進入這個快以前,這個變量不存在,離開這個快,這個變量也消失了
  • 在塊外定義的變量在塊內仍然有效
  • 在塊裏面定義了和外面同名的變量則掩蓋了外面的
  • 不能在同一塊內定義同名的變量
  • 本地變量不會被默認初始化
  • 參數在進入函數的時候就被初始化了

沒有參數時io

  • 在函數沒有參數時必定要使用void填充參數,好比: void f(void);
  • 由於若是不寫void就等於告訴編譯器,不肯定須要什麼參數,當調用函數時若是有參數,編譯器會默認覺得函數的參數的類型都是int ,並且在定義時若是參數不一致編譯器也不會報錯,所以當定義時變量爲double而聲明爲int調用的結果就不是咱們預期的了。
  • 一樣若是函數沒有聲明,編譯器會默認認爲這個函數是一個 int類型返回值而且有兩個int類型參數的函數,爲了程序便於閱讀,全部的函數在使用前都須要原型聲明,再定義。

逗號運算符

  • 調用函數時的逗號和逗號運算符怎麼區分?
  • 調用函數時的圓括號裏的逗號是標點分隔符,不是運算符
    • f(a,b) 標點分割符,分割多個參數
    • f((a,b)) 算術運算符
  • (a,b) 逗號運算符自左向右運算,先計算左邊表達式的值,再計算右邊表達式的值,最後的結果返回右邊表達式的值。好比 (a=3+2,a-5)的結果是 0

函數裏面的函數

  • c語言不容許函數的嵌套定義

奇怪的寫法

  • int i,j,sum(int a,int b); 雖然c語言容許這麼作,可是不推薦這種寫法,不易於閱讀。
  • return (i); 返回一個i的值,一樣不推薦,理由同上。

關於main

  • int mian()也是一個函數
  • 要不要寫成int main(void)? 能夠寫成void,而且在main函數執行前程序還有些準備的工做,當執行好這些準備工做後纔會調用main函數
  • return的0有人看嗎?
    • Windows: if errorlevel 1...
    • Unix Bash: echo $?
    • Csh: echo $status
    • return的值在各個系統都是能夠獲得的,有人會根據返回值來判斷程序是否出錯等,所以return 0 是有意義的。

5.3 課後習題

1 .題目內容: 題目內容:
每一個非素數(合數)均可以寫成幾個素數(也可稱爲質數)相乘的形式,這幾個素數就都叫
作這個合數的質因數。好比,6 能夠被分解爲 2x3,而 24 能夠被分解爲 2x2x2x3。
如今,你的程序要讀入一個[2,100000]範圍內的整數,而後輸出它的質因數分解式;當
讀到的就是素數時,輸出它自己。
輸入格式:
一個整數,範圍在[2,100000]內。
輸出格式:
形如:
n=axbxcxd

n=n
全部的符號之間都沒有空格,x 是小寫字母 x。
輸入樣例:
18
輸出樣例:
18=2x3x3

題目分析:

  • 咱們前面寫過判斷素數的功能,能夠把他封裝成一個函數。
  • 這裏用用戶輸入的有兩種狀況,輸入的是一個素數或者合數。
  • 素數十分好處理,咱們直接輸出這個數自己便可。
  • 若是是合數怎麼算出這個合數的質因數呢?咱們有三個未知的問題,一是不知道這個合數有多少個質因數,而且也不知道這些質因數的值和組合方式。
  • 咱們能夠採起笨一點的辦法,
    1. 用這個合數num和最小素數2作取餘,若是結果不爲0,則表示除不盡繼續用下一個素數3作整除,一直到能整除爲止,算出一個結果。
    2. 將結果賦值給num,若是num仍是合數回到第1步,不然咱們就已經把最初的素數num拆分紅n個相乘的素數了,也就是這個合數的質因數。
  • 所以咱們還須要一個取第x個素數的值一個函數,x>0

程序實現:

#ifndef getPrimeFactor_h

#define getPrimeFactor_h
#include <stdio.h>
int isPrime(int number);
void getPrimeFactor(void);
int getPrimeNumber(int index);
#endif



#include "getPrimeFactor.h"

int isPrime(int number)
{
 int isPrimeNumber = 1;
 int middle = 0;

 if (number == 1)
 {
  isPrimeNumber = 0;
 }
 else
 {
  int i = 2;
  middle = number / 2;
  for (; i <= middle; i++)
  {
   if (number % i == 0)
   {
    isPrimeNumber = 0;
    break;
   }
  }
 }

 return isPrimeNumber;
}

int getPrimeNumber(int index)
{
 int isPrimeNumber = 1;
 int middle = 0;
 int primeNumber = 2;
 int i, j;
 int currentIndex = 0;

 for (j = 2; j < 100000; j++)
 {
  //重置素數狀態
  isPrimeNumber=1;
  middle = j / 2;
  for (i = 2; i <= middle; i++)
  {
   if (j % i == 0)
   {
    isPrimeNumber = 0;
    break;
   }
  }
  if (isPrimeNumber)
  {
   primeNumber = j;
   currentIndex++;
  }
  if (index == currentIndex)
  {
   break;
  }
 }
 return primeNumber;
}

void getPrimeFactor(void)
{
 int number = 0;
 int currentPrimeNum = 2; //當前素數
 int primeIndex = 1;    //當前素數的序號,從1開始1,2,3...

 printf("請輸入一個範圍在[2,100000]的整數");
 scanf("%d", &number);

 if (isPrime(number))
 {
  printf("%d=%d", number, number);
 }
 else
 {
  printf("%d=", number);
  do
  {
   while (number % currentPrimeNum != 0 && currentPrimeNum < number)
   {
    primeIndex++;
    currentPrimeNum = getPrimeNumber(primeIndex);
   }
   number /= currentPrimeNum;
   printf("%dx", currentPrimeNum);
   //當number值改變重置狀態
   currentPrimeNum = 2;
   primeIndex = 1;
  } while (!isPrime(number));
  printf("%d", number);
 }
}


#include <stdio.h>
#include "getPrimeFactor.h"

int main(int argc, char *argv[])
{
 getPrimeFactor();
 return 0; 
}

測試樣例:

請輸入一個範圍在[2,100000]的整數18
18=2x3x3
--------------------------------
Process exited after 1.221 seconds with return value 0
請輸入一個範圍在[2,100000]的整數100
100=2x2x5x5
--------------------------------
Process exited after 1.691 seconds with return value 0
請輸入一個範圍在[2,100000]的整數108
108=2x2x3x3x3
--------------------------------
Process exited after 2.766 seconds with return value 0

2.題目內容:
一個正整數的因子是全部能夠整除它的正整數。而一個數若是剛好等於除它自己外的因子之
和,這個數就稱爲完數。例如 6=1+2+3(6 的因子是 1,2,3)。
如今,你要寫一個程序,讀入兩個正整數 n 和 m(1<=n<m<1000),輸出[n,m]範圍內
全部的完數。
提示:能夠寫一個函數來判斷某個數是不是完數。
輸入格式:
兩個正整數,以空格分隔。
輸出格式:
其間全部的完數,以空格分隔,最後一個數字後面沒有空格。若是沒有,則輸出一個空行。
輸入樣例:
1 10
輸出樣例:
6

題目分析:

  • 咱們須要輸出n到m範圍內全部的完數。
  • 如何判斷一個數n是不是完數呢?咱們用n作取餘運算,從1開始取餘n/2,這期間全部取餘爲0的數就是這個數的因子,而後咱們再對他們對累加,若是累加的和剛好等於n自己那麼這個數就是一個完數。

程序實現:

#ifndef getPerfectNumberRange_h

#define getPerfectNumberRange_h
#include <stdio.h>
void getPerfectNumberRange(void);
int getIsPerfectNumber(int number);
#endif



#include "getPerfectNumberRange.h"

int getIsPerfectNumber(int number)
{

    int sum = 0;
    int isPerfectNumber = 0;
    for (int i = 1; i <= number / 2; i++)
    {

        if (number % i == 0)
        {
            sum += i;
        }
    }

    if (sum == number)
    {
        isPerfectNumber = 1;
    }

    return isPerfectNumber;
}

void getPerfectNumberRange(void)
{

    int n, m;
    int isHaveAnyPerfectNumber = 0;
    printf("請輸入兩個正整數n和m,(1<=n<m<1000)");
    scanf("%d %d", &n, &m);

    for (int i = n; i <= m; i++)
    {

        if (getIsPerfectNumber(i))
        {
            printf("%d", i);

            if (isHaveAnyPerfectNumber == 0)
            {
                isHaveAnyPerfectNumber = 1;
            }

            if (i < m)
            {
                printf(" ");
            }
        }

       
    }

    if (isHaveAnyPerfectNumber == 0)
    {
        printf("\n");
    }
}




#include <stdio.h>
#include "getPerfectNumberRange.h"

int main(int argc, char *argv[])
{
 getPerfectNumberRange();
 return 0; 
}

測試樣例:

請輸入兩個正整數n和m,(1<=n<m<1000)1 100
6 28
--------------------------------
Process exited after 1.984 seconds with return value 0

請輸入兩個正整數n和m,(1<=n<m<1000)1 5


--------------------------------
Process exited after 4.39 seconds with return value 0
相關文章
相關標籤/搜索