0

I am trying to read in multiple lines in a file ,convert each line to binary. I reckon that for each line, we need to shift every 4 char in order to store the next 4. However I am not sure if the only way to store binary i.e. 0010 is as a String.Can someone please help? I can't get my head around how to do this. Many thanks!

  • Hexadecimal, decimal and binary are only representations of integer numbers and they can be stored as a string. Your `strcat` idea works, but you must zero-terminate `inter` and you should use ASCII codes for the digits, i.e. `'0'` and `'1'` in single quotes instead of `0` and `1`. Better yet, use string literals in double quotes: `strcat(output, "0011")`. – M Oehm Oct 08 '14 at 11:15
  • 2
    Forget your for loop. This is definitly awkward (you need 16 case labels). For each line read use `strtol` to convert the hex string into a number, and then convert that number into binary for example by using the shift (<<) operator. – Jabberwocky Oct 08 '14 at 11:17
  • @MOehm Thanks! By zero-terminate, do you mean adding inter [4] ='/0'? I wish I could store 0011 as something else rather than assigning an array each time.. – stillAFanOfTheSimpsons Oct 08 '14 at 11:19
  • @MichaelWalz Thank you! This sounds much more feasible. Could you elaborate? Can I not convert hex string directly to base 2 number using strtol? Or you mean convert the one char of the hex string to binary at a time, and then shift the numbers? – stillAFanOfTheSimpsons Oct 08 '14 at 11:26
  • @MichaelWalz : Don't you mean `>>` (and bitwise `&`)? And then of course we need to convert the bits back to char, which we can do with '|' or addition. – PM 2Ring Oct 08 '14 at 11:28
  • You need to use strtol to get the number and then use http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format to get the binary equivalent. As M Oehm said, these are all just representation of a number. – vvvv Oct 08 '14 at 11:32
  • 1
    user4056620 `strtol()` converts a string to a C long integer. And that integer is stored in memory as a binary number. But to get at those bits you need to use C's bit manipulation operators like `>>`, `&` and `|'. – PM 2Ring Oct 08 '14 at 11:32
  • In python its just `print(bin(int(line,16))[2:])` where `line` contains hex string – Ashwani Oct 08 '14 at 11:35
  • 2
    @AshwaniDausodia : maybe, but we are talking C here. – Jabberwocky Oct 08 '14 at 11:36
  • Eg. `n = strtol("1e2", NULL, 16);` converts the hex string to a C integer. `n&1` gives you the value of the least significant bit (LSB) as a C integer, which in this case is 0. `(n>>1)&1` shifts all the bits of `n` one place to the right and then gives you the LSB of that, which is 1. Make sense? – PM 2Ring Oct 08 '14 at 11:37
  • @PM2Ring : no I meant `<<` and yes we'd also need `&`. – Jabberwocky Oct 08 '14 at 11:38
  • 1
    @MichaelWalz : Ok. I guess that makes sense since were dealing with bitstrings of a fixed known length. And my way unfortunately generates the bits in reverse order. – PM 2Ring Oct 08 '14 at 11:41

4 Answers4

1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int n, k;
    char * nptr = "1e2", *endptr;              // nptr contains hex
    n = strtol(nptr, &endptr, 16);             // n contains decimal
    char bin[33];                              // bin contains binary
    int index = 0;
    while(n != 0)
    {
        if (n & 1)
            bin[index++] = '1';
        else
            bin[index++] = '0';
        n = n >> 1;
    }
    bin[index] ='\0';
    printf("%s", strrev(bin));
    return 0;
}

edit:
if you want a 32 bit number with leading zeros then:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int n, c, k;
    char * nptr = "1e2", *endptr;              // nptr contains hex
    n = strtol(nptr, &endptr, 16);
    char bin[33];
    int index = 0;
    for (c = 31; c >= 0; c--)
    {
        k = n >> c;
        if (k & 1)
            bin[index++] = '1';
        else
            bin[index++] = '0';
    }
    bin[index] = '\0';
    printf("%s", bin);
    return 0;
}
Ashwani
  • 1,938
  • 11
  • 15
  • Thanks! but I don't quite get the logic here: does n = strtol(nptr, &endptr, 16) convert nptr to decimal number? should it be strtol(nptr, &endptr, 10)? Another thing is that science n is decimal, i.e. 234, how can we use n & 1 to get the binary bit in bin? – stillAFanOfTheSimpsons Oct 08 '14 at 12:12
  • suppose `n = 234` or `11101010` in binary. `n & 1` is nothing but `11101010 & 00000001` which will be `1` if rightmost bit of `n` is `1`, `0` otherwise. If you don't know about **bitwise** operators, google it. – Ashwani Oct 08 '14 at 12:18
  • @PM 2Ring you can easily modify it to get 12 bit output. Assuming 12 bits are enough to hold the value, you can igonre first 20 charcters in string `bin`. – Ashwani Oct 08 '14 at 12:19
  • Sure. And I guess it's a good exercise for the OP to do that modification, once they understand your code better. It seems they don't quite get how all `int`s are actually stored as binary. But I let you try to explain that. :) – PM 2Ring Oct 08 '14 at 12:28
  • @user4056620 This link may help you [Number Bases and C’s Bitwise Operators](http://www.ece.ubc.ca/~edc/380.jan98/lectures/lec3.pdf) – Ashwani Oct 08 '14 at 13:14
1

This accepts a three character hex input and outputs a 12 character binary string. The function will accept arguments to change the input and output lengths. iLenOut should be at least the length of the hex input * 4.

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

int hextobin ( char *pacHexIn, char *pacBinOut, int iLenOut) {
    char acHexChars[17] = { "0123456789abcdef"};
    char *pcEachHex = NULL;
    unsigned int  uiHexIndex = 0;
    int  iEachBit = 0;
    int  iInputLen = 0;
    int  iOutputLen = iLenOut;

    if ( iLenOut % 4) {
        printf ( "as each hex character will result in 4 bits, use an even multiple of 4\n");
        return 2;
    }
    while ( iOutputLen) {
        pacBinOut[iOutputLen] = '0';
        iOutputLen--;
    }
    iOutputLen = iLenOut;
    iInputLen = strlen ( pacHexIn); // get length of input
    while ( iInputLen > 0) {
        iInputLen--;
        iOutputLen -= 4;
        pacHexIn[iInputLen] = tolower( pacHexIn[iInputLen]); // make sure input is lower case
        if ( ( pcEachHex = strchr ( acHexChars, pacHexIn[iInputLen])) != NULL) { // get index to acHexChars
            uiHexIndex = pcEachHex - acHexChars; // difference will be the value of the hex char f=15...

            for ( iEachBit = 3; iEachBit >= 0; iEachBit--) { // loop through the bits
                if ( 1 & ( uiHexIndex >> iEachBit)) { // right shift and compare to 1
                    pacBinOut[ iOutputLen + ( 3 - iEachBit)] = '1'; // set to 1
                }
                else {
                    pacBinOut[ iOutputLen + ( 3 - iEachBit)] = '0'; // set to 0
                }
            }
        }
        else {
            printf ( "Only input hex values 0-9 and a-f\n"); // invalid input
            return 1;
        }
    }
    pacBinOut[iLenOut] = '\0'; // make sure string is terminated
    return 0;
}

int main()
{
    char acInput[9] = { 0};
    char acBinary[33] = { "00000000000000000000000000000000"};
    scanf ( "%3s", acInput); // input 3 hex characters, acInput will allow for up to 8 characters
    if ( ( hextobin ( acInput, acBinary, 12)) == 0) { // return binary string of 12 characters, acBinary will allow up to 32
        printf ( "%s\n", acBinary); // print result
    }
    else {
        printf ( "conversion failed\n");
    }
    return 0;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16
0

Try this:

char inter[5];

const char *binary = std::bitset<4>(input [i] -'0').to_string().c_str(); //to binary
strcpy(inter, binary);

need to include <bitset>, <string> and <string.h>

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • 2
    Neither this method nor the includes are [tag:c], which is what the OP asks for. While it may be interesting to the OP to see how it's done in *another language*, it is not an answer to the question. – Jongware Oct 08 '14 at 12:59
0
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char *argv[]){
    static const char *table[] = {
        "0000","0001","0010", "0011",
        "0100","0101","0110", "0111",
        "1000","1001","1010", "1011",
        "1100","1101","1110", "1111"
    };
    FILE *file = fopen("data.txt", "r");
    char input[5], output[13] = {0};

    while (fgets(input, 5, file)!=NULL){
        char *p = output;
        for ( int i = 0; i < 3; ++i){
            if(isdigit(input[i]))
                memcpy(p, table[input[i]-'0'], 4);
            else //a-f
                memcpy(p, table[tolower(input[i])-'a'+10], 4);
            p += 4;
        }
        puts(output);
    }
    fclose(file);
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70