-
函數的設計應該遵從什麼原則?
答:函數的設計應該包括函數的聲明、函數的定義、函數的調用;
正解:我們說函數就是一種封裝的方法,函數的設計應該遵從“一個函數僅實作一個功能”的原則,這樣子我們就可以實作化繁為簡的目标,将一個複雜的程式給拆解開來,變成一個個獨立的功能,每個功能我們就用一個函數來實作。
1.“形參和實參,隻是放在不同位置的同一個變量。”,這種說法正确嗎?
答:不對,形參隻有在函數定義裡有作用,當出了函數體,形參什麼也算不上。
不正确。它們是不同的兩個變量,隻是函數在調用的過程中,發生了類似“形參 = 實參”的指派操作。
-
void 類型的函數能否使用 return 語句傳回?
答:實際上void類型的函數是沒有傳回值的函數類型,但是你如果非要寫一些return,編譯器也不會報錯。
正解:解析:在有傳回值的函數中,return 語句的作用通常是傳回函數的執行結果,并結束目前函數,讓 CPU 回到調用它的位置;在沒有傳回值的函數中也可以使用 return 語句,例如當檢查到一個錯誤的時候提前結束函數并傳回。
- 下面是 strcpy 函數的原型,請問為何第二個參數要使用 const 修飾?
char *strcpy(char *dest, const char *src);
正解:答:dest(Destination)參數指向用于存放字元串的目标數組,src(Source)參數指向待拷貝的源字元串。dest 參數是 char * 類型,而 src 參數是 const char * 類型,說明dest 所指向的記憶體空間在函數中是可以改寫的,而 src 所指向的記憶體空間在函數中隻能讀不能寫
- 請問下面這兩個函數的定義等價嗎?
func(int a[], int n)
{
……
}
and
func{int *a, int n}
{
……
}
答:應該等價,數組傳入函數時,實際上傳入的是數組首元素的位址。
-
請問下面代碼中,變量 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
- 請問下面代碼會列印什麼?
#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
動動可愛的小手
-
你應該聽說過 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;
}
-
這節課終于學到了可變參數,現在嘗試自己模拟實作 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;
}