函數的學習

函數分爲庫函數和自定義函數,庫函數是編譯器自帶的函數,自定義函數則是程序員本身定義的函數。程序員

庫函數

strcpy 字符串拷貝函數

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[] = "bit";
    char arr2[] = "###########";
    strcpy(arr2, arr1);
    printf("%s\n", arr2);   // 每一個字符串最後一位都是'\0',打印時遇到這個字符就會中止打印
    return 0;
}

程序實現了將一個字符串的內容覆蓋進另外一個字符串,在寫程序的時候須要注意的是,被覆蓋的須要比須要拷貝的字符串長,不然就是一個bug。這就是頭文件爲string.h內部的一個函數,可以實現字符串的拷貝。算法

memset 內存設置函數

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[] = "hello world";
    //將hello替換爲*****
    //memset(目標地址,'要換進去的字符',數量);
    memset(arr, '*', 5);
    printf("%s\n", arr);
    return 0;
}//主要是要學會在專業的網站上學會查詢庫函數的使用,zh.cppreference.com,cplusplus.com

msmset函數可以實現將內存裏的某些段的字符屏蔽掉,或者修改成某個字符。也是頭文件爲string.h 的一個函數。對於庫函數的學習最重要的仍是要認識到,要學會在函數庫或者專業的網站上進行查詢,[zh.cppreference.com, cplusplus.com ,進入網站對庫函數進行查詢,不必定要所有記住,可是要會查。數組

自定義函數

自定義函數有形參和實參,形參主要就是爲了接受實參的量,或者指針變量。主要是爲了在主函數外部實現某個單一的功能,一個函數能實現的功能越單一越好,更加簡潔的實現某個功能,不須要每次實現某個功能都要輸入對應的代碼。ide

兩個數取最大值

#include <stdio.h>
int getmax(int x, int y)
{
    return (x > y) ? (x) : (y);
    /*if (x > y)
        return x;
    else
        return y;*/
}
int main()
{
    int a = 20;
    int b = 30;
    int max = 0;
    max = getmax(a, b);
    printf("%d\n", max);
    return 0;
}

在外部寫出一個函數,實現兩個數裏取大的,屬於傳值調用,有返回值的函數,返回值爲一個整形,因此用int定義函數,內部使用更簡單的三目運算符。函數

交換兩個數的值

#include <stdio.h>

void Swap1(int x, int y)
{
    x = x ^ y;
    y = x ^ y;
    x = x ^ y;
}//事實證實,這個函數沒法實現兩個變量數值的交換
void Swap2(int* px, int* py)
{
    *px = *py ^ *px;
    *py = *py ^ *px;
    *px = *py ^ *px;
}
int main()
{
    int a = 10;
    int* pa = &a;
    int b = 30;
    int* pb = &b;
    printf("&a=%d &b=%d\n", pa, pb);
    printf("&a=%x &b=%x\n", pa, pb);
    printf("&a=%p &b=%p\n", pa, pb);
    printf("a=%d b=%d\n", *pa, *pb);//*解引用操做符,表示指針指向的數字,
    printf("a=%d b=%d\n", a, b);
    Swap1(a, b);   //傳值調用 只須要用到變量的值而無需改變外部的變量值的時候
                            //無需返回值的函數,函數類型爲void,意爲返回一個空值,
    printf("a=%d b=%d\n", a, b);
    Swap2(&a, &b); //傳址調用 外部的變量須要在函數內部進行直接改變的時候
                              //存入指針變量而且能讓指針變量正常使用的只能是取地址操做符取到的地址
    printf("a=%d b=%d\n", a, b);
    return 0;
}

第一次寫出函數,運行以後發現沒法實現變量的值的調換,仔細看過,並無發現什麼問題,逐步調試事後,才發現,被調換了值的是被賦值了的形參,與真正須要調換值的變量並沒有關係,在監視窗口中查詢地址,發現形參和實參也是存在不一樣的地址之下,最終在老師的指導之下,才明白,這是須要函數直接經過地址操縱變量,叫作傳址調用, 形參的種類須要是指針變量,輸入的形參也是取形參的地址。
另外我比較好奇指針到底會在不一樣的類型之中會打印成什麼樣子,「printf("a=%d b=%d\n", pa, pb);」打印的是a和b的值,「printf("&a=%p &b=%p\n", pa, pb);」是將a和b的地址打印在指針變量中,是十六位十六進制的地址,「printf("&a=%x &b=%x\n", pa, pb);」講地址打印在十六進制數中,值和printf("&a=%x &b=%x\n", pa, pb);同樣,形式不一樣,「printf("&a=%d &b=%d\n", pa, pb);」是直接用十進制打印出地址的值,可是值仍是和地址同樣。學習

用函數判斷一個數是否爲素數

#include <stdio.h>
#include <math.h>
int Prime(int x)
{
    int i = 0;
    for (i = 2; i <= sqrt(x); i++)
    {
        if (x % i == 0)
        {
            return 0;
        }
    }
    //if (i > sqrt(x))
        return 1;
}
int main()
{
    int a = 0;
    printf("請輸入一個正整數:\n");
    scanf("%d", &a);
    if (Prime(a))
        printf("是一個素數\n");
    else
        printf("不是一個素數\n");
    return 0;
}

判斷一個數是否爲素數的規則仍是很清晰的,看看這個數是否除了自身和1以外能被第二個數整除,不能就是一個素數。sqrt爲求算術平方根,須要math.h的頭文件,函數的調用爲傳值調用,返回一個整形。網站

判斷一個年份是否爲閏年

#include <stdio.h>
int Leap(int x)
{
    if ((x % 4 == 0 && x % 100 != 0) || (x % 400 == 0))
    {
        return 1;
    }
    else
        return 0;
}
int main()
{
    int year = 0;
    printf("請輸入一個年份:\n");
    scanf("%d", &year);
    if (Leap(year))
        printf("是閏年");
    else
        printf("不是閏年\n");
    return 0;
}

仍是一個傳值調用的函數,返回值爲一個整形,將函數的返回值用於主函數if語句的判斷條件。指針

用函數實現有序數組的二分查找

#include <stdio.h>
int binary_search(int arr[],int a,int s)
{
    //算法的實現
    int left = 0;

    int right = s - 1;
    int i = 0;
    while (left <= right)
    {
        int mid = (left + right) / 2;
        if (a > arr[mid])
        {
            left = mid + 1;
        }
        else if (a < arr[mid])
        {
            right = mid - 1;
        }
        else
            return mid;
    }
    return -1;

}
int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    int a = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    printf("請輸入想要查找的數字:\n");
    //若是找到了返回這個數的下標,若是沒找到,返回-1
    scanf("%d", &a);
    int ret = binary_search(arr, a, sz);
    //本質上傳輸到函數內部的是arr的地址,是一個指針變量,並非整個數組。
    if (ret == -1)
        printf("沒找到");

    else
        printf("該數爲arr[%d]\n",ret);

    return 0;
}

須要注意的點,第一次在寫程序過程當中並不能實現想要的效果,不管輸入多少,函數都會返回一個相同的值,調試函數的時候在監視窗口才看到,形參在賦值的時候,只是獲得了數組的第一個數,因此取地址,使得函數內部用指針訪問數組,就可以訪問到整個數組,而後數組的長度也就沒法在函數內部求,因此直接將數組的長度做爲一個參數加入函數之中,二分法也是瞭解的,所須要的功能得以實現。調試

每運行一次變量的值加一

#include <stdio.h>
void Add (int* p)
{
    *p = *p + 1;
}
int main()
{
    int num = 0;
    printf("%d\n", num);
    Add(&num);  //這是須要在函數內部改變自變量的值,傳址調用;
    printf("%d\n", num);
    Add(&num);
    printf("%d\n", num);
    Add(&num);
    printf("%d\n", num);
    return 0;
}

一個傳值調用的無返回值函數,須要經過函數改變實參的值,因此要經過指針直接訪問參量,改變參量的值。code

函數的聲明和定義

聲明和定義是分開來放的,聲明放在頭文件中,函數的定義放在另外一個源文件中,共同構成一個實現某個功能的函數模塊,在代碼中須要使用到函數時,就將頭文件的名稱用雙引號輸入在#include 以後,下面就能調用在該目錄之下的聲明過的函數。函數的模塊將會在函數的遞歸之中重點使用。

相關文章
相關標籤/搜索