0

I am trying to get some plain Ruby code ported to the C language for speed but I am not really being able to achieve that as C is not my primary language and I am struggling to understand what is causing it. Here is the code in Ruby for clarity of the purpose:

source_file = open("/tmp/image.jpg")
content = source_file.read
content_binary_string = content.unpack("b*")[0]
content_integer = content_binary_string.to_i(2)

I've been then playing around with several attempts in C to achieve the same results and somehow I am stuck on the binary comparison between the Ruby and C outputs. Here is the C code I've got so far:

// gcc -Wall -Wextra -std=c99 xxd.c
#include <stdio.h>
#include <string.h>

int main() {
  char buffer[32];
  FILE *image;
  image = fopen("/tmp/image.jpg","rb");
  while (!feof(image)) {
    fread(buffer, sizeof(buffer), 1, image);
    const size_t len = strlen(buffer);
    for (size_t j = 0; j < len; j++ ) {
      for (int i = 7; i >= 0; i--) {
        printf(buffer[j] & (1 << i) ? "1" : "0");
      }
    }
  }
  return 0;
}

Please notice that the C code is not yet complete and that I am for now printing the binary value so I can compare the output with the current working code and I believe I am missing some basic concept that is abstracted by Ruby like byte size or something else that is not obvious to me yet. The output is quite different at this point.

After I get that step right, then the goal is to produce an integer based value from that.

Any clues towards understanding why that output isn't accurate is highly appreciated!

fagiani
  • 2,293
  • 2
  • 24
  • 31
  • 2
    First you need to [find a good beginners book in C](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) and learn it. Then you should read [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Some programmer dude Apr 28 '16 at 06:45
  • 4
    `const size_t len = strlen(buffer);` could not be used for binary. [strlen](http://www.tutorialspoint.com/c_standard_library/c_function_strlen.htm) works only for C-Strings. BTW read function returns _The total number of elements successfully read bytes_ – LPs Apr 28 '16 at 06:45
  • 3
    On a general note, if printing in hex would do, use printf() with a %x. You can not use strlen() reliably here. On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. So use the return value instead of strlen() – subin Apr 28 '16 at 06:48
  • 4
    You are not checking return values of the file functions. Error checking in C is **vital** or you'll get *undefined behaviour* if something fails. – user694733 Apr 28 '16 at 06:50

1 Answers1

1
  1. feof() should be used after an input function indicated a failed read . It distinguishes if the failure was due to End-of-File.

  2. strlen() reports the length (not including null character) of a string. In C, a string is a sequence of characters up to and including the null character. Do no use this to determine how many bytes are in a buffer. Use the return value of fread(). @subin

  3. Check the return value of input functions. @user694733

  4. Avoid using a string that is not a format string as the first argument to printf().

  5. Better to use unsigned like 1u with bit operations.

  6. Minor: Avoid magic numbers like 7. CHAR_BIT is available in <limit.h>.

  7. Minor: Use fclose() Put your toys away when done.


  image = fopen("/tmp/image.jpg","rb");
  if (image == NULL) Handle_OpenFailure();

  size_t count;
  while ((count = fread(buffer, sizeof buffer[0], sizeof buffer, image)) > 0) {
    for (size_t j = 0; j < count; j++ ) {
      for (int i = CHAR_BIT-1; i >= 0; i--) {
        fputc(buffer[j] & (1u << i) ? '1' : '0', stdout);
      }
    }
  }
  fclose(image);
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256