samantha
samantha

Reputation: 563

Return fixed length std::string from integer value

Problem -> To return fixed length string to std::string*.
Target machine -> Fedora 11 .

I have to derive a function which accepts integer value and return fixed lenght string to a string pointer;
for example -> int value are in range of 0 to -127

so for int value 0 -> it shoud display 000
for value -9 -> it should return -009
for value say -50 -> it should return -050
for value say -110 -> it should return -110

so in short , lenght should be same in all cases.

What I have done : I have defined the function according to the requirement which has shown below.

Where I need help: I have derived a function but I am not sure if this is correct approach. When I test it on standalone system on windows side , the exe stopped working after sometimes but when I include this function with the overall project on Linux machine , it works flawlessly.

    /* function(s)to implement fixed Length Rssi */
 std::string convertString( const int numberRssi, std::string addedPrecison="" )
 {
     const std::string         delimiter   =   "-";
                stringstream   ss;

     ss  << numberRssi ;
     std::string tempString = ss.str();
     std::string::size_type found = tempString.find( delimiter );
     if( found == std::string::npos )// not found
     {
         tempString = "000";
     }
     else
     {
         tempString = tempString.substr( found+1 );
         tempString = "-" +addedPrecison+tempString ;
     }
     return  tempString;

 }

 std::string stringFixedLenght( const int number )
 {
     std::string str;
     if( (number <= 0) && (number >= -9) )
       {
           str = convertString( number, "00");
       }
       else if( (number <= -10) && (number >= -99) )
       {
           str = convertString( number, "0");
       }
       else
       {
           str= convertString(number, "");
       }
     return str;
 }
// somewhere in the project calling the function
ErrorCode A::GetNowString( std::string macAddress, std::string *pString )
{
    ErrorCode result = ok;
    int lvalue;
    //some more code like iopening file and reading file 
    //..bla
    // ..bla     
    // already got the value in lvalue ;

    if( result == ok )
    {
         *pString = stringFixedLenght( lValue );
    }

    // some more code

    return result;

}

Upvotes: 5

Views: 18109

Answers (5)

Steve Jessop
Steve Jessop

Reputation: 279405

I have nothing against the versions that use streams, but you can do it all yourself more simply than your code:

std::string fixedLength(int value, int digits = 3) {
    unsigned int uvalue = value;
    if (value < 0) {
        uvalue = -uvalue;
    }
    std::string result;
    while (digits-- > 0) {
        result += ('0' + uvalue % 10);
        uvalue /= 10;
    }
    if (value < 0) {
        result += '-';
    }
    std::reverse(result.begin(), result.end());
    return result;
}

Upvotes: 0

James Kanze
James Kanze

Reputation: 154047

Note that your examples contradict your description: if the value is -9, and the fixed length is 3, should the output be "-009" (as in your example), or "-09" (as you describe)? If the former, the obvious solution is to just use the formatting flags on std::ostringstream:

std::string
fixedWidth( int value, int width )
{
    std::ostringstream results;
    results.fill( '0' );
    results.setf( std::ios_base::internal, std::ios_base::adjustfield );
    results << std::setw( value < 0 ? width + 1 : width ) << value;
    return results.str();
}

For the latter, just drop the conditional in the std::setw, and pass width.

For the record, although I would avoid it, this is one of the rare cases where printf does something better than ostream. Using snprintf:

std::string
fixedWidth( int value, int width )
{
    char buffer[100];
    snprintf( buffer, sizeof(buffer), "%.*d", width, value );
    return buffer;
}

You'd probably want to capture the return value of snprintf and add some error handling after it, just in case (but 100 chars is sufficient for most current machines).

Upvotes: 2

Sebastian Mach
Sebastian Mach

Reputation: 39109

like this?

#include <cstdlib>
#include <string>

template <typename T>
std::string meh (T x)
{
    const char* sign = x < 0 ? "-" : "";
    const auto mag = std::abs (x);
    if (mag < 10)  return sign + std::string ("00" + std::to_string(mag));
    if (mag < 100) return sign + std::string ("0" + std::to_string(mag));
    return std::to_string(x);
}


#include <iostream>
int main () {
    std::cout << meh(4) << ' '
              << meh(40) << ' '
              << meh(400) << ' '
              << meh(4000) << '\n';
    std::cout << meh(-4) << ' '
              << meh(-40) << ' '
              << meh(-400) << ' '
              << meh(-4000) << '\n';
}

004 040 400 4000

-004 -040 -400 -4000

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409472

How about using std::ostringstream and the standard output formatting manipulators?

std::string makeFixedLength(const int i, const int length)
{
    std::ostringstream ostr;

    if (i < 0)
        ostr << '-';

    ostr << std::setfill('0') << std::setw(length) << (i < 0 ? -i : i);

    return ostr.str();
}

Upvotes: 13

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727057

You can use I/O manipulators to set the width that you need, and fill with zeros. For example, this program prints 00123:

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    cout << setfill('0') << setw(5) << 123 << endl;
    return 0;
}

You have to take care of the negative values yourself, though: cout << setfill('0') << setw(5) << -123 << endl prints 0-123, not -0123. Check if the value is negative, set the width to N-1, and add a minus in front.

Upvotes: 16

Related Questions