-2

I'm a student, and I am currently working on C++ Classes. I am making a program which is supposed to ask a user to input a float point number not greater that 99.99 as a price of fuel at a gas station. I have created code that saves the user input in to a char array, and created limits so that the user can't input more than 2 dots, for example (2..2). The maximum number of characters is 5 including one dot. Now, everything works fine except for if the user enters two sets of strings before hitting enter. I have a problem because the second string messes up with other cin statements in the loop. The code will also take the finalized char array input, and than covert it to a float variable so that the further calculations can be computed easily. I am working on a Windows system, and Visual Studio 2017 C++.
I have tried detecting the single white space in an if/else statement, but it seems that white space is not detected as a single char array member, like this ex. else if (str[count] == ' ') , and than asking to re enter the correct input without the white space. getline() function could not work on a char array, so I couldn't discard the characters entered after including and after the white space in this way. I have tried changing the char array to a string, but still if the user inputs two or more strings separated by white space, my program keeps reading it in to cin over again.

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;
}

Occasional stack around str variable has been corrupted, and that happens when I heavily try to mess with the user input just to check if the program can crash. That's why I need to know how to clear the input after the white space. I solved the stack corruption problem by changing the char array to string, but still not the excess characters that potential users might throw down at the program.

Silicomancer
  • 8,604
  • 10
  • 63
  • 130
Boksa
  • 1
  • 1
  • 2
    Are you allowed to use `std::string`? – NathanOliver Aug 29 '19 at 20:27
  • 1
    BTW, prefer to use character literals like `'A'` and `'Z'` rather than their decimal ASCII encoding; it reads better. – Thomas Matthews Aug 29 '19 at 20:33
  • Also, C++ has this new type for flags: `bool`. It has two values, `true` and `false`. Use this for flags and conditional variables. A lot more modern than the concept of using 1 and 0 (the concept is like around the 1960s). – Thomas Matthews Aug 29 '19 at 20:35
  • FYI, the `pow` function is *floating point*. You may experience some precision errors when assigning the result to an integer. – Thomas Matthews Aug 29 '19 at 20:36
  • Suggestion: Move the input validation to a function that returns a `bool`. That way you can `while (!validate(str)) {cin >> str;}` Makes `main` easier to read and eliminates a bunch of places where you are reading the string and resetting `len` again. – user4581301 Aug 29 '19 at 20:37
  • Check out this cool function, [strtod](https://en.cppreference.com/w/cpp/string/byte/strtof), which will convert a C-Style string to floating point and return an error if the string cannot be converted. I think it might save you some code. – Thomas Matthews Aug 29 '19 at 20:39
  • The concept of flags as 1 and 0 is taught at Seneca College in Toronto CPD course. I am also trying to understand better the function of buffer and how it can be regulated from an input stance, without using pre made functions someone else made, if posssible. I think I will understand the core of programming better in this way. Thanks. – Boksa Aug 29 '19 at 20:43
  • Ummm... your textbook, "Absolute C++", is _ancient_. You should consider getting a [better C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – alter_igel Aug 29 '19 at 20:46
  • 1
    Is `99.988` valid input? It's a value that's less than 99.99, but it's too long for your 5-character buffer. Instead of checking every character in the text, convert the input to a value (either with `double value; std::cin >> value;` or by reading a string and converting it with `std::stod`. Character-by-character validation is, as you've seen, a nightmare. Reading floating-point values is well understood; don't reinvent the wheel. – Pete Becker Aug 29 '19 at 21:14
  • 99.988 will not be accepted as it has 6 chars, and the limit is set to 5. – Boksa Aug 31 '19 at 18:49

2 Answers2

0

If you must use character arrays, I highly recommend restricting the amount of characters read from the console.

The std::istream::getline() is well suited for this:

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);

You can then use a function like strtod to convert the string to floating point variable.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Tried using that, the program will run, but when it gets to cin.getline() it will not accept any input characters, like I will try to type, and nothing will show on screen. I shall try the strtod function next. – Boksa Aug 31 '19 at 18:51
0

I have found one good way to solve a problem of the string buffer overflow. It uses cin>>ws; followed by getline() function. The two need to be used in conjunction, and than the read will be only the first string of characters and everything after the whitespace will be trashed.

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;
}
Boksa
  • 1
  • 1