首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ LeetCode 題解:Z 字形變換中 unsigned 與 signed 比較陷阱

     編輯:程式設計疑難解答

問題現象

LeetCode 第 6 題「Z 字形變換」實作中,條件判斷 if((k*num+i*x) >= s.size()) 在明明應為 false 時卻進入了 if 區塊,導致邏輯錯誤。

根本原因:型別隱式轉換陷阱

// s.size() 回傳 size_t (unsigned long long)
// k*num+i*x 為 int (可能為負數)
if ((k*num+i*x) >= s.size())  // 危險!負數轉 unsigned 變極大正數

詳細過程

  1. s.size() 回傳 size_t(無號整數,通常 64 位)
  2. k*num+i*x 計算結果為 int(有號,可能為 -1)
  3. 比較時,int 隱式轉換為 size_t
  4. -1 轉 size_t 變成 18446744073709551615 (2^64-1)
  5. 條件判斷變成 巨大數值 >= 14 → true

修正方法

方法一:強制轉型(最直接)

if ((k*num+i*x) >= (int)s.size())

方法二:統一使用有號型別

int len = (int)s.size();
if ((k*num+i*x) >= len)

方法三:避免負數索引(邏輯層面修正)

int idx = k*num + i*x;
if (idx < 0 || idx >= (int)s.size()) break;

完整修正後核心邏輯

string convert(string s, int numRows) {
    if (numRows <= 1) return s;
    int n = s.length();
    int cycle = 2 * numRows - 2;
    string result;
    
    for (int row = 0; row < numRows; ++row) {
        for (int i = row; i < n; i += cycle) {
            result += s[i];
            // 中間行有第二個字符
            if (row != 0 && row != numRows - 1) {
                int second = i + cycle - 2 * row;
                if (second < n) result += s[second];
            }
        }
    }
    return result;
}

C++ 型別比較鐵律

場景風險防範
signed 與 unsigned 比較負數變巨大正數統一轉為 signed 或用 static_cast
size_t 與 int 比較同上(int)vec.size()
容器索引運算減法產生負數先判斷邊界再運算

編譯器警告

啟用 -Wsign-compare (GCC/Clang) 或 /W4 (MSVC) 可在編譯期捕獲此類問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved