Home > Blockchain >  Why my number to string converter keeps returning 000?
Why my number to string converter keeps returning 000?

Time:09-27

I have a issue with my number to string implemention. For some reason I keep getting 000 on my terminal even though. I couldn't find a solution, what is the potantial issue here? Im now sure my code is broken but don't really see the problem.

#include <stdio.h> 
#include <stdlib.h>
#include <math.h>

/* public domain code feel free to use as what you wish, no warranties given*/
char finddigits(unsigned n) {
    char base = 6;
    unsigned tester = 100000;
    while(base % tester != 0) { 
        base--;
        /* inefficient but works for now */
        switch(tester) {
            case 100000:
                tester = 10000;
                break;
            case 10000:
                tester = 1000;
                break;
            case 1000:
                tester = 100;
                break;
            case 100:
                tester = 10;
                break;
            case 10:
                tester = 1;
                break;
        }
    }
    return base;
}

char* num2str(unsigned n) {
    char size = finddigits(n);
    char* tempbuf = malloc(size);
    *tempbuf = 48   (n / pow(10, size));
    for(unsigned int i = 1; i < size; i  ) 
        *(tempbuf   i) = 48   (n % (10 * i));
    return tempbuf;
}

int main(int argc, char* argv[]) {
    int numbr = 210;
    printf("%s \n", num2str(numbr));
    /* expected 210 on string got 000 */
    return 0;
}

CodePudding user response:

You just want num2str to return the digit string for n.

A few issues:

  1. finddigits is supposed to calculate the number of digits in n. But, [if it works at all], it uses an algorithm I've never seen.
  2. finddigits isn't needed in num2str as num2str can be [much] simpler by filling the buffer in the reverse direction.
  3. num2str is too complicated.
  4. Calling num2str from printf leaks memory from the num2str call to malloc

Here's a refactored version:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

char
finddigits(unsigned n)
{
    int count = 0;

    if (n == 0)
        count = 1;

    for (; n != 0; n /= 10,   count);

    return count;
}

char *
num2str(unsigned n)
{
    static char buf[100];
    char *dst = &buf[sizeof(buf) - 1];

    // add string terminator
    *dst-- = 0;

    // we must always output a 0
    if (n == 0)
        *dst-- = '0';

    // work backwards in the array
    for (;  n != 0;  n /= 10, --dst)
        *dst = (n % 10)   '0';

    // point to first digit in string
    dst  = 1;

    return dst;
}

void
dotest(unsigned n)
{
    printf("n=%u '%s'\n",n,num2str(n));
}

int
main(int argc, char *argv[])
{
    dotest(210);
    dotest(0);
    dotest(12345);

    return 0;
}

Here's the program output:

n=210 '210'
n=0 '0'
n=12345 '12345'

CodePudding user response:

The computer does what you told it to do, which is to say, it does complete nonsense.

finddigits(210) returns 1, because 6 % 100000 isn't 0 (it's 6), 5000 isn't 0 (it's 5), 4 % 1000 isn't 0 (it's 4), 3 % 100 isn't 0 (it's 3), 2 % 10 isn't 0 (it's 2), but 1 % 1 is 0 so the loop stops and the function returns 1.

Then, num2str allocates 1 byte. In this 1 byte, it sets the first byte to 48 (210 / 10) which is 69, ASCII code for the letter E. Since size is 1 the loop doesn't run at all and num2str returns this allocation. When you print it, it prints the letter E - possibly with more gibberish after it since the string is not terminated, although for me it just printed E.

I have no idea how you managed to get 000.

You need to write code that tells the computer to do what you want it to do. When you can't get it to do what you want it to, for one part of the code, don't just skip that part of the code and go onto the next one. It all has to be right or it won't work.

CodePudding user response:

If you're trying to convert a number to a string, why not just use sprintf()? See here:

How to convert an int to string in C?

CodePudding user response:

Mathematics is also "public domain". Here are two versions of one of your functions, shown with a main() that tests both versions with several values.

Don't convert a signed integer value to unsigned for no particular reason. If you need/want the absolute value of a (possibly) negative number, C provides a function to achieve that.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int finddigits1( int n ) {
    int count = n == 0; // ensure 0 is counted as 1 digit

    while( n ) count  , n /= 10;

    return count;
}

int finddigits2( int n ) {
    // log of zero is undefined
    return ( n == 0 ) ? 1 : (int)log10(abs(n)) 1;
}

char *num2str( int n, char buf[] ) {
    printf( "finddigits1( %d ) counted %d\n", n, finddigits1( n ) );
    printf( "finddigits2( %d ) returns %d\n", n, finddigits2( n ) );

    strcpy( buf, "Hello world!" ); // Left as an exercise to fix your own code

    return buf; // returning allows direct usage by caller
}

int main() {
    int tests[] = { 123, -123, 0, 100, 54321 };
    char buf[ 30 ]; // better to pass large buffer to function than use malloc()

    for( int i = 0; i < sizeof tests/sizeof tests[0]; i   ) {
        int n = tests[i];
        printf( "n = %d '%s'\n", n, num2str( n, buf ) );
    }

    return 0;
}
finddigits1( 123 ) counted 3
finddigits2( 123 ) returns 3
n = 123 'Hello world!'
finddigits1( -123 ) counted 3 // NB: Account for negative sign!
finddigits2( -123 ) returns 3
n = -123 'Hello world!'
finddigits1( 0 ) counted 1
finddigits2( 0 ) returns 1
n = 0 'Hello world!'
finddigits1( 100 ) counted 3
finddigits2( 100 ) returns 3
n = 100 'Hello world!'
finddigits1( 54321 ) counted 5
finddigits2( 54321 ) returns 5
n = 54321 'Hello world!'
  •  Tags:  
  • c
  • Related