前端學習C語言

2023-06-15 12:00:27

常數、運運算元、控制和迴圈

前文我們寫了第一個 c 語言程式,瞭解了基本的資料型別。本篇將繼續學習:常數運運算元控制語句迴圈語句

常數

#define 常數

#define是用來定義常數宏的預處理指令。定義常數的一般形式:#define 常數名 常數值。就像這樣:

#define MAX_NUM 100   // 定義整型常數 MAX_NUM 並初始化為 100
#define PI 3.1415926   // 定義雙精度浮點型常數 PI 並初始化為 3.1415926

使用 #define 宏定義所定義的常數是不可修改的(const 定義的能被修改),編譯器在編譯時會將所有程式碼中用宏定義表示的常數進行替換的操作,即文字替換。這意味著,程式在執行時並沒有儲存這些常數的值,而是直接使用它們的值來進行計算。例如,以下程式碼中:

#define MAX_NUM 100

int arr[MAX_NUM];  // 這裡的 MAX_NUM 在編譯時會被替換成 100

在編譯期間,編譯器會將程式碼中的 MAX_NUM 替換成 100,因此程式實際上是使用整數值 100 來宣告陣列 arr 的大小。

const

const 關鍵字所定義的常數是可以被修改的。雖然 const 常數不能作為左值(即不能出現在賦值語句的左邊),但是通過指標可以修改其所指向的變數的值。請看範例:

#include<stdio.h>

int main() {
   // 使用 const 關鍵字定義一個常數
   const int val =5;

   // 使用指標存取該常數
   int *ptr= (int*)&val;
   *ptr=10;// 修改儲存單元的值

   printf("val = %d\n",val);// 輸出:val = 5
   printf("*ptr = %d\n", *ptr);// 輸出:*ptr = 10

   return 0;
}

雖然我們通過指標存取了 val 的儲存單元並將其中的值修改為了 10,但是 val 的值仍然是 5,這是因為 val 被定義為一個 const 常數,所以編譯器會對其進行優化。具體來說,編譯器可能會在程式中使用 val 的地方直接替換成常數 5,而不是實際讀取 val 所在的儲存單元的值。這樣做可以提高程式的效率。

Tip:我們應該遵守 const 常數的規定,不要嘗試通過任何方法來修改 const 常數。

const vs #define

在定義常數時,使用#defineconst關鍵字都可以實現相同的功能,但是建議優先使用 const 關鍵字來定義常數。原因如下:

1.型別安全:const 常數有具體的型別資訊,而使用 #define 宏定義常數是不具備型別資訊的。在使用 #define 定義常數時,如果某個常數錯誤地被用於另一種資料型別的處理過程中,編譯器無法發現這樣的錯誤。而使用 const 常數定義常數可以有效避免這種型別錯誤。
1. 可讀性可維護性:通過使用 const 來定義常數,可以使程式碼更加清晰和易於閱讀,降低出錯率,並且增強了程式的可維護性。相比之下,使用 #define 宏定義的常數只是簡單的文字替換,執行程式碼後看不到定義的常數值,容易對程式的可讀性造成影響,難以維護和擴充套件。
1.編譯器優化:對於 const 常數,編譯器會將其存放在記憶體的唯讀區域,從而避免了意外修改它們的值。而使用 #define 宏定義的常數只是簡單的文字替換,這意味著編譯器無法進行優化。
1.作用域:const 常數定義的作用域只侷限於定義的檔案和其他使用該宣告的檔案,不影響其他檔案中的變數。而 #define 宏定義常數的作用域是全域性的,容易導致重名等問題。

因此,總體來說,使用 const 關鍵字定義常數可以使程式碼更加清晰、安全、易於維護,並且可以得到編譯器的優化作用,建議優先使用 const 來定義常數。

數值常數型別

  • 十進位制整數常數:
123 // 常數值為 123,預設是 int 型別
-456 // 常數值為 -456,也是 int 型別
1776L// 常數值為 1776,長整型
  • 進位制整數常數:以數位 0 到 7 組成,必須以 0 開頭,可以帶有字首 0 和同樣的標誌。例如:
05   // 常數值為 5,八進位製表示
077 // 常數值為 63,八進位製表示
031UL// 常數值為 25,無符號長整型
  • 十六進位制整數常數:以數位 0 到 9 和字母 A 到 F(或 a 到 f)組成,必須以 0x 或 0X 開頭,並且可以帶有同樣的標誌
0x1A // 常數值為 26,十六進位製表示
0XF00L// 常數值為 3840,長整型
0x3aUL// 常數值為 58,無符號長整型
  • 實型常數(即小數)
const float PI =3.1415926;
const double E =2.7182818284590452354;

字元常數型別

  • 字元常數:用單引號括起來的一個字元,可以是任意字元或跳脫序列,表示對應的 ASCII 碼值或 ANSI 碼值。例如:
'A'   // 常數值為 65,ASCII 碼值
'\n' // 常數值為 10,換行符
'\x41'// 常數值為 65,十六進位制值 A 的 ASCII 碼值
  • 字串常數:用雙引號括起來的一個字串,包含多個字元,以 \0(空字元)結尾。例如:
"This is a string"     // 常數值為字串的地址
"Hello, world!\n"     // 常數值為字串的地址
"Good\bmorning,\bKate"// 常數值為字串的地址,其中 \b 表示退格符

"Hello" 字串包含 5 個可見字元,但在 C 語言中,字串末尾需要新增一個表示字串結尾的 Null 字元 (\0),所以實際上這個字串佔用了 6 個位元組的記憶體空間。

在記憶體中,該字串被表示為一個字元陣列,如下所示:

+---+---+---+---+---+---+
|H|e|l|l|o|\0|
+---+---+---+---+---+---+

其中,每個字元都佔用一個位元組(8 位),最後一個空字元 \0 表示字串的結束,告訴程式不再繼續處理該字串。如果沒有 Null 字元,程式就無法區分字串何時停止,那麼在處理字串時可能會出現一些問題,特別是字串拼接和複製時。

:在字串拼接或複製時,目標字串必須具有足夠的記憶體空間,包括末尾的空字元 \0,否則可能導致緩衝區溢位或不可預期的結果。

定義一個字串常數。請看範例:

#include<stdio.h>

int main() {
   char*str="hello";
   printf("您輸入的字元是:%s\n",str);

   return 0;
}

將字串常數 "hello" 賦值給了指標變數 str,並使用 %s 格式符將其輸出。輸出結果為:您輸入的字元是:hello

跳脫字元

最重要的就是\n(換行符)、\t(水平製表符)。

在計算機程式設計中,跳脫字元(Escape Character)是以反斜槓(\)開頭的一個或多個字元的序列。這些字元被稱作跳脫序列,可以將一些特殊的字元插入到字串或字元常數中。

下面是一些常見的跳脫序列及其含義:

  • \' 單引號。用於在單引號字元常數中插入單引號本身,如:printf("'Hello' world\n");
  • \" 雙引號。用於在雙引號字串中插入雙引號本身,如:printf("a string with "double quotes"\n");
  • \\ 反斜槓。用於在字串中插入反斜槓本身,如:printf("C:\Windows\System32\n");
  • \n 換行符。用於在字串中插入一個換行符,如:printf("First line\nSecond line\n");
  • \t 水平製表符(Tab)。用於在字串中插入一個水平製表符,如:printf("Column1\tColumn2\tColumn3\n");
  • \r 回車符。用於將遊標位置移動至行首,如:printf("This is the first line.\rThis is the second line.\n");
  • \b 退格符。用於將遊標向左移動一個字元位置,如:printf("ab\bcd\n"); // 輸出 acd
  • \0 空字元。也叫空字元(Null character),通常用來表示字串的結束

在程式設計中,使用跳脫字元可以方便地處理特殊字元,充分利用了計算機的二進位制表示方法,並且讓程式碼更加靈活。

水平製表符

水平製表符是一種控制字元,通常用來在文字輸出中對齊內容或間隔資料欄位。

當程式遇到 \t 跳脫字元時,會在輸出中插入一個水平製表符,並將遊標移動到下一個製表符位置。這通常相當於將遊標向右移動到下一個 8、16 或 32 個字元的位置,具體取決於系統設定和螢幕寬度。

例如下面的程式碼會輸出帶有水平製表的兩列數位:

printf("1\t2\t3\n");
printf("10\t20\t30\n");

輸出如下:

1      2      3
10     20     30

第二行完美對齊了每個數位。這是因為第二行程式碼使用了水平製表符製作了對齊效果。

輸入和輸出

scanf()

下面通過 scanf() 輸入一個數位和一個字元。請看範例:

#include<stdio.h>

int main() {
   int num;
   char ch;

   printf("請輸入一個整數和一個字元(用空格隔開):");
   scanf("%d %c", &num, &ch);

   printf("您輸入的整數是:%d\n",num);
   printf("您輸入的字元是:%c\n",ch);

   return 0;
}

執行:

請輸入一個整數和一個字元(用空格隔開):123a
您輸入的整數是:123
您輸入的字元是:a

這裡,我們使用了scanf函數來讀取使用者輸入,讀取的格式為 %d %c,其中 %d 表示讀取一個整數%c 表示讀取一個字元。通過&num&ch的地址傳遞,將從終端讀取到的整數值和字元值分別儲存到定義好的變數 num 和 ch 中。

printf()

printf() 函數是C語言中用於輸出格式化字串的標準庫函數。下面是常用的一些輸出格式:

  • %d:將引數作為有符號十進位制整數列印。
  • %u:將引數作為無符號十進位制整數列印。
  • %o:將引數作為無符號八進位制數列印。
  • %x、%X:將引數作為無符號十六進位制數列印,分別使用小寫字母和大寫字母表示。
  • %f、%e、%E:將引數作為浮點數列印。使用 %f 時按小數形式輸出,使用 %e 或 %E 時按指數形式輸出。
  • %c:將引數作為字元列印。
  • %s:將引數作為字串列印。

在輸出格式中還可以使用其他控制字元來控制列印格式(例如空格、正負號等),也可以用 %% 來列印百分號字元。

下面是一個範例程式:

#include<stdio.h>

int main() {
    int n = 10;
    float f= 3.14159;
    char c ='A';
    char*str = "hello, world!";
    printf("整數:%d\n",n);
    printf("八進位制:%o\n",n);
    printf("十六進位制:%x\n",n);
    printf("浮點數(小數形式):%f\n",f);
    printf("浮點數(指數形式):%e\n",f);
    printf("字元:%c\n",c);
    printf("字串:%s\n",str);

    return 0;
}

輸出結果:

整數:10
八進位制:12
十六進位制:a
浮點數(小數形式):3.141590
浮點數(指數形式):3.141590e+00
字元:A
字串:hello,world!

運運算元

算數運運算元

C語言中常用算數運運算元:

  • +:加法運運算元。
  • -:減法運運算元。
  • *:乘法運運算元。
  • /:除法運運算元。
  • %:取模(或取餘)運運算元。

:整數相除,只保留整數部分。例如 10/3 不會是 3.333

請看範例:

#include<stdio.h>

int main() {
   int a = 10, b = 3;
   float c = 4.5, d = 2.0;

   printf("%d + %d = %d\n",a,b,a+b);
   printf("%d - %d = %d\n",a,b,a-b);
   printf("%d * %d = %d\n",a,b,a*b);
   printf("%d / %d = %d\n",a,b,a/b);// 整數相除,只保留整數部分
   printf("%d %% %d = %d\n",a,b,a%b);// 取餘運運算元 %
   printf("%.2f * %.2f = %.2f\n",c,d,c*d);
   printf("%.2f / %.2f = %.2f\n",c,d,c/d);// 浮點數相除,保留小數部分
   return 0;
}

輸出:

10+3=13
10-3=7
10*3=30
10/3=3
10%3=1
4.50*2.00=9.00
4.50/2.00=2.25

10 / 3 = 3。在C語言中,整數相除只保留整數部分是因為在計算機內部處理資料時使用的是二進位制數(0和1),而二進位制數是不能用來表示小數的。前面我們知道 float 表示數的方式和 int 不同。如果需要得到 3.3333,可使用浮點數進行除法運算。就像這樣:

inta=10,b=3;
floatresult= (float)a/ (float)b;
練習

題目:輸入數位並按照逆序輸出

實現:

#include<stdio.h>

int main() {
   int num,temp,reversed_num=0;

   printf("請輸入一個數位:");
   scanf("%d", &num);

   temp=num;
   while(temp!=0) {// 迴圈計算逆序數
       reversed_num=reversed_num*10+temp%10;
       temp/=10;
    }

   printf("您輸入的數位的逆序為:%d\n",reversed_num);

   return 0;
}

測試:

請輸入一個數位:6789
您輸入的數位的逆序為:9876

關係運算子

關係運算子是用於比較兩個值之間的大小或者關係的運運算元,例如大於(>)、小於(<)、等於(==)、大於等於(>=)、小於等於(<=)和不等於(!=)

邏輯運運算元

常見的有邏輯與 &&、邏輯或 ||、邏輯非 !

邏輯與和邏輯或都支援短路求值 :當左運算元已經能夠決定整個表示式的結果時,右運算元將不會被計算。例如,在 if (a && b) 中,如果變數 a 的值為 false,則無論變數 b 的值是什麼,整個表示式的結果一定是 false。

當邏輯非 ! 運運算元作用於一個非零值時,其結果為 false;當它作用於零值時,其結果為 true。

位運算

  1. 按位元(&):將兩個運算元對應的位進行邏輯與操作,即兩個位都為1時,結果才為1,否則為0。
    例如,6 & 3 = 2,二進位制為 0110 & 0011 = 0010。

  2. 按位元(|):將兩個運算元對應的位進行邏輯或操作,即兩個位中有一個為1時,結果就為1,否則為0。
    例如,6 | 3 = 7,二進位制為 0110 | 0011 = 0111。

  3. 按位元互斥或(^):將兩個運算元對應的位進行邏輯互斥或操作,即兩個位不相同時,結果為1,否則為0。
    例如,6 ^ 3 = 5,二進位制為 0110 ^ 0011 = 0101。

  4. 按位元取反(~):將運算元的每個位取反,即0變成1,1變成0。
    例如,~6 = -7,二進位制為 ~0110 = 1001。

  5. 左位移(<<):將運算元的各二進位制位全部左移若干位,高位丟棄,低位補0。
    例如,6 << 2 = 24,二進位制為 0110 前移2位補0,變為 011000 = 24。左移動兩位相當於乘以4。

  6. 右位移(>>):將運算元的各二進位制位全部右移若干位,低位丟棄,高位補0(對於正數)或補1(對於負數)。
    例如,6 >> 2 = 1,二進位制為 0110 後移2位補0,變為 0001 = 1。

練習1

題目:一組資料,例如 1 1 2 2 4 3 3,除了4出現1次,其他都出現兩次,請用互斥或快速找到只出現一次的數位,這裡是4。

分析:可以利用互斥或運算的性質來解決該問題。互斥或運算的規則是,相同的兩個數互斥或結果為0,不同的兩個數互斥或結果為1。

程式實現:

#include <stdio.h>  

int main()  
{  
    int arr[] = {1, 1, 2, 2, 4, 3, 3};  
    int n = sizeof(arr) / sizeof(arr[0]);  
    int result = 0;  
    for (int i = 0; i < n; i++) {  
        result ^= arr[i]; //互斥或操作  
    }  
    printf("只出現一次的數位是:%d\n", result);  
    return 0;  
}  
  1. 第一次迴圈:result = 0 ^ 1 = 1;
  2. 第二次迴圈:result = 1 ^ 1 = 0;
  3. 第三次迴圈:result = 0 ^ 2 = 2;
  4. 第四次迴圈:result = 2 ^ 2 = 0;
  5. 第五次迴圈:result = 0 ^ 4 = 4; //  0 xor 100(4的二進位制)得到 100(即十進位制的4)
  6. 第六次迴圈:result = 4 ^ 3 = 7; //  100 xor 11(3的二進位制)得到 111(即十進位制的7)
  7. 第七次迴圈:result = 7 ^ 3 = 4。 //  111 xor 11 得到 100(即十進位制的4)
練習2

題目:統計字元 a 在 ASCII 碼錶中對應的數位 97 的二進位制表示中有多少個 1

程式實現:

#include <stdio.h>

int main()
{
    int c = 97; // 字元 a 對應的ASCII碼值為 97
    int count = 0;
    for(int i = 0; i < 8; i++) {
        if(c & 1) {
            count++;
        }
        c >>= 1;
    }
    printf("字元 a 在ASCII碼錶中對應的數位 97 的二進位制表示中有 %d 個 1\n", count);
    return 0;
}

結果分析

  • 97的二進位制表示是 01100001
  • 字元是1個位元組,也就是8位元,所以迴圈8次
  • 接著就是用 a 的各位和1進行互斥或,如果結果是1,count 就加1。
第一次迴圈:i = 0,c & 1 的結果為 1,count 的值加 1,然後 c 右移一位,變成 00110000。

第二次迴圈:i = 1,c & 1 的結果為 0,不處理,然後 c 右移一位,變成 00011000。

第三次迴圈:i = 2,c & 1 的結果為 0,不處理,然後 c 右移一位,變成 00001100。

第四次迴圈:i = 3,c & 1 的結果為 0,不處理,然後 c 右移一位,變成 00000110。

第五次迴圈:i = 4,c & 1 的結果為 0,不處理,然後 c 右移一位,變成 00000011。

第六次迴圈:i = 5,c & 1 的結果為 0,不處理,然後 c 右移一位,變成 00000001。

第七次迴圈:i = 6,c & 1 的結果為 1,count 的值加 1,然後 c 右移一位,變成 00000000。

第八次迴圈:i = 7,c & 1 的結果為 1,count 的值加 1,然後 c 右移一位,變成 00000000。

賦值運運算元

=

a += 10 等於 a = a + 10

三目運運算元

例如:result = a > b ? a : b

Tip:單目運運算元:例如 a++。雙目運運算元: 例如 a + b

自增自減運運算元

請看範例:

#include <stdio.h>

int main()
{

   int a = 1;
    a += a++; // 筆者認為這句話等於:a = a + a; a++;
    printf("%d", a); // 所以是 3

    a = 1;
    a += ++a; //  筆者認為這句話等於:++a; a = a + a;
    printf("%d", a); // 所以是4
    return 0;
}

有的編譯器對該程式碼報錯如下:

/workspace/CProject-test/main.c:7:11: warning: unsequenced modification and access to 'a' [-Wunsequenced]  
a += a++; // a = a + a; a++;  
~~ ^  
/workspace/CProject-test/main.c:11:10: warning: unsequenced modification and access to 'a' [-Wunsequenced]  
a += ++a; // ++a; a = a + a;  
~~ ^  
2 warnings generated.  

其中 warning: unsequenced modification and access to 'a' [-Wunsequenced] 這個警告出現的原因是因為在同一表示式中有多個操作,而且這些操作對同一個變數進行修改和存取,並且它們之間沒有明確定義的順序。這種情況下,程式碼的行為是未定義的。

在看這段程式碼,請問 k 是多少:

int i = 3, k;  
k = (++i) + (++i) + (i++);  

該程式碼在騰訊雲和阿里雲中結果不相同。建議避免這種型別的表示式。

逗號運運算元

請看範例,這段程式碼會輸出什麼:

#include<stdio.h>
#include<unistd.h>

int main() {
   inti;
    // 逗號運運算元
   for(i=1; i<=3,printf("a"); i++) {
       printf("%d\n", i);
       sleep(1);
    }
   return 0;
}

該程式會一直執行下去。每秒輸出一行:

a1  
a2  
a3  
a4  
a5  
...   

這是因為表示式 i <= 3, printf("a") 實際上等價於 (i <= 3), printf("a"),其結果總是為 true。

控制結構

if

題目:用 if、else if、else 實現2個數位的計算,數位和操作符都通過 scanf 函數輸入。

程式實現(關注 if、else if、else 的用法即可):

#include<stdio.h>

int main() {
   double num1, num2;
   char operator;

   printf("計算2個數的加減乘除。例如 33 * 2:\n");
   scanf("%lf%c%*c%lf",&num1,&operator,&num2);

   if(operator=='+') {
       printf("%.2lf+%.2lf=%.2lf\n", num1, num2, num1+num2);
    }elseif(operator=='-') {
       printf("%.2lf-%.2lf=%.2lf\n", num1, num2, num1-num2);
    }elseif(operator=='*') {
       printf("%.2lf*%.2lf=%.2lf\n", num1, num2, num1*num2);
    }elseif(operator=='/') {
       if(num2==0) {
           printf("錯誤:除數不能為0。\n");
        }else{
           printf("%.2lf/%.2lf=%.2lf\n", num1, num2, num1/num2);
        }
    }else{
       printf("錯誤:無效的操作符。\n");
    }

   return 0;
}

測試:

開始執行...  

計算2個數的加減乘除。例如 33 * 2:  
33 * 2  
33.00 * 2.00 = 66.00  

執行結束。  
  • %lf 用於讀取雙精度浮點數並儲存到 num1 中。
  • %c 用於讀取一個字元並儲存到 operator 中。

switch

switch語句用來判斷一個表示式的值與若干個常數值中的哪一個相等,並執行相應的程式碼(可以和if互換)。其一般的語法格式如下:

switch (表示式){    
    case 常數1:        // 常數1匹配時執行的程式碼
        break;    
    case 常數2:        // 常數2匹配時執行的程式碼
        break;    
    ...    
    default:        // 表示式的值與所有常數都不匹配時執行的程式碼
        break;
}

其中,表示式為需要被判斷的值,而常數1、常數2等則為待匹配的常數值,需要用case關鍵字進行標識。如果表示式的值與某個常數相等,則執行相應的程式碼,並使用break語句跳出整個switch結構;如果表示式的值與所有常數都不匹配,則執行default後面的程式碼塊,並同樣使用break語句跳出整個switch結構。

需要注意的是,每個case語句都必須以一個常數值開頭,且後面必須緊跟一個冒號(:)。另外,case語句中的程式碼塊可以為空,但不能省略冒號。如果一個case語句的程式碼塊為空,且沒有接著的break語句,則程式會繼續執行下一個case語句的程式碼塊。

用 switch 重寫上述 if 的範例:

#include<stdio.h>

int main()
{
   doublenum1, num2;
   charoperator;

   printf("計算2個數的加減乘除。例如 33 * 2:\n");
   scanf("%lf%c%*c%lf",&num1,&operator,&num2);

   switch(operator)
    {
       case'+':
           printf("%.2lf+%.2lf=%.2lf\n", num1, num2, num1+num2);
           break;
       case'-':
           printf("%.2lf-%.2lf=%.2lf\n", num1, num2, num1-num2);
           break;
       case'*':
           printf("%.2lf*%.2lf=%.2lf\n", num1, num2, num1*num2);
           break;
       case'/':
           if(num2==0) {
               printf("錯誤:除數不能為0。\n");
            }else{
               printf("%.2lf/%.2lf=%.2lf\n", num1, num2, num1/num2);
            }
           break;
       default:
           printf("錯誤:無效的操作符。\n");
           break;
    }

   return 0;
}

測試:
這裡故意輸入一個無效操作符,進入 default。就像這樣:

開始執行...  

計算2個數的加減乘除。例如 33 * 2:  
1 # 2  
錯誤:無效的操作符。  

執行結束。  

:假如不小心將default輸錯,例如 defualt,再次測試 1 # 2,就不會在提示錯誤:無效的操作符。這是因為 defualt: 變成了 goto 標籤。在大型專案中較難發現此問題。

goto

在 C 語言中,goto 是一種流程控制語句,它可以直接跳轉到程式中的某個識別符號(通常是標籤 label),從而實現有選擇的跳轉或迴圈。語法格式如下:

// 定義標籤
label: statement;


// 跳轉到標籤
goto label;

goto 語句使用時需要小心謹慎,因為它會破壞程式碼結構的正常邏輯,使得程式難以理解和偵錯,建議只在特定情況下使用。

使用 goto 語句來實現在使用者輸入錯誤時重新輸入的功能。請看範例:

#include<stdio.h>

int main(void)
{
   int num;

start:
   printf("請輸入一個正整數:");
   scanf("%d",&num);

   if(num<=0)
    {
       printf("輸入錯誤,請重新輸入!\n");
       goto start;  // 跳轉到 start 標籤處重新開始輸入
    }

   printf("您輸入的正整數為:%d\n", num);

   return 0;
}

測試:

開始執行...  

請輸入一個正整數:-1  
輸入錯誤,請重新輸入!  
請輸入一個正整數:-2  
輸入錯誤,請重新輸入!  
請輸入一個正整數:-3  
輸入錯誤,請重新輸入!  
請輸入一個正整數:4  
您輸入的正整數為:4  

執行結束。  

迴圈語句

while

題目:假設房價為 100 萬元,每年漲幅為 5%,工資為 20 萬元,現在需要多少年才能買得起這套房子?

實現:

#include<stdio.h>

int main(void)
{
   double house_price = 100.0;  // 房價,單位:萬元
   const double interest_rate = 0.05;  // 每年增長率為 5%
   double annual_salary = 20.0;  // 年薪,單位:萬元
   double savings= 0.0;  // 積蓄,單位:萬元
   int year = 0;

   while(savings < house_price)
    {

        house_price *= (1 + interest_rate);  // 更新房價
        savings += annual_salary;  // 更新積蓄
        year++;
       printf("第%d年,房價為%.2lf萬元,積蓄為%.2lf萬元\n", year, house_price, savings);

    }

   printf("需要%d年後才能買得起這套房子\n", year);

   return 0;
}

輸出:

開始執行...  

第 1 年,房價為 105.00 萬元,積蓄為 20.00 萬元  
第 2 年,房價為 110.25 萬元,積蓄為 40.00 萬元  
第 3 年,房價為 115.76 萬元,積蓄為 60.00 萬元  
第 4 年,房價為 121.55 萬元,積蓄為 80.00 萬元  
第 5 年,房價為 127.63 萬元,積蓄為 100.00 萬元  
第 6 年,房價為 134.01 萬元,積蓄為 120.00 萬元  
第 7 年,房價為 140.71 萬元,積蓄為 140.00 萬元  
第 8 年,房價為 147.75 萬元,積蓄為 160.00 萬元  
需要 8 年後才能買得起這套房子  

執行結束。  

for

題目:用for 重寫 while 的範例

實現:

#include<stdio.h>

int main(void)
{
   doublehouse_price=100.0;  // 房價,單位:萬元
   constdoubleinterest_rate=0.05;  // 每年增長率為 5%
   doubleannual_salary=20.0;  // 年薪,單位:萬元
   doublesavings=0.0;  // 積蓄,單位:萬元
   intyear;  //年份

   for(year=1; savings<house_price; year++)
    {

        house_price*=(1+interest_rate);  // 更新房價
        savings+=annual_salary;  // 更新積蓄
       printf("第%d年,房價為%.2lf萬元,積蓄為%.2lf萬元\n", year, house_price, savings);

    }

   printf("需要%d年後才能買得起這套房子\n", year-1);

   return 0;
}

輸出與 while 相同:

開始執行...  

第 1 年,房價為 105.00 萬元,積蓄為 20.00 萬元  
第 2 年,房價為 110.25 萬元,積蓄為 40.00 萬元  
第 3 年,房價為 115.76 萬元,積蓄為 60.00 萬元  
第 4 年,房價為 121.55 萬元,積蓄為 80.00 萬元  
第 5 年,房價為 127.63 萬元,積蓄為 100.00 萬元  
第 6 年,房價為 134.01 萬元,積蓄為 120.00 萬元  
第 7 年,房價為 140.71 萬元,積蓄為 140.00 萬元  
第 8 年,房價為 147.75 萬元,積蓄為 160.00 萬元  
需要 8 年後才能買得起這套房子  

執行結束。  

跳回圈

continue只是跳過當前回圈的一部分,而break是跳出迴圈(完全終止迴圈)。兩者只能用於迴圈結構中,不能用於其他程式控制結構。

continue範例輸出1 3 5 7 9 

   inti;
   for(i=1; i<=10; i++)
    {
       if(i%2==0)// 只輸出奇數
           continue;
       printf("%d", i);// 輸出奇數
    }

break  範例輸出1 2 3 4 5

    intj;
   for(j=1; j<=10; j++)
    {
       if(j>5)// 只輸出前5個數
           break;
       printf("%d", j);// 輸出前5個數
    }

練習

練習1

題目:定整數範圍內找到能被 3 整除的數位,並按照每行5個數位的格式進行列印輸出

實現:

#include<stdio.h>

int main(void)
{
   inti;
   intcount=0;
   for(i=100; i<=200; i++)
    {
       if(i%3==0){
           printf("%d", i);
            count++;
           if(count==5){
               printf("\n");
                count=0;
            }

        }

    }
   return 0;
}

練習2

題目:輸入5個整數,求平均值

實現:

#include<stdio.h>

int main(void)
{
   inti;
   int num;
   doublesum=0;
   doubleaverage;

   printf("請輸入五個整數:\n");

   for(i=0; i<5; i++)
    {
       scanf("%d",&num);
        sum+=num;
    }

    average=sum/5.0;

   printf("這五個數的平均值為:%.1lf\n", average);

   return 0;
}

測試(以空格區分數位或回車區分都可以):

開始執行...  

請輸入五個整數:  
1 2 3 4 5  
這五個數的平均值為:3.0  

執行結束。  
開始執行...  

請輸入五個整數:  
3  
4  
5  
6  
7  
這五個數的平均值為:5.0  

執行結束。  

練習3

題目:有1,2,3,4 四個數位,能組成多少個互不相同且無重複數位的三位數,都是多少

實現:

#include<stdio.h>

int main(void) {
   intcount=0;

   printf("由 1、2、3、4 組成的所有互不相同且無重複數位的三位數有:\n");

   for(inti=1; i<=4; i++) {
       for(intj=1; j<=4; j++) {
           for(intk=1; k<=4; k++) {
               if(i!=j&&j!=k&&i!=k) {
                   int num=i*100+j*10+k;
                   printf("%d", num);
                    count++;
                }
            }
        }
    }

   printf("\n共計%d個三位數。\n", count);

   return 0;
}

輸出:

開始執行...  

由 1、2、3、4 組成的所有互不相同且無重複數位的三位數有:  
123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432  
共計 24 個三位數。  

執行結束。