程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言入門知識 >> C語言04函數與遞歸

C語言04函數與遞歸

編輯:C語言入門知識

1 函數的定義

1.1 問題

自定義兩個簡單的函數,使用return返回數據。

1.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:函數的定義

代碼如下所示:

  1. #include
  2.  
  3. int getInt()
  4. {
  5. return 10;
  6. }
  7.  
  8. double getDouble()
  9. {
  10. return 5.5;
  11. }
  12.  
  13. int main()
  14. {
  15. int n;
  16. n = getInt();
  17. printf ("%d\n", n);
  18.  
  19. double d;
  20. d = getDouble();
  21. printf("%lf\n", d);
  22.  
  23. return 0;
  24. }

上述代碼中,以下代碼:

  1. int getInt()
  2. {
  3. return 10;
  4. }

定義了一個函數getInt,該函數返回一個整型數據,沒有參數。

上述代碼中,以下代碼:

  1. double getDouble()
  2. {
  3. return 5.5;
  4. }

定義了一個函數getDouble,該函數返回一個雙精度浮點型數據,沒有參數。

上述代碼中,以下代碼:

  1. int n;
  2. n = getInt();
  3. printf ("%d\n", n);

首先,定義一個整型變量n,用於存儲getInt函數的返回值。

然後,調用函數getInt得到返回值,並存儲在變量n中。

最後,使用函數printf輸出變量n的內容。

上述代碼中,以下代碼:

  1. double d;
  2. d = getDouble();
  3. printf("%lf\n", d);

首先,定義一個雙精度浮點型變量d,用於存儲getDouble函數的返回值。

然後,調用函數getDouble得到返回值,並存儲在變量d中。

最後,使用函數printf輸出變量d的內容。

1.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int getInt()
  4. {
  5. return 10;
  6. }
  7.  
  8. double getDouble()
  9. {
  10. return 5.5;
  11. }
  12.  
  13. int main()
  14. {
  15. int n;
  16. n = getInt();
  17. printf ("%d\n", n);
  18.  
  19. double d;
  20. d = getDouble();
  21. printf("%lf\n", d);
  22.  
  23. return 0;
  24. }

2 函數的聲明

2.1 問題

定義兩個函數,分別測試隱式聲明和顯式聲明,同時體現出隱式聲明中類型的自動提示效果。

2.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:函數的聲明

代碼如下所示:

  1. #include
  2.  
  3. int main()
  4. {
  5. f1();
  6. double f2(/*void*//*int i*/);
  7. f2(1,2);
  8. return 0;
  9. }
  10.  
  11. int f1()
  12. {
  13. printf("f1()\n");
  14. return 0;
  15. }
  16.  
  17. double f2(int a,int b)
  18. {
  19. printf("f2()\n");
  20. return 3.0;
  21. }

上述代碼中,以下代碼:

  1. f1();

由於在調用f1前未對其進行聲明,所以是隱式聲明。

上述代碼中,以下代碼:

  1. double f2(/*void*//*int i*/);

對函數f2進行顯示聲明。其中,參數可以省略。如果沒有任何參數,表示可以接受任意的參數,如果寫void表示不接受任何參數。

上述代碼中,以下代碼:

  1. f2(1,2);

調用函數f2。

上述代碼中,以下代碼:

  1. int f1()
  2. {
  3. printf("f1()\n");
  4. return 0;
  5. }

定義了一個函數f1。該函數沒有參數,返回一個整型數據。

上述代碼中,以下代碼:

  1. double f2(int a,int b)
  2. {
  3. printf("f2()\n");
  4. return 3.0;
  5. }

定義了一個函數f2。該函數有兩個參數,分別是整型變量a和b。在函數體中並沒有使用這兩個參數,這是允許的。

2.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main()
  4. {
  5. f1();
  6. double f2(/*void*//*int i*/);
  7. f2(1,2);
  8. return 0;
  9. }
  10.  
  11. int f1()
  12. {
  13. printf("f1()\n");
  14. return 0;
  15. }
  16.  
  17. double f2(int a,int b)
  18. {
  19. printf("f2()\n");
  20. return 3.0;
  21. }

3 函數參數的應用

3.1 問題

定義兩個函數,分別體現參數傳遞時的值傳遞和數組做參數時的處理方法。

3.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:函數參數的應用

代碼如下所示:

  1. #include
  2.  
  3. void fun1(int a)
  4. {
  5. printf("形參a從主函數傳入fun1時的值為%d\n", a);
  6. a = a + 10;
  7. printf("形參a在fun1中改變後的值為%d\n", a);
  8. }
  9.  
  10. void fun2(int array[])
  11. {
  12. printf("形參array[0]從主函數傳入fun2時的值為%d\n", array[0]);
  13. array[0] = array[0] + 10;
  14. printf("形參array[0]在fun2中改變後的值為%d\n", array[0]);
  15. }
  16.  
  17. int main()
  18. {
  19. int a = 5;
  20. int array[10] = {1};
  21.  
  22. printf("變量a在調用函數fun1之前的值為%d\n", a);
  23. fun1(a);
  24. printf("變量a在調用函數fun1之後的值為%d\n", a);
  25.  
  26. printf("\n");
  27. printf("數組元素a[0]在調用函數fun2之前的值為%d\n", array[0]);
  28. fun2(array);
  29. printf("數組元素a[0]在調用函數fun2之後的值為%d\n", array[0]);
  30.  
  31. return 0;
  32. }

上述代碼中,以下代碼:

  1. void fun1(int a)
  2. {
  3. printf("形參a從主函數傳入fun1時的值為%d\n", a);
  4. a = a + 10;
  5. printf("形參a在fun1中改變後的值為%d\n", a);
  6. }

首先,定義了一個函數fun1,該函數有一個參數,為整型變量a。

然後,使用函數printf輸出形參a從調用函數傳入的值。

下一步,將形參a加上10。

最後,再使用函數printf輸出形參a加上10後的值。兩次調用可以看出形參a的變化情況。

上述代碼中,以下代碼:

  1. void fun2(int array[])
  2. {
  3. printf("形參array[0]從主函數傳入fun2時的值為%d\n", array[0]);
  4. array[0] = array[0] + 10;
  5. printf("形參array[0]在fun2中改變後的值為%d\n", array[0]);
  6. }

首先,定義了一個函數fun1,該函數有一個參數,為整型數組array。

然後,使用函數printf輸出形參數組的第一個元素array[0]從調用函數傳入的值。

下一步,將形參數組的第一個元素array[0]加上10。

最後,再使用函數printf輸出形參數組的第一個元素array[0]加上10後的值。兩次調用可以看出形參數組的第一個元素array[0]的變化情況。

上述代碼中,以下代碼:

  1. int main()
  2. {
  3. int a = 5;
  4. int array[10] = {1};

在主函數中定義一個整型變量a和一個整型數組array,並將變量a初始化為5,將數組array的第一個元素初始化成1。

上述代碼中,以下代碼:

  1. printf("變量a在調用函數fun1之前的值為%d\n", a);
  2. fun1(a);
  3. printf("變量a在調用函數fun1之後的值為%d\n", a);

首先,使用函數printf輸出變量a在調用函數fun1之前的值。

然後,調用函數fun1。

最後,再使用函數printf輸出變量a在調用函數fun1之後的值。兩次調用可以看出變量a的變化情況。

上述代碼中,以下代碼:

  1. printf("數組元素a[0]在調用函數fun2之前的值為%d\n", array[0]);
  2. fun2(array);
  3. printf("數組元素a[0]在調用函數fun2之後的值為%d\n", array[0]);

首先,使用函數printf輸出整型數組array的第一個元素array[0]在調用函數fun2之前的值。

然後,調用函數fun2。

最後,再使用函數printf輸出整型數組array的第一個元素array[0]在調用函數fun2之後的值。兩次調用可以看出整型數組array的第一個元素array[0]的變化情況。

3.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. void fun1(int a)
  4. {
  5. printf("形參a從主函數傳入fun1時的值為%d\n", a);
  6. a = a + 10;
  7. printf("形參a在fun1中改變後的值為%d\n", a);
  8. }
  9.  
  10. void fun2(int array[])
  11. {
  12. printf("形參array[0]從主函數傳入fun2時的值為%d\n", array[0]);
  13. array[0] = array[0] + 10;
  14. printf("形參array[0]在fun2中改變後的值為%d\n", array[0]);
  15. }
  16.  
  17. int main()
  18. {
  19. int a = 5;
  20. int array[10] = {1};
  21.  
  22. printf("變量a在調用函數fun1之前的值為%d\n", a);
  23. fun1(a);
  24. printf("變量a在調用函數fun1之後的值為%d\n", a);
  25.  
  26. printf("\n");
  27. printf("數組元素a[0]在調用函數fun2之前的值為%d\n", array[0]);
  28. fun2(array);
  29. printf("數組元素a[0]在調用函數fun2之後的值為%d\n", array[0]);
  30.  
  31. return 0;
  32. }

4 函數和程序的終止

4.1 問題

定義一個函數,分別調用return語句和exit()函數,並在主函數中調用測試效果。

4.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:函數和程序的終止

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. void fun(int e)
  5. {
  6. if (1 == e)
  7. exit(EXIT_SUCCESS);
  8. else
  9. return;
  10. }
  11.  
  12. int main()
  13. {
  14. int n;
  15. printf("輸入1在函數fun中調用exit函數\n輸入2函數fun中執行return語句\n請選擇輸入:");
  16. scanf("%d", &n);
  17.  
  18. fun(n);
  19.  
  20. printf("選擇2才會輸出此句");
  21.  
  22. return 0;
  23. }

上述代碼中,以下代碼:

  1. void fun(int e)
  2. {
  3. if (1 == e)
  4. exit(EXIT_SUCCESS);
  5. else
  6. return;
  7. }

定義了一個函數,該函數有一個參數為整型變量e。當參數e為1時,函數fun將調用函數exit退出程序;當參數e為其它值時,函數fun執行return語句返回。

上述代碼中,以下代碼:

  1. int n;
  2. printf("輸入1在函數fun中調用exit函數\n輸入2函數fun中執行return語句\n請選擇輸入:");
  3. scanf("%d", &n);

首先,定義一個整型變量n,用於存儲用戶輸入的選擇。

然後,使用函數printf提示輸入選擇。

最後,使用函數scanf輸入一個選擇到變量n中。

上述代碼中,以下代碼:

  1. fun(n);

將用戶的選擇,變量n,作為實參調用函數fun。

上述代碼中,以下代碼:

  1. printf("選擇2才會輸出此句");

當用戶選擇1時,程序會在函數fun中退出,則此語句將不被執行。只有用戶選擇了2或其他值時,函數fun將執行return語句返回,此語句才被執行。

4.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. void fun(int e)
  5. {
  6. if (1 == e)
  7. exit(EXIT_SUCCESS);
  8. else
  9. return;
  10. }
  11.  
  12. int main()
  13. {
  14. int n;
  15. printf("輸入1在函數fun中調用exit函數\n輸入2函數fun中執行return語句\n請選擇輸入:");
  16. scanf("%d", &n);
  17.  
  18. fun(n);
  19.  
  20. printf("選擇2才會輸出此句\n");
  21.  
  22. return 0;
  23. }

5 遞歸和遞推的應用

5.1 問題

分別使用遞歸函數和循環遞推的方式實現n的階乘。

5.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:遞歸和遞推的應用。

代碼如下所示:

  1. #include
  2.  
  3. int factorial(int n)
  4. {
  5. if (1 == n)
  6. return 1;
  7. int f;
  8. f = n * factorial(n - 1);
  9.  
  10. return f;
  11. }
  12.  
  13. int main()
  14. {
  15. int n;
  16. printf("請輸入求階乘的數:");
  17. scanf("%d", &n);
  18.  
  19. int f = 1;
  20. for (int i = 2; i <= n; i++)
  21. f *= i;
  22. printf("遞推方法求得%d的階乘為%d\n", n, f);
  23.  
  24. f = factorial(n);
  25. printf("遞歸方法求得%d的階乘為%d\n", n, f);
  26.  
  27. return 0;
  28. }

上述代碼中,以下代碼:

  1. int factorial(int n)
  2. {
  3. if (1 == n)
  4. return 1;
  5. int f;
  6. f = n * factorial(n - 1);
  7.  
  8. return f;
  9. }

定義遞歸函數factorial,用於計算整數n的階乘。在該函數中,以下語句:

  1. if (1 == n)
  2. return 1;

為遞歸函數的出口,因為1的階乘還是1。在該函數中,以下語句:

  1. int f;
  2. f = n * factorial(n - 1);

如果求整數n的階乘,則轉化為求n乘以n–1的階乘,而n–1的階乘的計算方法還是調用factorial函數,只是參數變成n-1。

上述代碼中,以下代碼:

  1. int main()
  2. {
  3. int n;
  4. printf("請輸入求階乘的數:");
  5. scanf("%d", &n);

首先,定義一個整型變量n,用於存儲求階乘的數。

然後,使用函數printf提示輸入求階乘的數。

最後,使用函數scanf輸入求階乘的數到變量n中。

上述代碼中,以下代碼:

  1. int f = 1;
  2. for (int i = 2; i <= n; i++)
  3. f *= i;
  4. printf("遞推方法求得%d的階乘為%d\n", n, f);

是使用遞推的方法求整數n的階乘,n的階乘是計算方法為1x2x3x· · ·xN,所以使用循環逐次相乘,得到整數n的階乘。

上述代碼中,以下代碼:

  1. f = factorial(n);
  2. printf("遞歸方法求得%d的階乘為%d\n", n, f);

是使用遞歸的方法求整數n的階乘,調用函數factorial,得到整數n的階乘。

5.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int factorial(int n)
  4. {
  5. if (1 == n)
  6. return 1;
  7. int f;
  8. f = n * factorial(n - 1);
  9.  
  10. return f;
  11. }
  12.  
  13. int main()
  14. {
  15. int n;
  16. printf("請輸入求階乘的數:");
  17. scanf("%d", &n);
  18.  
  19. int f = 1;
  20. for (int i = 2; i <= n; i++)
  21. f *= i;
  22. printf("遞推方法求得%d的階乘為%d\n", n, f);
  23.  
  24. f = factorial(n);
  25. printf("遞歸方法求得%d的階乘為%d\n", n, f);
  26.  
  27. return 0;
  28. }

6 遞歸和遞推的比較

6.1 問題

定義兩個函數,分別用遞歸和遞推方式計算費氏數列的第n項,並利用time命令查看時間差。

6.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:遞歸和遞推的應用。

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. long fib(int n)
  5. {
  6. long f1 = 1;
  7. long f2 = 1;
  8. long fn = 1;
  9.  
  10. for (int i = 2; i < n; i++)
  11. {
  12. fn = f1 + f2;
  13. f1 = f2;
  14. f2 = fn;
  15. }
  16.  
  17. return fn;
  18. }
  19.  
  20. long fib_f(int n)
  21. {
  22. if (1 == n || 2 == n)
  23. return 1;
  24.  
  25. return fib_f(n - 1) + fib_f(n - 2);
  26. }
  27.  
  28. int main()
  29. {
  30. int n;
  31. printf("請輸入月份:");
  32. scanf("%d", &n);
  33.  
  34. time_t begin = time(0);
  35. long sum = fib(n);
  36. time_t stop = time(0);
  37. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));
  38.  
  39. begin = time(0);
  40. sum = fib_f(n);
  41. stop = time(0);
  42. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));
  43.  
  44. return 0;
  45. }

上述代碼中,以下代碼:

  1. long fib(int n)
  2. {
  3. long f1 = 1;
  4. long f2 = 1;
  5. long fn = 1;
  6.  
  7. for (int i = 2; i < n; i++)
  8. {
  9. fn = f1 + f2;
  10. f1 = f2;
  11. f2 = fn;
  12. }
  13.  
  14. return fn;
  15. }

定義了一個使用遞推的方法求費氏數列的函數fib,該函數有一個參數是要求第幾個月的兔子數。費氏數列的計算公式為:

f1 = 1

f2 = 1

fn = fn-1 + fn-2

上述代碼中,以下代碼:

  1. fn = f1 + f2;

按計算公式fn = fn-1 + fn-2計算。

上述代碼中,以下代碼:

  1. f1 = f2;
  2. f2 = fn;

為下一次循環中公式fn = fn-1 + fn-2中的f1和f2做准備。

上述代碼中,以下代碼:

  1. long fib_f(int n)
  2. {
  3. if (1 == n || 2 == n)
  4. return 1;
  5.  
  6. return fib_f(n - 1) + fib_f(n - 2);
  7. }

定義了一個使用遞歸的方法求費氏數列的函數fib_f,該函數有一個參數是要求第幾個月的兔子數。該函數中,以下代碼:

  1. if (1 == n || 2 == n)
  2. return 1;

為遞歸出口,根據公式,第1個月和第2個月的兔子數均為1。該函數中,以下代碼:

  1. return fib_f(n - 1) + fib_f(n - 2);

根據公式fn = fn-1 + fn-2求第n個月的兔子數,因為求第n-1個月和第n-2個月與求第n個月的兔子數方法相同,都是調用fib_f函數,只是參數不同罷了,所以使用遞歸方法。

上述代碼中,以下代碼:

  1. int main()
  2. {
  3. int n;
  4. printf("請輸入月份:");
  5. scanf("%d", &n);

首先,定義一個整型變量n,用於存儲求兔子數的月份數。

然後,使用函數printf提示輸入求兔子數的月份數。

最後,使用函數scanf輸入求兔子數的月份數到變量n中。

上述代碼中,以下代碼:

  1. time_t begin = time(0);
  2. long sum = fib(n);
  3. time_t stop = time(0);
  4. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));

首先,使用time函數記錄調用遞推方法函數fib開始的時間。

然後,調用函數fib計算輸入月份的兔子數。

下一步,使用time函數記錄調用遞推方法函數fib結束的時間。

最後,打印輸入月份的兔子數和計算所用的時間數。

上述代碼中,以下代碼:

  1. begin = time(0);
  2. sum = fib_f(n);
  3. stop = time(0);
  4. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));

首先,使用time函數記錄調用遞歸方法函數fib_f開始的時間。

然後,調用函數fib_f計算輸入月份的兔子數。

下一步,使用time函數記錄調用遞歸方法函數fib_f結束的時間。

最後,打印輸入月份的兔子數和計算所用的時間數。

6.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. long fib(int n)
  5. {
  6. long f1 = 1;
  7. long f2 = 1;
  8. long fn = 1;
  9.  
  10. for (int i = 2; i < n; i++)
  11. {
  12. fn = f1 + f2;
  13. f1 = f2;
  14. f2 = fn;
  15. }
  16.  
  17. return fn;
  18. }
  19.  
  20. long fib_f(int n)
  21. {
  22. if (1 == n || 2 == n)
  23. return 1;
  24.  
  25. return fib_f(n - 1) + fib_f(n - 2);
  26. }
  27.  
  28. int main()
  29. {
  30. int n;
  31. printf("請輸入月份:");
  32. scanf("%d", &n);
  33.  
  34. time_t begin = time(0);
  35. long sum = fib(n);
  36. time_t stop = time(0);
  37. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));
  38.  
  39. begin = time(0);
  40. sum = fib_f(n);
  41. stop = time(0);
  42. printf("費氏數列第%d月兔子數為%ld,遞推方法用時%lf秒\n", n, sum, difftime(stop, begin));
  43.  
  44. return 0;
  45. }

7 遞歸的典型應用

7.1 問題

使用遞歸實現漢諾塔。

漢諾塔是指法國數學家愛德華·盧卡斯曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹雳中消滅,而梵塔、廟宇和眾生也都將同歸於盡。

7.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:遞歸的典型應用。

代碼如下所示:

  1. #include
  2.  
  3. void move(int n,char a,char b,char c)
  4. {
  5. if(n==1)
  6. printf("\t%c->%c\n",a,c);
  7. else
  8. {
  9. move(n-1,a,c,b);
  10. printf("\t%c->%c\n",a,c);
  11. move(n-1,b,a,c);
  12. }
  13. }
  14.  
  15. int main()
  16. {
  17. int n;
  18. printf("請輸入要移動的塊數:");
  19. scanf("%d",&n);
  20.  
  21. move(n,'a','b','c');
  22.  
  23. return 0;
  24. }

上述代碼中,以下代碼:

  1. void move(int n,char a,char b,char c)
  2. {
  3. if(n==1)
  4. printf("\t%c->%c\n",a,c);
  5. else
  6. {
  7. move(n-1,a,c,b);
  8. printf("\t%c->%c\n",a,c);
  9. move(n-1,b,a,c);
  10. }
  11. }

定義了一個遞歸函數move,用來模擬移動盤子。該函數有四個參數,說明如下:

第一個參數為盤子的數量。

第二個參數為從這根針移走。

第三個參數為經過這根針。

第四個參數為移到這根針。

在該函數中,以下代碼:

  1. if(n==1)
  2. printf("\t%c->%c\n",a,c);

表示當n只有1個盤子的時候直接從a移動到c。

在該函數中,以下代碼:

  1. move(n-1,a,c,b);

表示第n-1個盤子要從a通過c移動到b。

在該函數中,以下代碼:

  1. printf("\t%c->%c\n",a,c);

輸出從a移動到c。

在該函數中,以下代碼:

  1. move(n-1,b,a,c);

表示n-1個盤子移動到b後,b變開始盤,b通過a移動到c。

上述代碼中,以下代碼:

  1. int main()
  2. {
  3. int n;
  4. printf("請輸入要移動的塊數:");
  5. scanf("%d",&n);

首先,定義一個整型變量n,用於存儲要移動的盤子數。

然後,使用函數printf提示輸入要移動的盤子數。

最後,使用函數scanf輸入要移動的盤子數到變量n中。

上述代碼中,以下代碼:

  1. move(n,'a','b','c');

啟動移動函數,輸出移動過程。

7.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. void move(int n,char a,char b,char c)
  4. {
  5. if(n==1)
  6. printf("\t%c->%c\n",a,c); //當n只有1個的時候直接從a移動到c
  7. else
  8. {
  9. move(n-1,a,c,b); //第n-1個要從a通過c移動到b
  10. printf("\t%c->%c\n",a,c);
  11. move(n-1,b,a,c); //n-1個移動過來之後b變開始盤,b通過a移動到c,這邊很難理解
  12. }
  13. }
  14.  
  15. int main()
  16. {
  17. int n;
  18. printf("請輸入要移動的塊數:");
  19. scanf("%d",&n);
  20.  
  21. move(n,'a','b','c');
  22.  
  23. return 0;
  24. }

標准函數庫

1 格式化輸入輸出

1.1 問題

測試格式化輸入輸出函數的中格式字符串的各種效果。

1.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:格式化輸入輸出

代碼如下所示:

  1. #include
  2.  
  3. int main()
  4. {
  5. int a = 0, b = 0;
  6. scanf("%*d%d", &a, &b);
  7. printf("a = %d, b = %d\n", a, b);
  8.  
  9. printf("%10d,%-10d,%d\n", 100, 200, 300);
  10. printf("%08d\n", 100);
  11. printf("%0*d\n", 8, 100);
  12. printf("0%o,0x%x\n", 8, 16);
  13.  
  14. printf("%.2f\n", 12.34567);
  15. printf("%10.2f\n", 12.34567);
  16.  
  17. return 0;
  18. }

上述代碼中,以下代碼:

  1. scanf("%*d%d", &a, &b);

%*d中的*表示禁止字符,即輸入的第一個數據被跳過,不進行賦值。

上述代碼中,以下代碼:

  1. printf("%10d,%-10d,%d\n", 100, 200, 300);

首先,%10d中的10表示該數據如果不足10位則左邊補空格。

然後,%-10d中的-10表示該數據如果不足10位則右邊補空格。

上述代碼中,以下代碼:

  1. printf("%08d\n", 100);

%08d中的08表示數據如果不足8位則左邊補0。

上述代碼中,以下代碼:

  1. printf("%0*d\n", 8, 100);

%0*d中的0*表示數據不足後面第一個參數,即8,所含的位數,則左邊補0。

上述代碼中,以下代碼:

  1. printf("0%o,0x%x\n", 8, 16);

0%o表示將數據按8進制輸出;0x%x表示將數據按16進制輸出。

上述代碼中,以下代碼:

  1. printf("%.2f\n", 12.34567);

%.2f表示將數據保留2位小數。

上述代碼中,以下代碼:

  1. printf("%10.2f\n", 12.34567);

%10.2表示將數據保留2位小數,且包括小數點在內的位數不足10位時,左邊補0。

1.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main()
  4. {
  5. int a = 0, b = 0;
  6. scanf("%*d%d", &a, &b);
  7. printf("a = %d, b = %d\n", a, b);
  8.  
  9. printf("%10d,%-10d,%d\n", 100, 200, 300);
  10. printf("%08d\n", 100);
  11. printf("%0*d\n", 8, 100);
  12. printf("0%o,0x%x\n", 8, 16);
  13.  
  14. printf("%.2f\n", 12.34567);
  15. printf("%10.2f\n", 12.34567);
  16.  
  17. return 0;
  18. }

2 動態分配內存

2.1 問題

動態分配基本類型和字符串的內存,並進行數據存儲和取出打印。(最後記得用free()釋放)

2.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:動態分配內存

代碼如下所示:

  1. #include
  2. #include
  3. #include
  4.  
  5. int main()
  6. {
  7. int *pi = (int*)malloc(sizeof(int));
  8. *pi = 10;
  9. printf("*pi = %d\n", *pi);
  10. free(pi);
  11.  
  12. float *pf = (float*)malloc(sizeof(float));
  13. *pf = 10.23;
  14. printf("*pf = %f\n", *pf);
  15. free(pf);
  16.  
  17. double *pd = (double*)malloc(sizeof(double));
  18. *pd = 123.456;
  19. printf("*pd = %lf\n", *pd);
  20. free(pd);
  21.  
  22. char *pstr = (char*)malloc(1024);
  23. strcpy(pstr, "將字符串放在堆上");
  24. printf("%s\n", pstr);
  25. free(pstr);
  26.  
  27. return 0;
  28. }

上述代碼中,以下代碼:

  1. int *pi = (int*)malloc(sizeof(int));

在堆上動態分配一個整型變量。

上述代碼中,以下代碼:

  1. *pi = 10;

將動態分配的整型變量賦值。

上述代碼中,以下代碼:

  1. printf("*pi = %d\n", *pi);

使用printf函數輸出動態變量的值。

上述代碼中,以下代碼:

  1. free(pi);

釋放動態變量所占的存儲空間。

上述代碼中,以下代碼:

  1. float *pf = (float*)malloc(sizeof(float));

在堆上動態分配一個單精度浮點型變量。

上述代碼中,以下代碼:

  1. *pf = 10.23;

將動態分配的單精度浮點型變量賦值。

上述代碼中,以下代碼:

  1. printf("*pf = %f\n", *pf);

使用printf函數輸出動態變量的值。

上述代碼中,以下代碼:

  1. free(pf);

釋放動態變量所占的存儲空間。

上述代碼中,以下代碼:

  1. double *pd = (double*)malloc(sizeof(double));

在堆上動態分配一個雙精度浮點型變量。

上述代碼中,以下代碼:

  1. *pd = 123.456;

將動態分配的雙精度浮點型變量賦值。

上述代碼中,以下代碼:

  1. printf("*pd = %lf\n", *pd);

使用printf函數輸出動態變量的值。

上述代碼中,以下代碼:

  1. free(pd);

釋放動態變量所占的存儲空間。

上述代碼中,以下代碼:

  1. char *pstr = (char*)malloc(1024);

在堆上動態分配一個字符型數組。

上述代碼中,以下代碼:

  1. strcpy(pstr, "將字符串放在堆上");

將字符型數組賦值為字符串。

上述代碼中,以下代碼:

  1. printf("%s\n", pstr);

使用printf函數輸出動態字符型數組。

上述代碼中,以下代碼:

  1. free(pstr);

釋放動態字符型數組所占的存儲空間。

2.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3. #include
  4.  
  5. int main()
  6. {
  7. int *pi = (int*)malloc(sizeof(int));
  8. *pi = 10;
  9. printf("*pi = %d\n", *pi);
  10. free(pi);
  11.  
  12. float *pf = (float*)malloc(sizeof(float));
  13. *pf = 10.23;
  14. printf("*pf = %f\n", *pf);
  15. free(pf);
  16.  
  17. double *pd = (double*)malloc(sizeof(double));
  18. *pd = 123.456;
  19. printf("*pd = %lf\n", *pd);
  20. free(pd);
  21.  
  22. char *pstr = (char*)malloc(1024);
  23. strcpy(pstr, "將字符串放在堆上");
  24. printf("%s\n", pstr);
  25. free(pstr);
  26.  
  27. return 0;
  28. }

3 動態分配內存(續1)

3.1 問題

動態分配整型數組和結構的內存,並進行數據存儲和取出打印。(最後記得用free()釋放)

3.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:動態分配內存(續1)

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main()
  5. {
  6. int *array = (int *)malloc(sizeof(int) * 10);
  7. for (int i = 0; i < 10; i++)
  8. array[i] = i + 1;
  9. for (int i = 0; i < 10; i++)
  10. printf("%d ", array[i]);
  11. printf("\n");
  12. free(array);
  13.  
  14. struct Data
  15. {
  16. int a;
  17. double b;
  18. char c;
  19. };
  20. struct Data *p = (struct Data*)malloc(sizeof(struct Data));
  21. p->a = 10;
  22. p->b = 12.34;
  23. p->c = 'a';
  24. printf("%d %lf %c\n", p->a, p->b, p->c);
  25. free(p);
  26.  
  27. return 0;
  28. }

上述代碼中,以下代碼:

  1. int *array = (int *)malloc(sizeof(int) * 10);

在堆上定義了一個整型數組。該數組共有10個元素。

上述代碼中,以下代碼:

  1. for (int i = 0; i < 10; i++)
  2. array[i] = i + 1;

使用循環對堆上的數組元素進行逐個賦值。

上述代碼中,以下代碼:

  1. for (int i = 0; i < 10; i++)
  2. printf("%d ", array[i]);
  3. printf("\n");

使用循環遍歷輸出堆上的數組中的所有元素。

上述代碼中,以下代碼:

  1. free(array);

釋放堆上的整型數組。

上述代碼中,以下代碼:

  1. struct Data
  2. {
  3. int a;
  4. double b;
  5. char c;
  6. };

定義一個結構體Data,有三個成員,整型變量a,雙精度浮點型變量b,字符型變量c。

上述代碼中,以下代碼:

  1. struct Data *p = (struct Data*)malloc(sizeof(struct Data));

在堆上動態分配一個結構體Data的變量。

上述代碼中,以下代碼:

  1. p->a = 10;
  2. p->b = 12.34;
  3. p->c = 'a';

対堆上的結構體變量的每個成員進行賦值。

上述代碼中,以下代碼:

  1. printf("%d %lf %c\n", p->a, p->b, p->c);

使用printf函數輸出堆上的結構體Data的變量。

上述代碼中,以下代碼:

  1. free(p);

釋放堆上的結構體Data的變量。

3.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main()
  5. {
  6. int *array = (int *)malloc(sizeof(int) * 10);
  7. for (int i = 0; i < 10; i++)
  8. array[i] = i + 1;
  9. for (int i = 0; i < 10; i++)
  10. printf("%d ", array[i]);
  11. printf("\n");
  12. free(array);
  13.  
  14. struct Data
  15. {
  16. int a;
  17. double b;
  18. char c;
  19. };
  20. struct Data *p = (struct Data*)malloc(sizeof(struct Data));
  21. p->a = 10;
  22. p->b = 12.34;
  23. p->c = 'a';
  24. printf("%d %lf %c\n", p->a, p->b, p->c);
  25. free(p);
  26.  
  27. return 0;
  28. }

4 時間函數的使用

4.1 問題

打印年月日小時分秒格式的系統當前時間。

4.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:時間函數的使用

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main()
  5. {
  6. time_t t = time(0);
  7. struct tm * local = localtime(&t);
  8. printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);
  9.  
  10. return 0;
  11. }

上述代碼中,以下代碼:

  1. time_t t = time(0);

使用函數time獲取當前系統時間。

上述代碼中,以下代碼:

  1. struct tm * local = localtime(&t);

將系統時間轉換成本地時間。

上述代碼中,以下代碼:

  1. printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);

使用printf函數輸出本地時間。

4.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main()
  5. {
  6. time_t t = time(0);
  7. struct tm * local = localtime(&t);
  8. printf("%d年%d月%d日 %d:%d:%d\n", 1900 + local->tm_year, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec);
  9.  
  10. return 0;
  11. }

輸入輸出函數(IO)

1 打開文件

1.1 問題

用各種模式打開文件。

1.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:格式化輸入輸出

代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","w");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11. fclose(fp);
  12. fp=NULL;
  13.  
  14. fp=fopen("file.c","a");
  15. if(NULL==fp)
  16. {
  17. return -1;
  18. }
  19. fclose(fp);
  20. fp=NULL;
  21.  
  22. fp=fopen("file.c","r");
  23. if(NULL==fp)
  24. {
  25. return -1;
  26. }
  27. fclose(fp);
  28. fp=NULL;
  29.  
  30. return 0;
  31. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }
  6. fclose(fp);
  7. fp=NULL;

首先,使用函數fopen打開一個文件,該函數有兩個參數,說明如下:

第一個參數為字符串包含欲打開的文件路徑及文件名。

第二個參數為字符串代表文件打開方式。

在上述語句中,打開的文件名為當前目錄下的file.c。使用w方式打開,該方式打開只寫文件,若文件存在則清空原文件,若不存在新建。

然後,使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","a");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }
  6. fclose(fp);
  7. fp=NULL;

首先,使用函數fopen打開一個文件。

在上述語句中,打開的文件名為當前目錄下的file.c。使用a方式打開,該方式以追加的方式打開只寫文件,若文件存在則在最後追加寫入,若不存在新建。

然後,使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }
  6. fclose(fp);
  7. fp=NULL;

首先,使用函數fopen打開一個文件。

在上述語句中,打開的文件名為當前目錄下的file.c。使用r方式打開,該方式打開只讀文件,該文件必須存在。

然後,使用函數fclose關閉打開的文件。

1.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","w");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11. fclose(fp);
  12. fp=NULL;
  13.  
  14. fp=fopen("file.c","a");
  15. if(NULL==fp)
  16. {
  17. return -1;
  18. }
  19. fclose(fp);
  20. fp=NULL;
  21.  
  22. fp=fopen("file.c","r");
  23. if(NULL==fp)
  24. {
  25. return -1;
  26. }
  27. fclose(fp);
  28. fp=NULL;
  29.  
  30. return 0;
  31. }

2 使用fscanf()和fprintf()讀寫文件

2.1 問題

fscanf函數的功能是從一個流中執行格式化輸入,fscanf遇到空格和換行時結束。

fprintf函數的功能是傳送格式化輸出到一個文件中。

2.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:使用fscanf()和fprintf()讀寫文件

代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","w");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11.  
  12. int a = 10;
  13. float f = 12.34;
  14. double d = 12345.6789;
  15. char c = 'a';
  16.  
  17. fprintf(fp, "%c %d %f %lf", c, a, f, d);
  18.  
  19. fclose(fp);
  20. fp=NULL;
  21.  
  22. fp=fopen("file.c","r");
  23. if(NULL==fp)
  24. {
  25. return -1;
  26. }
  27.  
  28. char c1;
  29. int a1;
  30. float f1;
  31. double d1;
  32.  
  33. fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);
  34. printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);
  35.  
  36. fclose(fp);
  37. fp=NULL;
  38.  
  39. return 0;
  40. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用w的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. int a = 10;
  2. float f = 12.34;
  3. double d = 12345.6789;
  4. char c = 'a';

定義四個變量,並對它們進行初始化。

上述代碼中,以下代碼:

  1. fprintf(fp, "%c %d %f %lf", c, a, f, d);

使用函數fprintf用格式化方法將上述四個變量寫入文件中。該函數與printf使用方法非常類似。

上述代碼中,以下代碼:

  1. float *pf = (float*)malloc(sizeof(float));

在堆上動態分配一個單精度浮點型變量。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

首先,使用函數fopen用r的方式重新打開文件file.c。

上述代碼中,以下代碼:

  1. char c1;
  2. int a1;
  3. float f1;
  4. double d1;

重新定義四個新的變量,但並不對它們進行初始化。

上述代碼中,以下代碼:

  1. fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);

使用函數fscanf用格式化方法從文件file.c中讀入數據到這四個新的變量中。該函數與scanf使用方法非常類似。

上述代碼中,以下代碼:

  1. printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);

使用函數printf輸出這四個新的變量值,已驗證讀入的效果。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

2.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","w");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11.  
  12. int a = 10;
  13. float f = 12.34;
  14. double d = 12345.6789;
  15. char c = 'a';
  16.  
  17. fprintf(fp, "%c %d %f %lf", c, a, f, d);
  18.  
  19. fclose(fp);
  20. fp=NULL;
  21.  
  22. fp=fopen("file.c","r");
  23. if(NULL==fp)
  24. {
  25. return -1;
  26. }
  27.  
  28. char c1;
  29. int a1;
  30. float f1;
  31. double d1;
  32.  
  33. fscanf(fp, "%c%d%f%lf", &c1, &a1, &f1, &d1);
  34. printf("%c\n%d\n%f\n%lf\n", c1, a1, f1, d1);
  35.  
  36. fclose(fp);
  37. fp=NULL;
  38.  
  39. return 0;
  40. }

3 使用fread()和fwrite()讀寫文件

3.1 問題

使用fwrite()和fread()讀寫int、double、字符串類型的數據,先寫入後讀取。

3.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:使用fread()和fwrite()讀寫文件

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main(void)
  5. {
  6. FILE*fp=NULL;
  7. fp=fopen("file.c","w");
  8. if(NULL==fp)
  9. {
  10. return -1;
  11. }
  12.  
  13. int a = 10;
  14. double d = 12345.6789;
  15. char str[1024] = "This is a string.";
  16.  
  17. fwrite(&a, sizeof(int), 1, fp);
  18. fwrite(&d, sizeof(double), 1, fp);
  19. int len = strlen(str) + 1;
  20. fwrite(&len, sizeof(int), 1, fp);
  21. fwrite(str, sizeof(char), len, fp);
  22.  
  23. fclose(fp);
  24. fp=NULL;
  25.  
  26. fp=fopen("file.c","r");
  27. if(NULL==fp)
  28. {
  29. return -1;
  30. }
  31.  
  32. int a1;
  33. double d1;
  34. char str1[1024];
  35.  
  36. fread(&a1, sizeof(int), 1, fp);
  37. fread(&d1, sizeof(double), 1, fp);
  38. int len1;
  39. fread(&len1, sizeof(int), 1, fp);
  40. fread(str1, sizeof(char), len, fp);
  41. printf("%d\n%lf\n%s\n", a1, d1, str1);
  42.  
  43. fclose(fp);
  44. fp=NULL;
  45.  
  46. return 0;
  47. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用w的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. int a = 10;
  2. double d = 12345.6789;
  3. char str[1024] = "This is a string.";

定義兩個變量和一個數組,並對它們進行初始化。

上述代碼中,以下代碼:

  1. fwrite(&a, sizeof(int), 1, fp);

使用fwrite函數將變量a寫入文件。該函數有四個參數,說明如下:

第一個參數為是一個指針,是要獲取寫入文件的數據的地址。

第二個參數為要寫入內容的單字節數。

第三個參數為要進行寫入第二個參數中字節的數據項的個數。

第四個參數為目標文件指針。

上述代碼中,以下代碼:

  1. fwrite(&d, sizeof(double), 1, fp);

使用fwrite函數將變量d寫入文件。

上述代碼中,以下代碼:

  1. int len = strlen(str) + 1;
  2. fwrite(&len, sizeof(int), 1, fp);
  3. fwrite(str, sizeof(char), len, fp);

使用fwrite函數將字符數組str寫入文件。寫入字符數組時,應先將該數組中字符串的長度存入文件,再存入字符串本身,這樣有理由讀文件時,定義讀取字符串的長度。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式重新打開文件file.c。

上述代碼中,以下代碼:

  1. int a1;
  2. double d1;
  3. char str1[1024];

重新定義兩個變量和一個數組,但並不對它們進行初始化。

上述代碼中,以下代碼:

  1. fread(&a1, sizeof(int), 1, fp);

使用fread函數從文件中讀入數據放在變量a1中。該函數有四個參數,說明如下:

第一個參數為是一個指針,是要將獲取的數據寫入到的地址。

第二個參數為要讀取內容的單字節數。

第三個參數為要進行讀取第二個參數中字節的數據項的個數。

第四個參數為目標文件指針。

上述代碼中,以下代碼:

  1. fread(&d1, sizeof(double), 1, fp);

使用fread函數從文件中讀入數據放在變量d1中。

上述代碼中,以下代碼:

  1. int len1;
  2. fread(&len1, sizeof(int), 1, fp);
  3. fread(str1, sizeof(char), len, fp);

使用fread函數從文件中讀入數據放在字符數組str中。在讀取字符串前,先讀取該字符串的長度,然後根據長度讀取字符串的內容。

上述代碼中,以下代碼:

  1. printf("%d\n%lf\n%s\n", a1, d1, str1);

使用printf函數驗證讀取的內容是否正確。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

3.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main(void)
  5. {
  6. FILE*fp=NULL;
  7. fp=fopen("file.c","w");
  8. if(NULL==fp)
  9. {
  10. return -1;
  11. }
  12.  
  13. int a = 10;
  14. double d = 12345.6789;
  15. char str[1024] = "This is a string.";
  16.  
  17. fwrite(&a, sizeof(int), 1, fp);
  18. fwrite(&d, sizeof(double), 1, fp);
  19. int len = strlen(str) + 1;
  20. fwrite(&len, sizeof(int), 1, fp);
  21. fwrite(str, sizeof(char), len, fp);
  22.  
  23. fclose(fp);
  24. fp=NULL;
  25.  
  26. fp=fopen("file.c","r");
  27. if(NULL==fp)
  28. {
  29. return -1;
  30. }
  31.  
  32. int a1;
  33. double d1;
  34. char str1[1024];
  35.  
  36. fread(&a1, sizeof(int), 1, fp);
  37. fread(&d1, sizeof(double), 1, fp);
  38. int len1;
  39. fread(&len1, sizeof(int), 1, fp);
  40. fread(str1, sizeof(char), len, fp);
  41. printf("%d\n%lf\n%s\n", a1, d1, str1);
  42.  
  43. fclose(fp);
  44. fp=NULL;
  45.  
  46. return 0;
  47. }

4 使用fread()和fwrite()讀寫文件(續1)

4.1 問題

輸入學生信息(學號、姓名、出生日期),然後用結構存儲數據,並讀寫入文件中。

4.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:使用fread()和fwrite()讀寫文件(續1)

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. struct student
  5. {
  6. int id;
  7. char name[20];
  8. char address[200];
  9. };
  10.  
  11. int main(void)
  12. {
  13. FILE*fp=NULL;
  14. fp=fopen("file.c","w");
  15. if(NULL==fp)
  16. {
  17. return -1;
  18. }
  19.  
  20. struct student stu = {10000, "zhangsan", "江蘇南京"};
  21.  
  22. fwrite(&stu, sizeof(struct student), 1, fp);
  23.  
  24. fclose(fp);
  25. fp=NULL;
  26.  
  27. fp=fopen("file.c","r");
  28. if(NULL==fp)
  29. {
  30. return -1;
  31. }
  32.  
  33. struct student stu1;
  34.  
  35. fread(&stu1, sizeof(struct student), 1, fp);
  36. printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);
  37.  
  38. fclose(fp);
  39. fp=NULL;
  40.  
  41. return 0;
  42. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用w的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. struct student stu = {10000, "zhangsan", "江蘇南京"};

定義一個結構體student的變量stu,並對它進行初始化。

上述代碼中,以下代碼:

  1. fwrite(&stu, sizeof(struct student), 1, fp);

使用fwrite函數將結構體student的變量stu寫入文件。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式重新打開文件file.c。

上述代碼中,以下代碼:

  1. struct student stu1;

重新定義一個結構體student的變量stu1,但並不對它進行初始化。

上述代碼中,以下代碼:

  1. fread(&stu1, sizeof(struct student), 1, fp);

使用fread函數從文件中讀入數據放在結構體student的變量stu1中。

上述代碼中,以下代碼:

  1. printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);

使用printf函數驗證讀取的內容是否正確。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

4.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. struct student
  5. {
  6. int id;
  7. char name[20];
  8. char address[200];
  9. };
  10.  
  11. int main(void)
  12. {
  13. FILE*fp=NULL;
  14. fp=fopen("file.c","w");
  15. if(NULL==fp)
  16. {
  17. return -1;
  18. }
  19.  
  20. struct student stu = {10000, "zhangsan", "江蘇南京"};
  21.  
  22. fwrite(&stu, sizeof(struct student), 1, fp);
  23.  
  24. fclose(fp);
  25. fp=NULL;
  26.  
  27. fp=fopen("file.c","r");
  28. if(NULL==fp)
  29. {
  30. return -1;
  31. }
  32.  
  33. struct student stu1;
  34.  
  35. fread(&stu1, sizeof(struct student), 1, fp);
  36. printf("%d %s %s\n", stu1.id, stu1.name, stu1.address);
  37.  
  38. fclose(fp);
  39. fp=NULL;
  40.  
  41. return 0;
  42. }

5 fseek()的使用

5.1 問題

測試fseek()的效果,包括三個不同的起始位置。

5.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:fseek()的使用

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main(void)
  5. {
  6. FILE*fp=NULL;
  7. fp=fopen("file.c","w+");
  8. if(NULL==fp)
  9. {
  10. return -1;
  11. }
  12.  
  13. char buf[] = "abcdefghijklmnopqrstuvwxyz";
  14.  
  15. fwrite(buf, sizeof(char), 26, fp);
  16.  
  17. fseek(fp, 0, SEEK_SET);
  18. memset(buf, 0, 26);
  19. fread(buf, sizeof(char), 10, fp);
  20. printf("%s\n", buf);
  21.  
  22. fseek(fp, 5, SEEK_CUR);
  23. memset(buf, 0, 26);
  24. fread(buf, sizeof(char), 10, fp);
  25. printf("%s\n", buf);
  26.  
  27. fseek(fp, -10, SEEK_END);
  28. memset(buf, 0, 26);
  29. fread(buf, sizeof(char), 10, fp);
  30. printf("%s\n", buf);
  31.  
  32. fclose(fp);
  33. fp=NULL;
  34.  
  35. return 0;
  36. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w+");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用w+的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. char buf[] = "abcdefghijklmnopqrstuvwxyz";

定義一個字符數組buf,並初始化為一個字符串。

上述代碼中,以下代碼:

  1. fwrite(buf, sizeof(char), 26, fp);

使用fwrite函數將字符串buf寫入文件。

上述代碼中,以下代碼:

  1. fseek(fp, 0, SEEK_SET);
  2. memset(buf, 0, 26);
  3. fread(buf, sizeof(char), 10, fp);
  4. printf("%s\n", buf);

首先,使用函數fseek設置文件指針fp的位置為文件頭開始的第一個字節。該函數有三個參數,說明如下:

第一個參數為目標文件指針。

第二個參數為從第三個參數開始的偏移量,為正數時向後偏移,為負數時向前偏移。

第三個參數為偏移的起始位置。

然後,使用memset函數將字符串buf清空。

下一步,使用fread函數從文件當前設定位置讀入10個字符。

最後,使用printf函數驗證讀入的字符是從文件開頭第一個字節開始的10個字符。

上述代碼中,以下代碼:

  1. fseek(fp, 5, SEEK_CUR);
  2. memset(buf, 0, 26);
  3. fread(buf, sizeof(char), 10, fp);
  4. printf("%s\n", buf);

首先,使用函數fseek設置文件指針fp的位置為文件當前位置向後偏移5個字節的位置。

然後,使用memset函數將字符串buf清空。

下一步,使用fread函數從文件當前設定位置讀入10個字符。

最後,使用printf函數驗證讀入的字符是從文件當前位置向後偏移5個字節開始的10個字符。

上述代碼中,以下代碼:

  1. fseek(fp, -10, SEEK_END);
  2. memset(buf, 0, 26);
  3. fread(buf, sizeof(char), 10, fp);
  4. printf("%s\n", buf);

首先,使用函數fseek設置文件指針fp的位置為文件尾開始向前偏移10個字節的位置。

然後,使用memset函數將字符串buf清空。

下一步,使用fread函數從文件當前設定位置讀入10個字符。

最後,使用printf函數驗證讀入的字符是從文件尾開始向前偏移10個字節開始的10個字符。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

5.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int main(void)
  5. {
  6. FILE*fp=NULL;
  7. fp=fopen("file.c","w+");
  8. if(NULL==fp)
  9. {
  10. return -1;
  11. }
  12.  
  13. char buf[] = "abcdefghijklmnopqrstuvwxyz";
  14.  
  15. fwrite(buf, sizeof(char), 26, fp);
  16.  
  17. fseek(fp, 0, SEEK_SET);
  18. memset(buf, 0, 26);
  19. fread(buf, sizeof(char), 10, fp);
  20. printf("%s\n", buf);
  21.  
  22. fseek(fp, 5, SEEK_CUR);
  23. memset(buf, 0, 26);
  24. fread(buf, sizeof(char), 10, fp);
  25. printf("%s\n", buf);
  26.  
  27. fseek(fp, -10, SEEK_END);
  28. memset(buf, 0, 26);
  29. fread(buf, sizeof(char), 10, fp);
  30. printf("%s\n", buf);
  31.  
  32. fclose(fp);
  33. fp=NULL;
  34.  
  35. return 0;
  36. }

6 ftell()的使用

6.1 問題

使用ftell()獲取文件的大小。

6.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:ftell()的使用

代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","r");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11.  
  12. fseek(fp, 0, SEEK_END);
  13. long len = ftell(fp);
  14.  
  15. printf("文件長度為:%ld個字節\n", len);
  16.  
  17. fclose(fp);
  18. fp=NULL;
  19.  
  20. return 0;
  21. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. fseek(fp, 0, SEEK_END);

使用函數fseek設置文件指針fp的位置為文件尾開始的第一個字節。

上述代碼中,以下代碼:

  1. long len = ftell(fp);

使用函數ftell獲得指定文件的文件指針當前位置距離文件頭的第一個字節的字節數。如果文件當前位置在文件尾開始的第一個字節,即文件最後一個字節的下一個位置,則將得到文件長度。

上述代碼中,以下代碼:

  1. printf("文件長度為:%ld個字節\n", len);

打印文件長度。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

6.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp=NULL;
  6. fp=fopen("file.c","r");
  7. if(NULL==fp)
  8. {
  9. return -1;
  10. }
  11.  
  12. fseek(fp, 0, SEEK_END);
  13. long len = ftell(fp);
  14.  
  15. printf("文件長度為:%ld個字節\n", len);
  16.  
  17. fclose(fp);
  18. fp=NULL;
  19.  
  20. return 0;
  21. }

7 字符的輸入輸出

7.1 問題

使用字符的輸入輸出函數實現文件的復制。

7.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:字符的輸入輸出

代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp = NULL;
  6. fp = fopen("file.c","r");
  7. if(NULL == fp)
  8. {
  9. return -1;
  10. }
  11. FILE*fp1 = NULL;
  12. fp1 = fopen("file副本.c","w");
  13. if(NULL == fp1)
  14. {
  15. return -1;
  16. }
  17.  
  18. char ch;
  19. while ((ch = getc(fp)) != EOF)
  20. putc(ch, fp1);
  21.  
  22. fclose(fp);
  23. fp=NULL;
  24. fclose(fp1);
  25. fp=NULL;
  26.  
  27. return 0;
  28. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用w的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. char ch;
  2. while ((ch = getc(fp)) != EOF)
  3. putc(ch, fp1);

首先,在循環的結束條件處,使用函數getc從文件fp中讀入一個字符。

然後,在循環體內,將讀入的字符寫入到另一個文件fp1中。

最後,設置一個循環,逐個字節地讀入文件fp的內容,再逐個字節的寫入文件fp1,直到文件fp結束,即讀入的字節是EOF。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fclose(fp1);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

7.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2.  
  3. int main(void)
  4. {
  5. FILE*fp = NULL;
  6. fp = fopen("file.c","r");
  7. if(NULL == fp)
  8. {
  9. return -1;
  10. }
  11. FILE*fp1 = NULL;
  12. fp1 = fopen("file副本.c","w");
  13. if(NULL == fp1)
  14. {
  15. return -1;
  16. }
  17.  
  18. char ch;
  19. while ((ch = getc(fp)) != EOF)
  20. putc(ch, fp1);
  21.  
  22. fclose(fp);
  23. fp=NULL;
  24. fclose(fp1);
  25. fp=NULL;
  26.  
  27. return 0;
  28. }

8 字符串函數的使用

8.1 問題

使用sscanf()和sprintf()處理字符串。

8.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:字符串函數的使用

代碼如下所示:

  1. #include
  2. #include
  3. #include
  4.  
  5. int main(void)
  6. {
  7. FILE*fp=NULL;
  8. fp=fopen("file.c","w");
  9. if(NULL==fp)
  10. {
  11. return -1;
  12. }
  13.  
  14. char buf[] = "abcdefghijklmnopqrstuvwxyz";
  15. fprintf(fp, "%lu%s", strlen(buf), buf);
  16.  
  17. fclose(fp);
  18. fp=NULL;
  19.  
  20. fp=fopen("file.c","r");
  21. if(NULL==fp)
  22. {
  23. return -1;
  24. }
  25.  
  26. char *buf1;
  27. int len;
  28. fscanf(fp, "%d", &len);
  29. buf1 = malloc(len) + 1;
  30. fscanf(fp, "%s", buf1);
  31. buf1[len] = 0;
  32. printf("%s\n", buf1);
  33.  
  34. fclose(fp);
  35. fp=NULL;
  36.  
  37. return 0;
  38. }

上述代碼中,以下代碼:

  1. FILE*fp=NULL;

定義一個FILE類型的指針fp。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","w");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式打開一個文件file.c。

上述代碼中,以下代碼:

  1. char buf[] = "abcdefghijklmnopqrstuvwxyz";

定義一個字符數組buf,並對其進行初始化。

上述代碼中,以下代碼:

  1. fprintf(fp, "%lu%s", strlen(buf), buf);

使用函數fprintf將字符數組buf保存到文件中。

注意:在保存之前應先保存字符數組buf中的字符串長度。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

上述代碼中,以下代碼:

  1. fp=fopen("file.c","r");
  2. if(NULL==fp)
  3. {
  4. return -1;
  5. }

使用函數fopen用r的方式重新打開文件file.c。

上述代碼中,以下代碼:

  1. char *buf1;
  2. int len;

首先,定義一個字符指針buf1。

然後,定義一個整型變量len。

上述代碼中,以下代碼:

  1. fscanf(fp, "%d", &len);
  2. buf1 = malloc(len) + 1;

首先,使用fscanf函數從文件中讀入字符串的長度到變量len中。

然後,根據len中的值使用malloc函數為字符指針buf1申請存儲空間。加1是為了給字符串結束符\0留出位置。

上述代碼中,以下代碼:

  1. fscanf(fp, "%s", buf1);
  2. buf1[len] = 0;
  3. printf("%s\n", buf1);

首先,使用fscanf函數從文件中從文件中讀入字符串。

然後,將字符數組buf1中的最後一個字節置為\0。

最後,使用printf函數驗證讀入的內容。

上述代碼中,以下代碼:

  1. fclose(fp);
  2. fp=NULL;

使用函數fclose關閉打開的文件。

8.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3. #include
  4.  
  5. int main(void)
  6. {
  7. FILE*fp=NULL;
  8. fp=fopen("file.c","w");
  9. if(NULL==fp)
  10. {
  11. return -1;
  12. }
  13.  
  14. char buf[] = "abcdefghijklmnopqrstuvwxyz";
  15. fprintf(fp, "%lu%s", strlen(buf), buf);
  16.  
  17. fclose(fp);
  18. fp=NULL;
  19.  
  20. fp=fopen("file.c","r");
  21. if(NULL==fp)
  22. {
  23. return -1;
  24. }
  25.  
  26. char *buf1;
  27. int len;
  28. fscanf(fp, "%d", &len);
  29. buf1 = malloc(len) + 1;
  30. fscanf(fp, "%s", buf1);
  31. buf1[len] = 0;
  32. printf("%s\n", buf1);
  33.  
  34. fclose(fp);
  35. fp=NULL;
  36.  
  37. return 0;
  38. }

9 可變長參數的使用

9.1 問題

可變長函數參數是指定義一個函數,該函數的參數個數為不確定的值,如printf函數。

9.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:可變長參數的使用

代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int max(int cnt, ...)
  5. {
  6. va_list v;
  7. va_start(v, cnt);
  8.  
  9. int maxvalue = va_arg(v, int);
  10. for(int i = 1; i < cnt; i++)
  11. {
  12. int data = va_arg(v, int);
  13. if(data > maxvalue)
  14. maxvalue = data;
  15. }
  16. va_end(v);
  17.  
  18. return maxvalue;
  19. }
  20.  
  21. int main(void)
  22. {
  23. int maxNum = max(10, 55, 34, 28, 16, 47, 62, 77, 86, 91, 9);
  24. printf("最大數為:%d\n", maxNum);
  25.  
  26. return 0;
  27. }

上述代碼中,以下代碼:

  1. int max(int cnt, ...)
  2. {
  3. va_list v;
  4. va_start(v, cnt);
  5.  
  6. int maxvalue = va_arg(v, int);
  7. for(int i = 1; i < cnt; i++)
  8. {
  9. int data = va_arg(v, int);
  10. if(data > maxvalue)
  11. maxvalue = data;
  12. }
  13. va_end(v);
  14.  
  15. return maxvalue;
  16. }

定義了一個函數max。用於求參數中的最大值。在該函數中,以下語句:

  1. va_list v;

定義可變長參數表變量v。在該函數中,以下語句:

  1. va_start(v, cnt);

使用函數va_start將參數cnt之後的那些參數保存到v中。在該函數中,以下語句:

  1. int maxvalue = va_arg(v, int);

使用函數va_arg從參數表中取一個int類型參數放入變量maxvalue中,並假設maxvalue保存的是所有參數中的最大值。在該函數中,以下語句:

  1. int data = va_arg(v, int);
  2. if(data > maxvalue)
  3. maxvalue = data;

首先,使用函數va_arg從參數表中取一個int類型參數放入變量data中。

然後,將變量data與變量maxvalue對比,如果data大於maxvalue,則將data賦值給maxvalue,以保證maxvalue中保存的永遠是最大值。在該函數中,以下語句:

  1. for(int i = 1; i < cnt; i++)
  2. {
  3. int data = va_arg(v, int);
  4. if(data > maxvalue)
  5. maxvalue = data;
  6. }

設置循環,將cnt後的參數,逐個遍歷,找出最大值。在該函數中,以下語句:

  1. va_end(v);

使用函數va_end釋放可變長參數表v。

上述代碼中,以下代碼:

  1. int main(void)
  2. {
  3. int maxNum = max(10, 55, 34, 28, 16, 47, 62, 77, 86, 91, 9);
  4. printf("最大數為:%d\n", maxNum);

在主函數中,使用函數max,找出參數中的最大值,並輸出。

9.3 完整代碼

本案例的完整代碼如下所示:

  1. #include
  2. #include
  3.  
  4. int max(int cnt, ...)
  5. {
  6. va_list v;
  7. va_start(v, cnt);
  8.  
  9. int maxvalue = va_arg(v, int);
  10. for(int i = 1; i < cnt; i++)
  11. {
  12. int data = va_arg(v, int);
  13. if(data > maxvalue)
  14. maxvalue = data;
  15. }
  16. va_end(v);
  17.  
  18. return maxvalue;
  19. }
  20.  
  21. int main(void)
  22. {
  23. int maxNum = max(10, 55, 34, 28, 16, 47, 62, 77, 86, 91, 9);
  24. printf("最大數為:%d\n", maxNum);
  25.  
  26. return 0;
  27. }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved