天天看點

《帶你學C帶你飛學習筆記》—— SE29參數和指針

  1. 函數的設計應該遵從什麼原則?

    答:函數的設計應該包括函數的聲明、函數的定義、函數的調用;

正解:我們說函數就是一種封裝的方法,函數的設計應該遵從“一個函數僅實作一個功能”的原則,這樣子我們就可以實作化繁為簡的目标,将一個複雜的程式給拆解開來,變成一個個獨立的功能,每個功能我們就用一個函數來實作。

1.“形參和實參,隻是放在不同位置的同一個變量。”,這種說法正确嗎?

答:不對,形參隻有在函數定義裡有作用,當出了函數體,形參什麼也算不上。

不正确。它們是不同的兩個變量,隻是函數在調用的過程中,發生了類似“形參 = 實參”的指派操作。

  1. void 類型的函數能否使用 return 語句傳回?

    答:實際上void類型的函數是沒有傳回值的函數類型,但是你如果非要寫一些return,編譯器也不會報錯。

    正解:解析:在有傳回值的函數中,return 語句的作用通常是傳回函數的執行結果,并結束目前函數,讓 CPU 回到調用它的位置;在沒有傳回值的函數中也可以使用 return 語句,例如當檢查到一個錯誤的時候提前結束函數并傳回。

  2. 下面是 strcpy 函數的原型,請問為何第二個參數要使用 const 修飾?
char *strcpy(char *dest, const char *src);
           

正解:答:dest(Destination)參數指向用于存放字元串的目标數組,src(Source)參數指向待拷貝的源字元串。dest 參數是 char * 類型,而 src 參數是 const char * 類型,說明dest 所指向的記憶體空間在函數中是可以改寫的,而 src 所指向的記憶體空間在函數中隻能讀不能寫

  1. 請問下面這兩個函數的定義等價嗎?
func(int a[], int n)
{
        ……
}
           

and

func{int *a, int n}
{
        ……
}
           

答:應該等價,數組傳入函數時,實際上傳入的是數組首元素的位址。

  1. 請問下面代碼中,變量 a 和變量 b 的值列印出來分别是多少?為什麼?

    #include <stdio.h>

void get_array(int b[10]);

void get_array(int b[10])

{

int i;

printf("sizeof b: %d\n", sizeof(b));
           

}

int main()

{

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

printf("sizeof a: %d\n", sizeof(a));
    get_array(a);

    return 0;
           

}

答:會列印

sizeof a: 40
sizeof b:4
           
  1. 請問下面代碼會列印什麼?
#include <stdio.h>

void func(int b[][3]);

void func(int b[][3])
{
        printf("%d\n", b[2][2]);
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 10, 11, 12}
        };

        func(a);

        return 0;
}
           

答:**錯解:**将會列印數組a第三行第三列的值:11

正解:9,為什麼呢?因為在調用數組時,傳進去的是數組首元素的位址,在函數定義裡b數組時一個三列的數組,要列印b[2][2]其實要列印的是b數組第三行第三列的值,需要将數組a重新排列成三列的數組,根據二維數組也是橫向排列的原則将a數組排列成3列的數組,這樣就找到b[2][2]的值9

動動可愛的小手

  1. 你應該聽說過 itoa 函數(函數文檔 -> 傳送門),它的作用是将一個整數轉換成字元串形式存儲。現在要求我們自己來實作一個類似功能的函數 myitoa(int num, char *str),該函數的第一個參數是待轉換的整型變量,第二參數傳入一個字元指針,用于存放轉換後的字元串。

    此段代碼較難,咱不了解,代入懂了

#include <stdio.h>

char *myitoa(int num, char *str);

char *myitoa(int num, char *str)
{
        int dec = 1;
        int i = 0;
        int temp;

        if (num < 0)
        {
                str[i++] = '-';
                num = -num;
        }

        temp = num;

        while (temp > 9)
        {
                dec *= 10;
                temp /= 10;
        }

        while (dec != 0)
        {
                str[i++] = num / dec + '0';
                num = num % dec;
                dec /= 10;
        }

        str[i] = '\0';

        return str;
}

int main(void)
{
        char str[10];

        printf("%s\n", myitoa(520, str));
        printf("%s\n", myitoa(-1234, str));

        return 0;
}
           
  1. 這節課終于學到了可變參數,現在嘗試自己模拟實作 printf 格式化輸出的基本功能。

    要求:

    自己寫一個函數 myprintf,模拟實作 printf 函數的可變參數特性

    輸出第一個參數中除了格式化占位符外的所有字元

    實作 %d 的格式化輸出

    實作 %c 的格式化輸出

    實作 %s 的格式化輸出

    實作 myprintf 函數傳回列印了多少字元

    全程僅能使用 putchar 唯一一個标準庫函數

    不了解/沒看

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

int myprintf(char *format, ...);
int countInt(int num);
void printInt(int num);
void printStr(char *str);

// 這裡我們使用疊代的方式列印整數
// 等後面學了遞歸,用遞歸會更友善呢
void printInt(int num)
{
        int dec = 1;
        int temp;

        if (num < 0)
        {
                putchar('-');
                num = -num;
        }

        temp = num;

        while (temp > 9)
        {
                dec *= 10;
                temp /= 10;
        }        

        while (dec != 0)
        {
                putchar(num / dec + '0');
                num = num % dec;
                dec /= 10;
        }
}

// 計算整數占多少個字元
int countInt(int num)
{
        int count = 0;

        if (num < 0)
        {
                count++;
                num = -num;
        }

        do
        {
                count++;
        } while (num /= 10);

        return count;
}

void printStr(char *str)
{
        int i = 0;

        while (str[i] != '\0')
        {
                putchar(str[i]);
                i++;
        }
}

int myprintf(char *format, ...)
{
        int i = 0;
        int count = 0;
        int darg; 
        char carg;
        char *sarg; 
        va_list vap;

        va_start(vap, format);

        while (format[i] != '\0')
        {
                // 如果不是格式化占位符,直接列印字元串
                if (format[i] != '%')
                {
                        putchar(format[i]);
                        i++;
                        count++;
                }
                // 如果是格式化占位符...
                else
                {
                        switch (format[i+1])
                        {
                                case 'c':
                                        {
                                                carg = va_arg(vap, int);
                                                putchar(carg);
                                                count++;
                                                break;
                                        }
                                case 'd':
                                        {
                                                darg = va_arg(vap, int);
                                                printInt(darg);
                                                count += countInt(darg);
                                                break;
                                        }
                                case 's':
                                        {
                                                sarg = va_arg(vap, char *);
                                                printStr(sarg);
                                                count += strlen(sarg);
                                                break;
                                        }
                        }
                        i += 2;
                }
        }

        va_end(vap);

        return count;
}

int main(void)
{
        int i;

        i = myprintf("Hello %s\n", "FishC");
        myprintf("共列印了%d個字元(包含\\n)\n", i);
        i = myprintf("int: %d, char: %c\n", -520, 'H');
        myprintf("共列印了%d個字元(包含\\n)\n", i);
        
        return 0;
}