-1

I need to be able to take a textfile: e.g. text.txt

a
b
c
0
1
2

and I need to print the binary values of these characters. This is what I have written so far:

#include "p01.h"
int main(int argc, char **argv) {
  FILE *fptr = fopen(argv[1],"r");
  char buf[50];

  for(long i =0; i<6; i++) {
    fscanf(fptr, "%c", &buf[i]);
    fgets(buf, 50, fptr);
    fprintf(stdout,"[%d]%c %d\n", i, buf[i], (int)buf[i]);

  }
  return 0;
}

This is the current output I have:

[0]
 10
[1] 0
[2]c 99
[3]0 48
[4]1 49
[5]2 50

I am not really sure why it is printing a newline, skipping a and b, and then I am not even sure how to approach printing their bits. Any help would be much appreciated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • What do you mean "binary"? As in `00101001`? Hint: [There are answers like that](https://stackoverflow.com/questions/41384262/convert-string-to-binary-in-c). – tadman Sep 26 '20 at 22:58

1 Answers1

0

Your loop is:

for (long i = 0; i < 6; i++) {
    fscanf(fptr, "%c", &buf[i]);
    fgets(buf, 50, fptr);
    fprintf(stdout, "[%d]%c %d\n", i, buf[i], (int)buf[i]);
}

On the iteration when i is 0, you read a into buf[0] with scanf(). Then, the fgets() call reads the newline over buf[0] and places a null byte to mark the end of the input over buf[1]. Therefore, the fprintf(stdout, …) call (conventionally written printf(…)) produces the data for a newline as that's the character stored in buf[0].

On the iteration when i is 1, you read b into buf[1] with scanf(). Then the call to fgets() reads the newline over buf[0] and places a null byte to mark the end of the input over buf[1]. Therefore, the printing operation prints the data about the null byte as that's the character stored in buf[1].

On the subsequent iterations, the fgets() call continues to write over buf[0] and buf[1], but the rest of your code is looking after those characters and isn't affected.

Mixing scanf() and fgets() like this is dubious. It would probably be best to use just

if (scanf(fptr, " %c", &buf[i]) != 1)
    break;

and drop the fgets() completely. The leading space in the format string skips optional white space, meaning blanks, tabs and (crucially) newlines. On the first iteration, it skips nothing; on the second, it skips the newline and proceeds to read b. And there's no confusing overwriting going on. If you add a null terminator, you'd have the string abc123 in buf after the loop and null termination.

Alternatively, just use fgets() and always work with buf[0].

Note that the cast to int is immaterial. When a char value is passed to printf() or fprintf(), it is automatically converted to int — both the arguments buf[i] are passed as int, regardless of the presence or absence of a cast. See C11 §6.5.2.2 Function calls ¶7 — and ¶6 is also relevant for the definition of default argument promotions. There's room for more discussion, but it is more complex than needed to answer this question.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278