Alternative std::to_string

Jan 13, 2014 at 1:51am
I'm trying to create an "to_string" function without use headers to help. I made my own code but it seems not to work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

unsigned short int intlen(int numb)
{
  if (numb < 0) numb = -numb;
  if (numb <         10) return 1;
  if (numb <        100) return 2;
  if (numb <       1000) return 3;
  if (numb <      10000) return 4;
  if (numb <     100000) return 5;
  if (numb <    1000000) return 6;
  if (numb <   10000000) return 7;
  if (numb <  100000000) return 8;
  if (numb < 1000000000) return 9;
  return 10;
}


char* to_ascii(int variable)
{
    int times;
    char numbers[] = {'0','1','2','3','4','5','6','7','8','9'};
    int numb;
    char* string;
    int variable_t = variable;
    int* str_r;
    /* PEGAR CADA DIGITO AO CONTRARIO NO ARRAY DE MANEIRA INVERSA*/
    while(variable_t)
    {
        for(int i = 1; i <= intlen(variable_t); i++)
        {
            str_r[(intlen(variable_t) - i)] = variable_t % 10;
            variable_t /= 10;
        }
    }
    for(int i = 0; i < variable; i++)
    {
        string[i] = '0' + str_r[i];
    }

    return string;
}

int main()
{
    std::cout << to_ascii(1002);
}


What I'm doing wrong?
Jan 13, 2014 at 2:14am
Must you use char arrays (C strings), or can you just use std::string?

The problem here is that in your code, string and str_r are just pointers, and since you never allocate an array for them to point to, you're just accessing and writing to some random piece of memory that you probably shouldn't be tampering with.

On a side note, implementing a to_string function is a lot easier if you use a std::stringstream....
Last edited on Jan 13, 2014 at 2:15am
Jan 13, 2014 at 10:31am
I am restricted to use "pure C++"; even STL is restricted. I'm just using std::cout for show the output. I know that I should allocate the memory (dynamic memory allocation), so I'll create an array with an int function that looks as strlen(char*) (my implementation) and intlen(int). Any suggestion?
Last edited on Jan 13, 2014 at 10:32am
Jan 13, 2014 at 11:11am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char* to_string( long value, char* buffer, size_t bufsz, size_t offset )
{
    snprintf( buffer+offset, bufsz-offset, "%ld", value ) ;
    return buffer ;
}

char* to_malloced_string( long value )
{
    enum { SZ = 32 } ;
    char* str = malloc(SZ) ;
    if(!str) return NULL ;
    return to_string( value, str, SZ, 0 ) ;
}

int main()
{
    int v = 12345 ;
    char cstr[128] = "The value is: " ;

    to_string( v, cstr, sizeof(cstr), strlen(cstr) ) ;
    puts(cstr) ;

    char* temp = to_malloced_string(999) ;
    puts(temp) ;
    free(temp) ;
}

http://coliru.stacked-crooked.com/a/47230d4c105cec57
Jan 13, 2014 at 12:00pm
@JLBorges I need C++ without headers, only #include <iostream> to show the value (std::cout). My code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
namespace func
{
    int intlen(int number_t)
    {
        int number = number_t;
        int end = 0;
        while(number > 0)
        {
            number /= 10;
            end++;

        }
        return end;
    }

    int get_digits(int number, int pos)
    {
        int ret_ [intlen(number)];
        int number_t = number;
        for(int i = 0; i < intlen(number); i++)
        {
            ret_[i] = number_t % 10;
            number_t /= 10;
        }
        return ret_[intlen(number) - pos];
    }

    char* to_ascii(int number)
    {
        char * string;
        char numbers [] = {'0','1','2','3','4','5','6','7','8','9'};
        int * str;
        for(int i = 0; i < intlen(number); i++)
        {
            str[i] = get_digits(number, i);
        }
        for(int i = 0; i < intlen(number); i++)
        {
            string[i] = numbers[str[i]];
        }
        
        return string;

    }

}


int main()
{
    std::cout << func::to_ascii(10);
}
Jan 13, 2014 at 2:35pm
1
2
3
4
5
>  char* to_ascii(int number)
>    {
>          char * string; 
>           // ...
>           int * str;


These are uninitialized pointers; they do not point to valid memory.

A recursive solution (with bounds checking):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// returns number of characters placed into buffer
// excluding the terminating null character
// returns -1 if the buffer is not large enough
int to_string( long value, char* buffer, int bufsz )
{
    if( value < 0 && bufsz > 2 )
    {
        value = -value ;
        buffer[0] = '-' ;
        int n = to_string( value, buffer+1, bufsz-1 ) ;
        if( n != -1 ) return n+1 ;
    }

    else if( value < 10  && bufsz > 1 )
    {
        buffer[0] = value + '0' ;
        buffer[1] = 0 ;
        return 1 ;
    }

    else
    {
        int digit = value%10 ;
        int n = to_string( value/10, buffer, bufsz-1 ) ;
        if( n != -1 && bufsz > (n+1) )
        {
            buffer[n] = digit + '0' ;
            buffer[n+1] = 0 ;
            return n+1 ;
        }
    }

    buffer[0] = 0 ;
    return -1 ;
}

#include <iostream>

int main()
{
    int values[] = { -12345678, 1234, 0, -9999, 100 } ;
    char cstr[128] ;

    for( int v : values )
    {
        int n = to_string( v, cstr, sizeof(cstr) ) ;
        if( n>0 ) std::cout << cstr << " [" << n << "]\n" ;
    }
}

http://coliru.stacked-crooked.com/a/ef16332cc94ab283
Jan 13, 2014 at 3:44pm
Found this back in an old file I used for the same purpose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
inline void AddNumber(unsigned long long Number, unsigned int Base = 10) {
	if(Number == 0) { Add(T('0')); return; }
	if(Base <= 1) { Base = 2; }
	else if(Base > 36) { Base = 36; }
	else if(Base == 8) { Add(T('0')); }
	else if(Base == 16) { Add(T('0')); Add(T('x')); }
	const unsigned char LastCh = sizeof(unsigned long long)*8+1;
	unsigned long long ThisProcess = 0;
	T Buffer[LastCh+1];
	unsigned char OffsetEnd = 0;
	while(Number > 0)
	{
		Buffer[LastCh-OffsetEnd] = T((char)((Number % Base) + '0'));
		if(Buffer[LastCh-OffsetEnd] > '9')
			Buffer[LastCh-OffsetEnd] += ('A' - '9' - 1);
		++OffsetEnd;
		Number /= Base;
	}
	Add(Buffer + LastCh - (OffsetEnd-1),OffsetEnd);
}


Consider "T" to be char, and Add a function that adds a character to your current string.
Jan 15, 2014 at 6:03pm
@JLBorges what is for(int v : values) ? I've nerver learnt that!
Jan 15, 2014 at 6:37pm
closed account (Dy7SLyTq)
google range based for loop. its equivalent to using iterators on a type in a for loop, a foreach loop in php, or a for loop in python
Jan 15, 2014 at 7:54pm
To add to DTSCode's list, C++11's range-based for-loop is equivalent to Java 5's enhanced for-loop.
Topic archived. No new replies allowed.