4

So I got asked this on a skills test for an internship, and at the time it completely baffled me. I have some code now that I thought should work, but isn't assigning the correct values to the string.

#include <iostream>
#include <string>
using namespace std;

int main()
{
     // declarations
     int i = 0, num= 63;
     string b="";

     while (num != 0)
     {
          i = num % 10;
          b.insert(0,i + 48 + "");
          num = num/10;
     }


     cout << b << endl;

     return 0;
}

With "num" being the integer value (I just used 63 as an example)

EDIT:: I incorrectly paraphrased, I could not use any function that did an int to string conversion for me, not that I couldn't use the string library, my mistake.

ssrobbi
  • 496
  • 1
  • 5
  • 15
  • `int + int + const char[N]` doesn't work. Anyway, use `'0'`, not 48. – chris Oct 17 '12 at 23:52
  • @Nick That won't work, there's no overload that'll match those arguments after removing the `""` – Praetorian Oct 17 '12 at 23:56
  • For performance and simplicity, do the other way around: dual pass, and start with the MS digit. – Pavel Radzivilovsky Oct 17 '12 at 23:59
  • 1
    What do you mean when you say "without access to library function"? Which library? The Standard Template Library? 3rd-party libraries? External libraries? If you mean the STL, then why did you use `std::string`? – Casey Oct 18 '12 at 00:35
  • I rewrote the OP, I didn't realize how I phrased the question, I meant I couln't use a library function that did the int to string conversion for me. – ssrobbi Oct 18 '12 at 00:42

5 Answers5

6

Change the insert line to

b.insert(0, 1, '0' + i);

This will insert the character obtained from adding i to '0' once at index 0 in the string.


Explanation of why your code isn't working:

b.insert(0,i + 48 + "");

the line above is calling

basic_string::insert( size_type index, const CharT* s );

where the pointer is being determined by adding 48 + i to the address of the "" string literal, resulting in garbage.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
0

I would suggest recursive function:

std::string f( int val )
{
   if ( val >= 10 )
      return f( val / 10 ) + ( char )( val % 10 + '0' ) ;
   else
      return std::string( 1, '0' + val ) ;
}

Usage:

std::cout << f( 63 ) << std::endl ;

Note that this function should append to your string instead of using very expensive shifting (and putting in the front of the string.)

Grzegorz
  • 3,207
  • 3
  • 20
  • 43
  • On the other hand, this creates one new `string` object per digit, and this isn't tail-recursive, so I'd wager that this is in fact _more_ expensive. – ildjarn Oct 18 '12 at 00:16
  • Sure, however optimizer will never allocate one byte, so for shorter strings it will be reusing the same memory. Thanks for the note, though. – Grzegorz Oct 18 '12 at 00:19
  • Shifting string for converting number is not a `very expensive shifting`, since to convert a number we need an small buffer and almost all implementations of `std::string` will start with a small buffer(even in the heap or in their structure), so memory will not reallocated and shifting 1-20 bytes of data is not a very expensive task! – BigBoss Oct 18 '12 at 00:21
0

It is worth noting that there are other errors with the code. For example, the transformation doesn't work for num == 0. Here is a better version:

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>

int main(int ac, char* av[])
{
    int num(ac == 1? 0: std::atoi(av[1]));
    std::string b;

    do
    {
        b.push_back((num % 10) + '0');
        num /= 10;
    }
    while (num != 0);
    std::reverse(b.begin(), b.end());
    std::cout << b << '\n';
    return 0;
}
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • I think `std::reverse` counts as a library function. ;-] – ildjarn Oct 18 '12 at 00:18
  • Well, `std::string` is full of library functions! ... and if I'd be called up on use of `std::reverse()` I'd implement it: `template void reverse(BIt b, BIt e) { for (; b != e && b != --e; ++b) { swap(*b, e); } }` (unless I made some silly error). I trust, you believe that I can cook up `swap()` (and I have also implemented all of the string members before but it could actually use a fixed sized array...). Also, it doesn't say "library function**s**" ;) – Dietmar Kühl Oct 18 '12 at 00:22
  • I agree, the OP asking for no library functions then using `std::string` is a little inconsistent, but I thought it worth commenting for the sake of pedantry if nothing else. :-] – ildjarn Oct 18 '12 at 00:24
  • 1
    I paraphrased the question, it stated specifically not to use a built in integer to string function. Not necessarily library. It was a problem to test logical problem solving, which I botched :P – ssrobbi Oct 18 '12 at 00:32
0

Very simple solution: Use string streams. In this case, an output string stream:

#include <iostream>
#include <string>
#include <sstream>

std::string IntToString(int value) {
    std::ostringstream ss;
    ss << value;
    return ss.str();
}

const char* IntToCString(int value) {
    std::ostringstream ss;
    ss << value;
    return ss.str().c_str();
}
Casey
  • 10,297
  • 11
  • 59
  • 88
  • I assume "*without access to library function*" also means without using stream objects. – ildjarn Oct 18 '12 at 00:17
  • @ildjarn "without access to library function" can *not* mean "without access to the Standard Template Library" because `std::string` is used. But no assumptions can really be made because that can only be clarified from the OP. – Casey Oct 18 '12 at 00:31
  • 2
    Agreed, hence the lack of downvote. ;-] Note, however, that your `IntToCString` invokes [undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior) – see [this answer](http://stackoverflow.com/a/11165022/636019) for details. – ildjarn Oct 18 '12 at 00:34
  • My mistake, I edited the OP, you can use the standard template library, and the string library, just nothing that specifically does the int to string conversion for you – ssrobbi Oct 18 '12 at 00:36
  • @ildjarn Thanks for pointing that out. I just threw that in there for completeness. I really only intended to demonstrate `IntToString`. – Casey Oct 18 '12 at 00:39
  • @user1754776 If I wanted to get pedantic about semantics (Hah!) Technically my function appends an integer to an empty stream and outputs the stream as a string. It in no way shape or form "uses a function that converts an integer to a string" like the horribly bad `itoa(...)`. – Casey Oct 18 '12 at 00:45
0

Here's some code that doesn't use any libraries and doesn't perform allocations. Instead, the user is expected to provide a buffer that's large enough, and she receives a pointer to the beginning of the result string in return:

char * format(unsigned int n, char * buf, std::size_t len)
{
    if (len == 0) return NULL;

    char * p = buf + len;

    *--buf = 0;

    while (n && p > buf)
    {
        *--buf = '0' + (n % 10);
        n /= 10;
    }

    return n == 0 ? p : NULL;
}

Embedded people might like this especially because the function doesn't do anything outside your control.

Usage:

char buf[100];
char * s = format(12345, buf, sizeof buf);
if (s) { printf("Formatted: %s\n", s); }
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084