Home > OS >  (C ) How do I display an error when more than one "." is used in a calcualtor?
(C ) How do I display an error when more than one "." is used in a calcualtor?

Time:03-31

I am making a calculator using command line arguments, and one of the problems I am having is that I can't find a way to display an error to inputs that have more than one ".". 3.33 can be accepted, but 3.3.3.2 cannot because its an invalid number.

int main(int argc, char* argv[]) {
if (argc == 1) {

    cout << "E\n";
    return 0;
}
if (argc <= 2) {
    cout << "P\n";
    return 0;
}
if (argc > 4) {
    cout << "P\n";
    return 0;
}

if (argc == 3) {
    cout << endl << (atof(argv[1])   atof(argv[2])) << endl;
    return 0;
}

else if (argc == 4)
{
    //Addition operation  
    if (argv[3][0] == 'a')
        cout << endl << (atoi(argv[1])   atoi(argv[2])) << endl;

    //Subtraction operation
    else if (argv[3][0] == 's')
        cout << endl << (atof(argv[1]) - atof(argv[2])) << endl;

    //Multiplication operation
    else if (argv[3][0] == 'm')
        cout << endl << (atof(argv[1]) * atof(argv[2])) << endl;

    //Division operation
    else if (argv[3][0] == 'd')
        if (argv[2][0] == '0') {
            cout << endl << "error";
            return 0;
        }
        else {
            cout << endl << (atof(argv[1]) / atof(argv[2])) << endl;
        }


    //Exponential operation
    else if (argv[3][0] == 'p')
        if (argv[2][0] > - 1.00 && argv[2][0] < 1.00) {
            cout << endl << "Y";
            return 0;
        }
        else if (argv[1][0] == '-') {
            cout << endl << "Y";
            return 0;
        }

        else 
            cout << endl << pow(atof(argv[1]), atof(argv[2])) << endl;
        

    else
        cout << endl << "V" << endl;
    //Any other operator
}

}

CodePudding user response:

atof will stop when it finds characters that cannot be part of the floating point number, and this includes an extra '.'. Unfortunately it does not tell you this happened.

Smarter conversion functions like std::stof or strtof will notify you if the entire string was not consumed when parsing.

Example:

size_t end;
float val = std::stof(argv[1], &end);
if (end != strlen(argv[1]))
{
    cout << "Bad input: " << argv[1] << "\n"; 
    return -1; 
} 

will return from main and exit the program if the entire argument is not consumed when parsing or throw an exception if the number was out of range or no number could be parsed, ending the program if uncaught.

char * endp; 
errno = 0;
float val = strtof(argv[1], &endp); 
if (*endp != '\0' || errno = ERANGE) 
{ 
    cout << "Bad input: " << argv[1] << "\n"; 
    return -1; 
}

will return from main and exit the program if the entire argument is not consumed when parsing or the number was out of range. I personally prefer this option because I don't like throwing exceptions over user input. Users getting the input wrong is not exceptional enough to be worth an exception.

If your compiler is up to date, std::from_chars can be extremely helpful. The linked documentation provides excellent examples of its usage.

CodePudding user response:

One way for checking the validity of a string is to use regular expressions, for example, you can use this.

You can write something like this to extract your operands:

float op1, op2;
std::string p1 = argv[1];
std::string p2 = argv[2];
std::regex pattern("[ -]?([0-9]*[.])?[0-9] ");

if (std::regex_match(p1, pattern) && 
    std::regex_match(p2, pattern)) {
  op1 = atof(argv[1]);
  op2 = atof(argv[2]);
  // ...
} else {
  cout << "Error!" << std::endl;
}

Alternatively, you could use the return value of atof to check if an error happened:

Return value

Floating point value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and HUGE_VAL, HUGE_VALF or HUGE_VALL is returned. If no conversion can be performed, ​0​ is returned and *str_end is set to str.

  •  Tags:  
  • c
  • Related