簡體   English   中英

如果用戶輸入兩個或多個由空格分隔的字符串,如何防止 C++ 緩沖區溢出?

[英]How to prevent C++ buffer overflow if the user enters two or more strings separated by white spaces?

我是一名學生,目前正在研究 C++ 類。 我正在制作一個程序,它應該要求用戶輸入一個不大於 99.99 的浮點數作為加油站的燃料價格。 我創建了將用戶輸入保存到字符數組的代碼,並創建了限制,以便用戶不能輸入超過 2 個點,例如 (2..2)。 最大字符數為 5,包括 1 個點。 現在,除了用戶在按 Enter 鍵之前輸入兩組字符串之外,一切正常。 我有一個問題,因為第二個字符串與循環中的其他 cin 語句混淆。 該代碼還將采用最終的 char 數組輸入,然后將其轉換為浮點變量,以便可以輕松計算進一步的計算。 我正在使用 Windows 系統和 Visual Studio 2017 C++。
我曾嘗試在 if/else 語句中檢測單個空格,但似乎沒有將空格檢測為單個字符數組成員,就像這個例子一樣。 else if (str[count] == ' ') ,而不是要求重新輸入沒有空格的正確輸入。 getline() 函數無法在字符數組上工作,因此我無法以這種方式丟棄在包含空格之后和空格之后輸入的字符。 我嘗試將 char 數組更改為字符串,但是如果用戶輸入兩個或多個由空格分隔的字符串,我的程序會繼續將其讀入 cin 。

int main()
{

    int count = 0;
    int lenFlag = 0, mainFlag = 0;
    float result = 0;
    int len;
    char str[6] = "00000";
        //string str ="00000";

        cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);

    //This part will ask the user to set the price of fuel 
        //for the gas pump program.   The programming project segment 
    //is from a book by Walter Savitch "Absolute C++".


while (mainFlag == 0)
{
    cout << "Please enter the fuel price in dollars $";
    cin >> str;
    len = strlen(str);
    cout << "strlen is = " << len << endl;

    while (len <= 5 && mainFlag == 0)
    {
        count = 0, lenFlag = 0;

            while (count < len && lenFlag == 0)
        {
        if (count == 0 && (str[count] < 48 || str[count] > 57))
        {                                                    
                   cout << "The first input member must be a number."
                "You must use a number between 0-9.\n"
            "Try again: ";

            cin >> str;
            len = strlen(str);
            lenFlag = 1;
        }
                else if (count > 0 && (str[count] < 48 || str[count] > 57)   
                    &&  str[count] != '.')
        {
    cout << "You must enter number between 0-9, or a decimal delimiter.\n"
        "Try again, : ";

            cin >> str;
            len = strlen(str);
            lenFlag = 1;
        }
        else if (count > 0 && (str[0] == '.' && str[1] == '.') || (str[0] == '.' && str[2] == '.') ||
                    (str[0] == '.' && str[3] == '.') || (str[0] == '.' && str[4] == '.') ||
                    (str[1] == '.' && str[2] == '.') || (str[1] == '.' && str[3] == '.') ||
                    (str[1] == '.' && str[4] == '.') || (str[2] == '.' && str[3] == '.') ||
                    (str[2] == '.' && str[4] == '.') || (str[3] == '.' && str[4] == '.'))
        {
    cout << "You have entered more than 1 decimal delimiter, try again: ";
            cin >> str;
            len = strlen(str);
            lenFlag = 1;
        }
        else if (count > 1 && str[0] > 48 && str[0] < 58 && str[1]>47 
                         && str[1] < 58 && str[2]>47 && str[2] < 58)
        {
                cout << "Maximum number is 99.99, try again:\n";
            cin >> str;
            len = strlen(str);
            lenFlag = 1;
        }
        else if (str[count] == ' ')
        {
            cout << "Typing whitspace is not an option!!" << endl;
            cout << "Try again!!" << endl;
            cin >> str;
            len = strlen(str);
            lenFlag = 1;
        }
        else if (count == len - 1 && lenFlag == 0)
        {
            //cout << "Main flag switches to 1!!" << endl;
            mainFlag = 1;
        }
             count++;
          }

    } //while(lenCopy <= 5) loop end 
        if (len > 5)
        {
                cout << "Either non-numbers were entered, or a negative 
                number, or an incorrect " << endl;
            cout << "number size. Enter a maximum size of 5 
                including a .dot for decimal number" << endl;
            cout << "Maximum number is 99.99." << endl;
            mainFlag = 0;
        }

 }//mainflag loop ends

    int dotpos = 0;

    for (int n = 0; n < len; n++)                            
    {                                       
        if (str[n] == '.')                                  
        {
            //dotpos = n + 1;
            dotpos = len - n - 1;
            cout << "dotpos = " << dotpos << endl;
        }
        else
        {
            result = result * 10 + (str[n] - '0');                       
              //Line above is a  float and character mix as a math equation.
            cout << "result " << n << " = " << result << endl;
        }
    }
    if (dotpos > 0)                                         
        result = result / (power(10, dotpos));              

     cout << "You have set the cost at $" << result << " per gallon." << endl;

    system("pause");
    return 0;
}

偶爾圍繞 str 變量的堆棧已損壞,當我大量嘗試弄亂用戶輸入只是為了檢查程序是否會崩潰時,就會發生這種情況。 這就是為什么我需要知道如何清除空格后的輸入。 我通過將字符數組更改為字符串解決了堆棧損壞問題,但仍然沒有解決潛在用戶可能會在程序中丟棄的多余字符。

如果您必須使用字符數組,我強烈建議限制從控制台讀取的字符數量。

std::istream::getline()非常適合於此:

const unsigned int LIMIT = 10;
char number_as_text[LIMIT];
std::cout << "Enter a floating point number, less than 10 characters: ";
std::cin.getline(number_as_text, LIMIT);

然后,您可以使用strtod類的函數將字符串轉換為浮點變量。

我找到了一種解決字符串緩沖區溢出問題的好方法。 它使用cin>>ws; 然后是 getline() 函數。 兩者需要結合使用,並且讀取的將只是第一個字符串,空格之后的所有內容都將被丟棄。

cout << "Do you want to set cost in gallons or liters? "
    "\nPress G for gallons or L for liters: ";
cin >> ws;
getline(cin, chooseSetCost);

while (chooseSetCost != "G" && chooseSetCost != "g" && chooseSetCost != "L" && chooseSetCost != "l")
{
    cout << "Incorrect input. Try again: "; 
    cin >> ws;
    getline(cin, chooseSetCost);
    cout << "choose cost is = " << chooseSetCost << endl;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM