Convert values ​​from string to long long

val = atoll(a[i].c_str()); 

How to protect yourself from Vasya Pupkin, who wrote down the number that is greater than the maximum (9223372036854775807)? It is necessary to equate val to 0.

The program does not produce errors, but the presence of such a flaw annoys me.

  • Connect <errno.h> , zero errno before atoll() and check errno == ERANGE after. - avp
  • @avp: Functions of the ato... group generate undefined behavior when overflowing. They do not expose errno . - AnT
  • @AnT, I actually checked before advising in g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 . Obviously it is implemented through the usual strtoll, which exposes errno - avp
  • @avp What does "I checked" mean? In C / C ++, there is no “I checked” in rpincipe, and when it comes to unspecific behavior, it’s generally funny to talk about some kind of “checking”. How atol implemented there in your implementation is not interesting to anyone. Behavior is not defined. And your "checks" are no more than an attempt to look at the details of this indefinite behavior. Why do this is not clear. - AnT
  • Separately, it is worth noting that in the GNU implementation of the atoi standard library, it is implemented through a direct caste of the result of strtol to the int type without any checks for exceeding the range. That is no goal to determine the behavior of ato... when the library overflowed before itself, the developers of the library did not set. Implementing ato... via strto... is nothing more than a reasonable saving of code within the framework of the freedom provided by the same indefinite behavior. Do not try to look inside the implementations of standard functions and invent non-existent guarantees based on what you see there. - AnT

4 answers 4

Well, as an option, use stoll and catch exceptions ...

 int main(int argc, const char * argv[]) { string s; cin >> s; long long l; try { l = stoll(s); } catch(out_of_range&) { l = 0; } catch(invalid_argument&) { l = -1; } cout << "s = " << s << endl; cout << "l = " << l << endl; } 
  • Or check errno with the same atoll() without messing around with exceptions - avp
  • @avp: Functions of the ato... group generate undefined behavior when overflowing. They do not expose errno . - AnT

The functions of the ato.. group were [semi-] officially "abandoned" by the C language standard back in 1995 (see http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf ) . They do not provide any means for handling error situations. In the standard library C, the functions of the strto... group have replaced them, which provide such tools.

These functions were not officially declared obsolescent due to their widespread occurrence in the old code. They can also potentially be implemented more efficiently than the functions of the strto... group strto... However, real implementations are not usually involved in this, but simply delegate calls to ato... to strto... while ignoring potential errors.

Therefore, if for some reason you insist on using C functions to solve such problems, forget about the existence of functions of the ato... group ato... these are "dead" functions. Use the functions of the group strto...

Of course, given that your question is tagged with the [C ++] tag, you better just use the same tools of the standard C ++ library.

    This is the fastest implementation of the cast, from me known. She yes, requires some validation at compile time, but works like a clock. In the while (*p >= '0' && *p <= '9') add a check for the length of the string corresponding to the length of the maximum number. The type of return value can be played. It should work many times faster than the read version.

      STATIC_ASSERT(1 == '1' - '0'); STATIC_ASSERT(2 == '2' - '0'); STATIC_ASSERT(3 == '3' - '0'); STATIC_ASSERT(4 == '4' - '0'); STATIC_ASSERT(5 == '5' - '0'); STATIC_ASSERT(6 == '6' - '0'); STATIC_ASSERT(7 == '7' - '0'); STATIC_ASSERT(8 == '8' - '0'); STATIC_ASSERT(9 == '9' - '0'); int to_int(const char *p) { while (*p == ' ') ++p; int r = 0; bool neg = false; if (*p == '-') { neg = true; ++p; } while (*p >= '0' && *p <= '9') { r = (r*10) + (*p - '0'); ++p; } if (neg) { r = -r; } return r; } 
    • Or so - avp
    • And in this case, what is the meaning of the “invention of the bicycle” in comparison with the standard functions available? From the point of view of the control of erroneous situations, this option is as holes as atoi . And to work "at times faster" standard function, it is, of course, will not. As for the "compilation checks": they are redundant - all this is already guaranteed by the specification of the language. - AnT
    • But most importantly, this answer has nothing to do with the topic of discussion, i.e. to the question. - AnT
    • @AnT since I took measurements more than six months ago, I don’t remember how many times it is faster than standard implementations by compilers that we use (for Linux, Solaris, Windows), but it was faster at times, and when it was critical, it helped (only for double). It answers the question, because when introducing a counter, it gives control over the overflow to the discretion of the user. As for the guarantees of the language, I would be grateful for the reference to the standard, which guarantees that the character codes 0 and 3 really different by 3, I did not find this at one time, and therefore I was reinsured. - Arkady
    • one
      @Arkady C is the section "5.2.1 Character sets", in C ++ - "2.3 Character sets". It says "after the number of decimal digits after the death of each character." (referring to the sequence 0123456789) - AnT
     std::string s="922337203685477580712324567878"; size_t index; long long l=std::stoll(s, &index); if(index!=s.size()) throw std::runtime_error("bad number"); 
    • Make sure it doesn't work: ideone.com/9zb5cL - Harry
    • There will be an out_of_range exception. Checking the index is needed to catch an error on lines with spaces "1234 4567". - Chorkov
    • And what did the vehicle ask? How to protect yourself from Vasya Pupkin, who wrote down the number that is greater than the maximum ... - Harry