C++ 程式第一次運行正常,第二次運行(或循環內多次讀取)時出現異常行為、崩潰或跳過輸入。程式碼混用 gets_s() 讀取字串與 cin >> ch 讀取字符。
char line[100];
gets_s(line); // ① 讀取整行(含空格),消費換行符 '\n'
char ch;
cin >> ch; // ② 讀取字符,**跳過空白字符(含換行符)**,但後續殘留換行符
// 第三次循環 gets_s 讀到空行,或 cin 讀取失敗
核心衝突:gets_s 屬 C 標準庫,直接操作 stdin 緩衝區;cin 屬 C++ iostream,有獨立緩衝區且默認與 stdio 同步。兩者混用會導致緩衝區狀態不一致、殘留字符干擾後續讀取。
#include
#include
using namespace std;
int main() {
string line;
cout << "輸入字符串:";
getline(cin, line); // 安全、無長度限制、自動處理換行符
char ch;
cout << "輸入字符:";
cin >> ch; // 讀取字符,自動跳過前導空白
cin.ignore(numeric_limits::max(), '\n'); // 清理殘留換行符
// 業務邏輯...
return 0;
}
#include
#include
int main() {
char line[100];
printf("輸入字符串:");
fgets(line, sizeof(line), stdin); // 安全替代 gets_s
line[strcspn(line, "\n")] = 0; // 移除結尾換行符
char ch;
printf("輸入字符:");
scanf(" %c", &ch); // 格式串前加空格,跳過空白字符
// 業務邏輯...
return 0;
}
ios::sync_with_stdio(true); // 強制同步(默認即為 true)
cin.tie(nullptr); // 解除 cin/cout 綁定(可選,提速)
// 但仍不推薦混用,極易出錯
// 原程式碼邏輯錯誤:while 循環條件與內部 i 遞增邏輯衝突
while(line[i] != '\0') {
while(line[i] != ch) i++; // 若找不到 ch,i 會越界訪問 line[len] 導致 UB
// ...
}
// 修正:使用標準庫算法
#include
char* pos = find(line, line + strlen(line), ch);
if (pos != line + strlen(line)) {
// 找到 ch,執行移除邏輯
memmove(pos, pos + 1, strlen(pos));
}
gets_s/gets:C11 可選、C++17 棄用、極易緩衝區溢出iostream 或全用 C stdio,切勿混用std::string + 算法:安全、可讀、無手動記憶體管理cin.ignore() / scanf(" %c") 空格跳過空白重構為現代 C++ 風格(std::string、getline、algorithm)後,程式將穩定、可讀、無緩衝區殘留問題。