2

I am trying to write a small bit of code where i can scan a binary digit, like 00110011, and get this into an integer as a number. So 00110011 would be 51. The code i made for this goes like this

int main()
{
    unsigned char byte;
    int d;

    scanf("%8s", &byte);

    d = byte;

    printf("%d,%c",d, byte);
    return 0;
}

This however, give me an output of 48. 00000001 also gives me 48 and so does anything else. I know whats going wrong, it sees the string of zeros and ones as a single 0 and since its character is 0x30, or 0d48, it outputs 48. I wont to know if there is a way to get around this adn scan this in as the binary equivelent.

marko
  • 9,029
  • 4
  • 30
  • 46
Bas de Wildt
  • 23
  • 1
  • 3
  • `48` is the ASCII code for the character `0`. Does this provide any clues? – marko Sep 17 '21 at 18:46
  • 2
    If you read into a string you can apply [`strtol`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strtol-wcstol-strtol-l-wcstol-l?view=msvc-160). You have better verification than with `scanf` and anyway, there is no binary format specifier. – Weather Vane Sep 17 '21 at 18:50
  • @marko ye thats what i meant with 0x30, meaning 48 in hex – Bas de Wildt Sep 17 '21 at 18:51
  • 2
    Your call to `scanf` reads in a string of eight characters (which takes up 9 bytes), but you only allocate space for a single byte. – David Schwartz Sep 17 '21 at 18:54
  • @Weather Vane I know there isnt a binary format specifier. But i still want to be able to scan it in. – Bas de Wildt Sep 17 '21 at 18:56
  • @DavidSchwartz how do i allocate more space? – Bas de Wildt Sep 17 '21 at 18:57
  • You could scan it as `unsigned long long` and write some code to convert the 'fake' binary value to true binary. But the input range would be only 20 bits and you might as well do it properly. And you have no error control if say `10007` was entered, which isn't binary. – Weather Vane Sep 17 '21 at 18:58
  • `"how do i allocate more space?"` -- By changing `unsigned char byte;` to `unsigned char bytes[9];`. Afterwards, you can use `scanf` (or `fgets`) and `strtol` on it, to solve your problem. – Andreas Wenzel Sep 17 '21 at 18:59
  • @WeatherVane I'm sorry, I'm not that experienced in C. What is unsigned long long, and how would i do it properly? – Bas de Wildt Sep 17 '21 at 19:00
  • 1
    The way I [mentioned](https://stackoverflow.com/questions/69228173/way-to-scanf-binary-number?noredirect=1#comment122358925_69228173) is generally satisfactory. There is example usage [here](https://stackoverflow.com/questions/14176123/correct-usage-of-strtol). – Weather Vane Sep 17 '21 at 19:01
  • 1
    Generally, I recommend that you use `fgets` and `strtol` instead of `scanf`. See this link for further information: [A beginners' guide away from scanf()](http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html) – Andreas Wenzel Sep 17 '21 at 19:04
  • @AndreasWenzel Ye, this is a bit too hard for me to understand. I think it's best if i just let this rest until i have some more experience. – Bas de Wildt Sep 17 '21 at 19:13
  • you cannot `scanf` a binary number... only octal, decimal and hexadecimal bases are allowed. – Luis Colorado Sep 19 '21 at 11:16

2 Answers2

2

Your code does not work at all:

  • you scan up to 8 characters plus a null terminator, passing the address of a single byte variable: this has undefined behavior.
  • d = byte does not perform any conversion. the character '0' was read into byte and its ASCII value is stored into d, namely 48 as output by your program.

Furthermore, there is no standard conversion specifier for binary encoding in scanf(). Reading a string is a good approach, but you should pass a larger buffer and use a loop to convert to binary:

#include <ctype.h>
#include <stdio.h>

int main() {
    char buf[100];

    /* read a sequence of at most 99 binary digits into buf */
    if (scanf(" %99[01]", buf) == 1) {
        unsigned int d = 0;
        /* convert the binary digits one at a time into integer d */
        for (int i = 0; buf[i]; i++) {
            d = (d << 1) | (buf[i] - '0');
        }
        /* print value as a number */
        printf("%s -> %d\n", buf, d);
        if (d == (unsigned char)d && isprint(d)) {
            /* print value as a character if printable */
            printf("%s -> %c\n", buf, d);
        }
    }
    return 0;
}

You can also use strtoul() to convert a number expressed as a string of binary digits (or in any other base up to 36):

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

int main() {
    char buf[100];

    /* read a sequence of at most 99 binary digits into buf */
    if (scanf(" %99[01]", buf) == 1) {
        unsigned long d = strtoul(buf, NULL, 2);
        /* print value as a number */
        printf("%s -> %lu\n", buf, d);
        if (d == (unsigned char)d && isprint((unsigned char)d)) {
            /* print value as a character if printable */
            printf("%s -> %c\n", buf, (unsigned char)d);
        }
    }
    return 0;
}

Note however that the behavior of strtoul() will differ from the first code: strtoul() will return ULONG_MAX on overflow, whereas the first example would just compute the low order bits of the binary string.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • thank you for you awnser. Do you think it is possible to get value d out side of this bit of script so i can use it for another bit underneath? – Bas de Wildt Sep 17 '21 at 19:48
  • @BasdeWildt: I am not sure what you mean. The converted value is in the integer variable `d`. You can perform further tasks with it. Study the functions and modify to fit your purpose. – chqrlie Sep 17 '21 at 19:50
0

I found this simple function that should be easy to understand and it does the trick. Its a algorithm that follows how you would naturally do it in real life with a pen and paper however you're gonna need -lm when you compile it(the gcc command) to include the math library, however you can get around the pow() and include problems if you just do a for loop.

#include <stdio.h>
#include <math.h>
int todecimal(long bno){
   int dno = 0, i = 0, rem;
   while (bno != 0) {
      rem = bno % 10;
      bno /= 10;
      dno += rem * pow(2, i);
      ++i;
   }
   return dno;
}
Imeguras
  • 436
  • 6
  • 18
  • 3
    It's not really good advice to use `pow` for powers of 2 in an integer context. Shifting is better. – Weather Vane Sep 17 '21 at 19:05
  • There is generally nothing wrong with asking homework questions, as long as OP shows a good-faith attempt (which I believe is the case here). See this link for further information: [How do I ask and answer homework questions?](https://meta.stackoverflow.com/q/334822/12149471) – Andreas Wenzel Sep 17 '21 at 19:08
  • If you really *found* the function presented then it is obligatory to cite the source. If you mean you *wrote* it, then please clarify that. – John Bollinger Sep 17 '21 at 21:11
  • @WeatherVane but he seems like a beginner thats why i didn't complicate nothing and yes shifting is really easy concempt but a very weird one for people who are starting out – Imeguras Sep 17 '21 at 21:37
  • @AndreasWenzel well im used to seeing countless closed questions due to people just dumping their homework assignments here – Imeguras Sep 17 '21 at 21:38