天天看點

C++小白到專家之for語句進階

作者:忠陸先森

引言

今天我們将從三個方面介紹for語句的應用,先講解什麼是超長整型,break語句與continue語句的用法,以及通過三個應用例子完成for語句的全部教程。

超長整型與資料溢出

超長整型(long long)是一種整型資料類型,它比标準的整型(int)擁有更大的存儲空間,能夠表示更大範圍的整數。在C++中,超長整型的取值範圍通常為-9223372036854775808到9223372036854775807。

資料溢出是指當一個變量的值超出了它所能表示的範圍時發生的情況。例如,當一個int類型的變量被賦予一個超過其取值範圍的值時,就會發生資料溢出。資料溢出可能會導緻程式運作錯誤,甚至崩潰。

為了避免資料溢出,我們可以采取以下措施:

  1. 在需要表示較大整數時使用超長整型。
  2. 在進行數值運算時注意檢查結果是否超出了變量的取值範圍。
  3. 使用異常處理機制來捕獲并處理資料溢出。

下面我們通過一個例子來給大家示範,阿凡提的故事是可以說是家喻戶曉了的,其中阿凡提和國王在棋盤放小麥的故事是一個經典的故事,它講述了阿凡提向國王提出了一個要求:在棋盤的第一格放一粒小麥,第二格放兩粒,第三格放四粒,以此類推,直到第64格。國王同意了阿凡提的要求,但當他開始放小麥時,才發現這個要求實際上是非常巨大的。

這個故事可以用來說明超長整型的用法。我們可以編寫一個程式來計算棋盤上第64格中應該放多少粒小麥。下面是一個簡單的C++程式,它使用超長整型來存儲結果:

#include <iostream>
using namespace std;

int main() {
    long long sum,n; // 定義超長整型變量sum,并初始化為1
    sum = 0;
    n = 1;
    for (int i = 1; i < 64; i++) {
        n *= 2; // 每次循環将n乘以2
        sum += n;
        cout << "第"<<i<<"格中應該放 " << n << " 粒小麥" << endl;
    }
    cout << "總數: " << sum << endl;
    return 0;
}

           
第1格中應該放2粒小麥
第2格中應該放4粒小麥
...
第63格中應該放-9223372036854775808粒小麥
第64格中應該放0粒小麥
總數:-2
           

為什麼會這樣呢?因為運算過程中産生的資料實在是太大了,超出了超長整型資料可表示的範圍,造成了資料溢出了。

總之,超長整型與資料溢出是C++程式設計中需要注意的問題。通過合理使用超長整型和避免資料溢出,我們可以編寫出更加健壯和可靠的程式。

break語句與continue語句

continue語句的作用是跳過目前循環的剩餘部分,直接進入下一次循環。它通常和if語句配合使用,用來實作某些條件下的循環跳過。例如,如果我們想要輸出1到10之間的所有奇數,我們可以用continue語句來實作:

for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) { // 如果i是偶數
        continue; // 跳過本次循環
    }
    cout << i << " "; // 輸出i
}
           

輸出結果是:

1 3 5 7 9
           

break語句的作用是終止目前循環,跳出循環體。它通常和if語句配合使用,用來實作某些條件下的循環終止。例如,如果我們想要輸出1到10之間的所有素數,我們可以用break語句來實作:

for (int i = 2; i <= 10; i++) {
    bool isPrime = true; // 假設i是素數
    for (int j = 2; j < i; j++) { // 周遊i之前的所有數
        if (i % j == 0) { // 如果i能被j整除
            isPrime = false; // i不是素數
            break; // 終止内層循環
        }
    }
    if (isPrime) { // 如果i是素數
        cout << i << " "; // 輸出i
    }
}
           

輸出結果是:

2 3 5 7
           

continue和break語句在C++中的差別和聯系如下:

  • 差別:continue語句隻跳過本次循環,不影響後續循環;break語句直接結束目前循環,不再執行後續循環。
  • 聯系:continue和break語句都可以用來控制循環結構的執行流程,提高程式的效率和靈活性;continue和break語句都隻對最近的一層循環起作用,如果有多層嵌套循環,需要使用标簽或者其他方法來跳出指定的循環。

希望這個章節能夠幫助你了解C++中的continue和break語句。

應用執行個體

水仙花數

水仙花數是一種特殊的自幂數,它的每個位上的數字的幂次之和等于它本身。例如,153是一個水仙花數,因為153 = 1^3 + 5^3 + 3^3。水仙花數的名字來源于中國古代數學家陳壽祺的《算法統宗》,他将這類數比喻為“出淤泥而不染”的水仙花。

要用C++判斷一個數是否是水仙花數,我們需要先求出這個數的位數,然後分别求出每個位上的數字,再計算它們的幂次之和,最後和原來的數比較是否相等。我們可以用for語句來實作這個過程,如下所示:

bool isNarcissistic(int n) { // 定義一個函數,判斷一個數是否是水仙花數
    int digits = 0; // 初始化位數為0
    int sum = 0; // 初始化幂次之和為0
    int temp = n; // 用一個臨時變量存儲原來的數
    while (temp > 0) { // 循環求出位數
        digits++; // 每次循環位數加1
        temp /= 10; // 每次循環除以10
    }
    temp = n; // 重新指派臨時變量
    for (int i = 0; i < digits; i++) { // 循環求出每個位上的數字和幂次之和
        int digit = temp % 10; // 求出目前位上的數字
        sum += pow(digit, digits); // 計算目前位上數字的幂次并累加到和中
        temp /= 10; // 每次循環除以10
    }
    return sum == n; // 傳回幂次之和是否等于原來的數
}
           

要用C++輸出一個範圍内的所有水仙花數,我們可以用一個for語句周遊這個範圍,然後用上面定義的函數判斷每個數是否是水仙花數,如果是就輸出。例如,如果我們想要輸出100到1000之間的所有水仙花數,我們可以寫如下代碼:

for (int i = 100; i < 1000; i++) { // 周遊100到1000之間的所有數
    if (isNarcissistic(i)) { // 如果目前數是水仙花數
        cout << i << " "; // 輸出目前數
    }
}
           

輸出結果是:

153 370 371 407 
           

回文數

回文數是一種對稱的數,它的每個位上的數字從左到右和從右到左都是一樣的。例如,121,12321,99999都是回文數。回文數的名字來源于回文詩,它是一種古老的詩歌形式,它的每個字從左到右和從右到左都是一樣的。例如,下面這首詩就是一個回文詩:

莺啼岸柳弄春晴,
柳弄春晴夜月明。
明月夜晴春弄柳,
晴春弄柳岸啼莺。
           

要用C++反轉一個數,我們可以用一個for語句從右到左依次取出每個位上的數字,然後用一個變量累加它們的逆序。例如,如果我們想要反轉12345,我們可以寫如下代碼:

int reverse(int n) { // 定義一個函數,反轉一個數
    int result = 0; // 初始化結果為0
    for (int i = n; i > 0; i /= 10) { // 循環從右到左取出每個位上的數字
        int digit = i % 10; // 取出目前位上的數字
        result = result * 10 + digit; // 将結果乘以10再加上目前位上的數字
    }
    return result; // 傳回結果
}
           

要用C++判斷一個數是否是回文數,我們可以用上面定義的函數反轉這個數,然後和原來的數比較是否相等。我們可以用一個簡單的if語句來實作這個判斷,如下所示:

bool isPalindrome(int n) { // 定義一個函數,判斷一個數是否是回文數
    if (n == reverse(n)) { // 如果原來的數和反轉後的數相等
        return true; // 傳回真
    } else { // 否則
        return false; // 傳回假
    }
}
           

要用C++輸出一個範圍内的所有回文數,我們可以用一個for語句周遊這個範圍,然後用上面定義的函數判斷每個數是否是回文數,如果是就輸出。例如,如果我們想要輸出100到1000之間的所有回文數,我們可以寫如下代碼:

for (int i = 100; i < 1000; i++) { // 周遊100到1000之間的所有數
    if (isPalindrome(i)) { // 如果目前數是回文數
        cout << i << " "; // 輸出目前數
    }
}
           

輸出結果是:

101 111 121 131 141 151 161 171 181 191 202 212 222 232 242