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

Visual Studio 2012 中 C++ gets() 函數無法輸入字符串的原因分析

     編輯:程式設計疑難解答

問題代碼

#include <string>
#include <iostream>
using namespace std;

int main() {
    string ch;
    char *p = &ch[0];
    gets(p);
    cout << ch << endl;
    system("pause");
    return 0;
}

現象描述

在 VS2012 中運行上述代碼,程序無法通過 gets(p) 正常接收鍵盤輸入的字符串。

根本原因分析

1. string 對象內存佈局問題

  • string ch; 默認構造為空字符串,內部緩衝區大小為 0
  • &ch[0] 返回的是首字符引用,但空字符串無有效字符存儲空間
  • 向此地址寫入數據會導致**緩衝區溢出**,屬於未定義行為

2. gets() 函數的固有缺陷

  • 不檢查緩衝區邊界:極易導致緩衝區溢出漏洞
  • C11 標準已移除:VS2012 可能仍保留但強烈不推薦使用
  • 無法指定最大讀取長度:無法防止輸入超過分配空間

3. 代碼邏輯錯誤

  • cout << ch 輸出的是 string 對象本身,而非字符指針
  • 若使用 gets,應配合字符數組而非 string 內部緩衝區

正確解決方案

方案一:使用 C++ 風格的 std::getline(推薦)

#include <string>
#include <iostream>
using namespace std;

int main() {
    string ch;
    cout << "請輸入字符串: ";
    getline(cin, ch);  // 安全、自動管理內存、支持空格
    cout << "輸入內容: " << ch << endl;
    system("pause");
    return 0;
}

方案二:使用字符數組配合 fgets(C 風格兼容)

#include <cstdio>
#include <iostream>
using namespace std;

int main() {
    char buffer[256] = {0};  // 固定大小緩衝區
    cout << "請輸入字符串: ";
    fgets(buffer, sizeof(buffer), stdin);  // 安全讀取,包含換行符
    // 移除末尾換行符
    buffer[strcspn(buffer, "\n")] = '\0';
    cout << "輸入內容: " << buffer << endl;
    system("pause");
    return 0;
}

方案三:修正原代碼(僅供理解原理,不推薦生產使用)

#include <string>
#include <iostream>
#include <cstdio>  // gets 需要此頭文件
using namespace std;

int main() {
    string ch;
    ch.resize(255);  // 關鍵:預分配足夠空間
    char *p = &ch[0];
    gets(p);  // 仍不安全,僅演示
    cout << ch << endl;  // 正確輸出 string 對象
    system("pause");
    return 0;
}

最佳實踐總結

場景推薦函數優點
C++ 字符串輸入std::getline(cin, str)類型安全、自動擴容、支持空白字符
C 風格字符數組fgets(buf, size, stdin)可控緩衝區大小、標準庫函數
格式化輸入cin >> var / scanf(fmt, &var)適合非空白分隔的數據

核心原則:現代 C++ 開發中完全避免使用 gets(),優先選擇 std::string 配合 std::getline,兼顧安全性與便利性。

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