0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>


#define BINARY_ACCURACY 32

int convertDezToDualString(const int number, char stringDualNumber[]){
    int num = number;
    if (number<0){
        //nothing here yet
    } else {
        for (int i = 0; i<BINARY_ACCURACY; i++){
            sprintf(stringDualNumber,"%d%s",num%2,stringDualNumber); 
                   //I think that's the part where the thing happens
            printf("%s",stringDualNumber);    //For Testing purposes
            printf("\n");
            num/=2;
        }

    }
}

int main() {
    char* stringDualNumber= (char*) calloc(BINARY_ACCURACY,sizeof(char));
    const int dezNumber = getInt();    //Gets a decimal number and returns if it's valid
    convertDezToDualString(dezNumber, stringDualNumber);
}

Input:
1234
Output:
00
110
0010
00010
110010
0010010
11010010
111010010
0011010010
00011010010
110011010010
0010011010010
00010011010010
000010011010010
0000010011010010
00000010011010010
000000010011010010
0000000010011010010
00000000010011010010
000000000010011010010
0000000000010011010010
00000000000010011010010
000000000000010011010010
0000000000000010011010010
00000000000000010011010010
000000000000000010011010010
0000000000000000010011010010
00000000000000000010011010010
000000000000000000010011010010
0000000000000000000010011010010
00000000000000000000010011010010
000000000000000000000010011010010

I was wondering why it puts out the last number twice all the time... I did not expect that behaviour. I am using cygwin. I stumbled apon the problem when my output had 33 instead of 32 digits. So i made the for loop output the string every iteration. and found this problem. i am quite new with c but used java before.

MrMxffin
  • 1
  • 2
  • 1
    after you calloc `stringDualNumber` all its 32 bytes are zero. When you overwrite the last zero, you no longer have a string. Try calloc'ing 33 bytes – pmg May 28 '21 at 12:01
  • 4
    Possibly related: [Is sprintf(buffer, “%s...”, buffer, ...) safe?](https://stackoverflow.com/q/1283354/10871073) – Adrian Mole May 28 '21 at 12:03
  • @pmg The Program has the same output if i change the allocated space to 33 – MrMxffin May 28 '21 at 12:05
  • The `stringDualNumber` array can contain strings up to a length of **31** (not 32). You need to allocate one more byte for the NUL string terminator. – Jabberwocky May 28 '21 at 12:41

4 Answers4

0

I think, in your call to sprintf, it's writing num%2 to stringDualNumber (via %d) immediately, and then the results of that gets written again in the same call since it's referencing the now modified stringDualNumber to the %s?

Here's a modified version of your code with a temporary string to fix this:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>


#define BINARY_ACCURACY 32

int convertDezToDualString(const int number, char stringDualNumber[]){
    char tempstr[32];
    int num = number;
    if (number<0){
        //nothing here yet
    } else {
        for (int i = 0; i<BINARY_ACCURACY; i++){
            strcpy(tempstr, stringDualNumber);
            sprintf(stringDualNumber,"%d%s",num%2,tempstr);
                   //I think that's the part where the thing happens
            printf("%s",stringDualNumber);    //For Testing purposes
            printf("\n");
            num/=2;
        }

    }
}

int main() {
    char* stringDualNumber= (char*) calloc(BINARY_ACCURACY,sizeof(char));
    const int dezNumber = 5;    //Gets a decimal number and returns if it's valid
    convertDezToDualString(dezNumber, stringDualNumber);
}
tonebender
  • 69
  • 4
0

First, you should terminate stringDualNumber at the beginning, because you pass it to sprintf() with a freshly allocated memory area. Obviously your memory is initialized with zeros (so I guess you're running a debug build).

Second: Think about what the sprintf() does: At first it writes the value of num%2 to your string. And after that it writes the content of your string itself. But at this moment your string already contains the new digit. That's why you see it twice.

Edit:
The first loop writes
'0' + (string now) "0" = "00"
The second loop overwrites the string with
'1' (changing "00" to "10") + (string now) "10" = "110"
and so on ...

MattTT
  • 339
  • 3
  • 9
0

You need to allocate enough space to accommodate the null terminating character.

I would not use sprintf monster function for this job. It can be achived in a much much more efficient way:

char *convertToBinString(unsigned val, char *buff, int printLeadingZeroes)
{
    unsigned mask = 1 << (sizeof(val) * CHAR_BIT - 1);
    char *wrkbuff = buff ? buff : calloc(sizeof(val) * CHAR_BIT + 1, 1);
    
    buff = wrkbuff;
    if(wrkbuff)
    {
        for(; mask; mask >>= 1)
        {
            if(!printLeadingZeroes) 
            {
                if(val & mask) printLeadingZeroes = 1; 
            }
            if(printLeadingZeroes)
            {
                *wrkbuff++ = val & mask ? '1' : '0';
            }
        }
    }
    return buff;
}

int main(void)
{
    char *buff = NULL;
    int x = 1234;
    printf("%8d in binary is: %s\n", x, (buff = convertToBinString(x, buff, 0)));
    printf("%8d in binary is: %s\n", x, (buff = convertToBinString(x, buff, 1)));
    x = -1234;
    printf("%8d in binary is: %s\n", x, (buff = convertToBinString(x, buff, 0)));
    printf("%8d in binary is: %s\n", x, (buff = convertToBinString(x, buff, 1)));
    free(buff);
}```

https://godbolt.org/z/dc1KxWaqr
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Any comment DV-ter? Anything is wrong with this answer? – 0___________ May 28 '21 at 12:33
  • @Jabberwocky it is **not NUL** character only **null** character. From the C standard: *`A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string.`* – 0___________ May 28 '21 at 12:50
  • You're right about `null`, but it's very often also called NUL. UV is mine BTW. – Jabberwocky May 28 '21 at 12:53
-2
int convertDezToDualString(const int number, char stringDualNumber[]){
    int num = number;
    for (int i = BINARY_ACCURACY-1; i>=0; i--){
        stringDualNumber[i]=48+(num%2);
        num/=2;
    }
}

I think that one is better... I know that I allocated too less. It was more of a desperate try to fix this issue. No matter that it would've given the same output.

MrMxffin
  • 1
  • 2
  • It's not using magic numbers (https://www.c-howto.de/tutorial/anhang/ascii-tabelle/) it's a way to convert digits to chars, you were just plugging in -1234 which is a negative number, which can't get into this part of the method anyways. when negative odd ints are halved they round down. that's why your -0.5 gets -1, which leads to the char value of 47 which is "/" – MrMxffin May 28 '21 at 12:37
  • I would rather advise you to learn from own mistakes, not defend something which cannot be defended. It is a very "naive" way of converting chars and better do not use this site for learning. The second part of your comment makes not sense in the context of your answer – 0___________ May 28 '21 at 12:45
  • @MrMxffin not my DV but `48` should be `'0'`. And you don't address the problem that he's not allocting enough space for the resulting string. – Jabberwocky May 28 '21 at 12:46
  • @Jabberwocky but it is still not portable bad way – 0___________ May 28 '21 at 12:47
  • @0___________ formally you're right, but even in EBCDIC (which virtually no no one uses anyway) the values of 0 to 9 are consecutive, so even with EBCDIC the code with `0` would work, so it is de facto portable. – Jabberwocky May 28 '21 at 12:50
  • @Jabberwocky why shall one do something the wrong way if it is a very easy way of doing it correctly? – 0___________ May 28 '21 at 12:57