CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Oct 2009
    Posts
    56

    Convert string to int

    Presently, I am using the atoi() function. But I don't want to use this because if the user inputs a value that isn't numeric, it returns 0. So I can't really check if they entered an actual 0 or an incorrect value. What are alternatives to using atoi?

  2. #2
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Convert string to int

    You could use strtol(). It takes a pointer to the part that failed. You can use pointer arithmetic to determine how the conversion proceded:

    http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx

    Or just use a std::stringstream

  3. #3
    Join Date
    Jun 2009
    Posts
    65

    Re: Convert string to int

    Quote Originally Posted by SterlingM View Post
    Presently, I am using the atoi() function. But I don't want to use this because if the user inputs a value that isn't numeric, it returns 0. So I can't really check if they entered an actual 0 or an incorrect value. What are alternatives to using atoi?
    strtol() for long int
    strtoul() for long unsigned int
    strtod() for double

  4. #4
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Convert string to int

    If you are using C++, you could use boost lexical. If you are using C++, but don't want to be dependent on boost, then you could use stringstream to write your own conversion function. For example, this should do what you need:

    Code:
    template <typename T> 
    T string_to(const std::string &s) 
    { 
      T result; 
     
      //check for the boolean 'true' keyword  
      if (s.find("true")!=std::string::npos) 
      { 
        result = 1; 
      }  
      //check for the boolean 'false' keyword 
      else if (s.find("false")!=std::string::npos) 
      { 
        result=0; 
      } 
      else 
      { 
         std::stringstream ss; 
     
        //Check for Hex input 
        if(s.size()>1) 
        { 
          //If the first two characters are '0x' then the input is 
          //a hexidecimal input and therefore the stringstream 
          //base needs to be set to base 16. 
          if(s[0]=='0' && tolower(s[1])=='x') 
          { 
            ss << std::setbase(16);  
          } 
        } 
     
        ss.str(s); 
     
        if (!(ss >> result)) 
        { 
          throw std::runtime_error("string_to: Failed to convert string to destination type"); 
        } 
      } 
     
      //Return the resulting value. 
      return result; 
    }
    You can use it like:

    Code:
    int value = string_to<int>("123");
    The above works for conversions from a string to other types too (bool, float etc...).

  5. #5
    Join Date
    Jan 2009
    Posts
    1,689

    Re: Convert string to int

    I wrote this for a scripting language. It converts them to long doubles, but you can cast that down to an int easily. Admittedly, it's a little messy, but it's stable and fast. I probably send a million conversions through it a week.

    Code:
    /*
     *  Number_Functions.cpp
     *  Math
     *
     *  Created by Wallace on 12/5/09.
     *  Copyright 2009 LiveTechnology. All rights reserved.
     *
     */
    
    #include "Number_Functions.h"
    #include <sstream>
    #include <iomanip>
    #include <cmath>
    #include <iostream>
    
    string LS_INFINITY = "Infinity";
    string NEG_LS_INFINITY = "-Infinity";
    string LS_UNDEFINED = "NaN";
    long double Infinity = 1.0f / 0.0f;
    long double NaN = sqrt(-1);
    
    long double e = 2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274f;
    long double pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f;
    
    char NumberChars[] = {"0123456789"};
    char HexChars[] = {"012345679ABCDEFabcdef"};
    
    int Fixed_Precision = 12;
    
    long double StringToHex(const string & str){
        long long tout = 0;
        char * p = (char*)str.c_str();
        p += 2;  //go past the 0 and x
        while(*p){
    	   tout = tout << 4;  //a hex character represents 4 bits
    	   unsigned char ch = *p;
    	   if (ch < 58){  //0-9
    		  tout |= ch - 48;
    	   } else if (ch < 71){ //A-F
    		  tout |= ch - 55;
    	   } else {  //a-f
    		  tout |= ch - 87;
    	   }
    	   ++p;
        }
        return (long double)tout;
    }
    
    long double PercentToNumber(const string & s, size_t len, const long double & outof){
        //len is the length of the NUMBER (exclusing the &#37;)
        long double res = atof(s.substr(0, len).c_str());
        return res * outof / 100.0f;   
    }
    
    bool NumberFunctions::CheckNonNumberChar(const string & str, size_t pp, long double & out, const long double & outof, bool AllowDecimals){
        /*
    	   This is for when it found a character that is not numeric, it could still be 
    		  scientific notation
    		  a decimal place
    		  a percentage
        */
        switch (str[pp]){
    	   case 'e':  //scientific notation, or just an e?
    		  switch (str[pp + 1]){
    			 case '+':
    				if (str.find_first_not_of(NumberChars, pp + 2) == string::npos){
    				    out = atof(str.c_str());
    				    return true;
    				}
    				break;
    			 case '-':  //initial negation was already compensated for, so pp can never be 0
    				if (str.find_first_not_of(NumberChars, pp + 2) == string::npos){ 
    				    out = atof(str.c_str());
    				    return true;
    				}
    				break;
    		  }
    		  break;
    	   case '.':
    		  if (!AllowDecimals) return false;  //already been through this once, it's the second decimal
    		  pp = str.find_first_not_of(NumberChars, pp + 1);
    		  if (pp == string::npos) return true;
    		  return CheckNonNumberChar(str, pp, out, outof, false);
    	   case '%':
    		  size_t len = str.length();
    		  if (pp == len){
    			 out = PercentToNumber(str, len, outof);
    			 return true;
    		  }
        } 
        return false;
    }
    
    string NumberFunctions::ToString(long double n){
        if (n == Infinity) return LS_INFINITY;
        if (n == -Infinity) return NEG_LS_INFINITY;
        stringstream out;
        out << setprecision(Fixed_Precision) << n;
        return out.str();
    }
    
    /*
        <x> = (0-9)
        <h> = (<x> | (A-F) | (a-f))*
        <d> = (<x>*).(<x>*)
        <c> = Pi | PI | pi | e
        Number = ([-](<d> | Infinity | 0x<h> | <d>e[-]<x>)) | NaN | <c>
    */
    
    long double NumberFunctions::ToNumber(const string & s, const long double & outof){
        if (s == "e") return e;
        if ((s == "Pi") || (s == "pi") || (s == "PI")) return pi;
        return ToNumber_NoConstants(s, outof);
    }
    
    long double NumberFunctions::ToNumber_NoConstants(const string & s, const long double & outof){
        if (((s[0] == '0') && (s[1] == 'x')) ||
    	   ((s[0] == '-') && (s[1] == '0') && (s[2] == 'x'))){
    	   return StringToHex(s);
        } else {
    	   size_t len = s.length() - 1;
    	   if (s[len] == '%'){
    		  return PercentToNumber(s, len, outof);
    	   }
        }
        if (s == LS_INFINITY) return Infinity;
        if (s == NEG_LS_INFINITY) return -Infinity;
        if (s == LS_UNDEFINED) return NaN;
        return atof(s.c_str());
    }
    
    bool NumberFunctions::IsNumber(const string & str, long double & out, const long double & outof){
        if (str == "e"){
    	   out = e;
    	   return true;
        }
        if ((str == "Pi") || (str == "pi") || (str == "PI")){
    	   out = pi;
    	   return true;
        }
        return IsNumber_NoConstants(str, out, outof);
    }
    
    bool NumberFunctions::IsNumber_NoConstants(const string & str, long double & out, const long double & outof){
        if (str == LS_INFINITY){
    	   out = Infinity;
    	   return true;
        }
        if (str == NEG_LS_INFINITY){
    	   out = -Infinity;
    	   return true;
        }
        if (str[0] == '-'){
    	   if ((str[1] == '0') && (str[2] == 'x')){
    		  if (str.find_first_not_of(HexChars, 3) != string::npos) return false;
    		  out = StringToHex(str);
    		  return true;
    	   } else {  //negative, non hex, keep looking for failure
    		  size_t pp = str.find_first_not_of(NumberChars, 1);
    		  if (pp != string::npos) return CheckNonNumberChar(str, pp, out, outof);
    	   }
        } else if ((str[0] == '0') && (str[1] == 'x')){
    	   if (str.find_first_not_of(HexChars, 2) != string::npos) return false;
    	   out = StringToHex(str);
    	   return true;
        } else {
    	   size_t pp = str.find_first_not_of(NumberChars);
    	   if (pp != string::npos) return CheckNonNumberChar(str, pp, out, outof);
        }
        out = atof(str.c_str());
        return true;
    }
    Here is the grammar:
    Code:
        <x> = (0-9)
        <h> = (<x> | (A-F) | (a-f))*
        <d> = (<x>*).(<x>*)
        <c> = Pi | PI | pi | e
        Number = ([-](<d> | Infinity | 0x<h> | <d>e[-]<x>)) | NaN | <c>
    No octal support, but I've never actually seen a programmer use an octal value :\
    Last edited by ninja9578; March 9th, 2010 at 02:20 PM.

  6. #6
    Join Date
    Jun 2008
    Posts
    592

    Re: Convert string to int

    Quote Originally Posted by SterlingM
    Presently, I am using the atoi() function. But I don't want to use this because if the user inputs a value that isn't numeric, it returns 0. So I can't really check if they entered an actual 0 or an incorrect value. What are alternatives to using atoi?
    I simple check if str is '0' would probably work.
    Code:
    int satoi( const char* Str, bool& Err )
    {
        int Num = atoi( Str );
        Err = !Num && *Str != '0';
        return Num;
    }
    or you just
    Code:
    int satoi( const char* Str )
    {
        int Num = atoi( Str );
        if( !Num && *Str != '0' ) throw( "String to int failed" );
        return Num;
    }
    0100 0111 0110 1111 0110 0100 0010 0000 0110 1001 0111 0011 0010 0000 0110 0110 0110 1111 0111 0010
    0110 0101 0111 0110 0110 0101 0111 0010 0010 0001 0010 0001 0000 0000 0000 0000
    0000 0000 0000 0000

  7. #7
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Convert string to int

    Quote Originally Posted by ninja9578 View Post
    long double e = 2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274f;
    long double pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f;
    I love the fact that you included about a thousand digits, and then put "f" on the end to indicate the literal should be a single-precision float, effectively discarding the majority of those digits.....

  8. #8
    Join Date
    Jan 2009
    Posts
    1,689

    Re: Convert string to int

    O.o Oops. Uh, that should be ld. I don't know how I missed that one :\ I think I had less digits there once, then added the others just for the hell of it.

  9. #9
    Join Date
    Jun 2009
    Posts
    65

    Re: Convert string to int

    Quote Originally Posted by Lindley View Post
    I love the fact that you included about a thousand digits, and then put "f" on the end to indicate the literal should be a single-precision float, effectively discarding the majority of those digits.....
    lol.

  10. #10
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Lightbulb Re: Convert string to int

    This is one of those questions where an appropriate answer could have been to just make a referral to the FAQ since this question is one that has been asked so often. It would save you all a lot of typing!
    http://www.codeguru.com/forum/showthread.php?t=231054

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured