Thread: Reading 16 bit binary numbers from file

  1. #1
    Registered User
    Join Date
    Feb 2015
    Posts
    23

    Reading 16 bit binary numbers from file

    This is supposed to read a series of 16 bit binary numbers as short ints in the array memory. However, it only appears to be reading the first number, and I can't figure why.

    Code:
    short int memory[256];
    
    void readFile(){
        //read input file into int memory[]
        FILE *ifp;
        ifp = fopen("proj1a.dat", "r"); //input file 
        
        //validates file exists
        if (ifp == NULL)
        {
            perror("proj1a.dat");
            exit(0);
        }
           
        char str[16];//current line from file 
        int i = 0; //index of memory
        while(fgets(str, 17, ifp)){
            memory[i] = (short)(strtol(str, NULL, 2));
            printf("%d\n", memory[i]);//DEBUG
            i++;
        }
    }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Please post a small sample of your input file.

    Also post a sample of what your program is outputting and what you expect the program to output.


    Jim

  3. #3
    Registered User
    Join Date
    May 2014
    Posts
    121
    What exactly do you mean when you say "16 bit binary numbers"? If you have a string like "123" then strtol can convert that to the integer 123 but strtol does not handle 16 bit code points. If it's just 16 bit binary numbers you want to read then use fread with a pointer to your memory buffer. If it's a text file encoded as UTF-16 or similar then it gets a bit more tricky. If wchar_t is 16 bits on your platform then you can use fgetws and wstrol but otherwise you'll need to read the raw binary data with fread and implement the string to number conversion yourself.

  4. #4
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    Sample input:
    0000000000001010
    0001000000001000
    0000000100001011

    Expected output:
    10
    4104
    267

    Actual output:
    10

    @MOS: The third parameter for strtol is the base, which I set to 2. Reading the binary numbers appears to be working correctly, its just that it only does it once instead of continuing.

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Please do NOT lie to the compiler!

    You tell it to have space for 16 then later you tell it to put 17 in it.
    Code:
    char str[16];//current line from file
    I suggest changing the 16 to 20 for now; then, learn whether the correct value is 17,18, or 19 for your program later.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    Thank you, this works. Changing the size of str to anything less than 18 gives a completely wrong output. Could anyone explain why this is the case? Each line of the input file has 16 chars, so I would expect str to only need to be 16 chars long.

    Code:
    void readFile(){
        //read input file into int memory[]
        FILE *ifp;
        ifp = fopen("proj1a.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
        
        //validates file exists
        if (ifp == NULL)
        {
            perror("proj1a.dat");
            exit(0);
        }
           
           char str[18] = {0};//current line from file 
           int i = 0; //index of memory
        while(fgets(str, sizeof(str), ifp) != NULL){
            memory[i] = (short)(strtol(str, NULL, 2));
            printf("%d\n", memory[i]);//DEBUG
            i++;
        }
    }

  7. #7
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Take a look at how fgets() works. You have 16 characters to read in + the newline + the null terminating character for a grand total of 16 + 1 + 1 = 18. Just because you don't see the characters doesn't mean they aren't there. fgets will automatically reserve space for applying the null terminating character '\0' so right of the bat you will only read num-1 characters. fgets also views the newline character '\n' as valid input so it will try to read that into the buffer as well.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Because in C a string is always terminated by the end of string character '\0', and you must reserve room for this character.
    fgets also views the newline character '\n' as valid input so it will try to read that into the buffer as well.
    But if there is not enough room in the string, fgets() leaves the end of line character in the stream. This could cause problems for the next extraction operation, fgets() for example will retrieve this character and consider it's job done.

    Jim
    Last edited by jimblumberg; 03-15-2015 at 08:28 PM.

  9. #9
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    But the newline and null terminating character are after the data though, correct?
    For example: 0001000100010001\n\0

    So why doesn't fgets(str, 16, ifp) just get the first 16 characters? Does fgets() take the last N characters from each line?

    EDIT:
    @Jim: Didn't see your reply until after I posted. I think I understand now.
    Last edited by PsylentKnight; 03-15-2015 at 08:33 PM.

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    So why doesn't fgets(str, 16, ifp) just get the first 16 characters?
    Because fgets() always reserves room for the end of string character, meaning it will retrieve only 15 actual characters from the file, if your limit is 16. Your fgets call will retrieve "000100010001000" and append the end of string character to the string. This will leave these characters in the file: "1\n" for the next extraction operation.

    By the way the end of string character is not found inside a text file.

    Jim

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 11-28-2012, 09:16 AM
  2. Replies: 12
    Last Post: 06-18-2012, 08:23 AM
  3. Reading in numbers from a binary file
    By Tagg in forum C Programming
    Replies: 5
    Last Post: 11-23-2010, 01:41 PM
  4. Reading numbers from a file, how can I do it?
    By angeloulivieri in forum C Programming
    Replies: 2
    Last Post: 06-11-2010, 05:11 AM
  5. Floating point numbers in a binary file
    By frenchfry164 in forum C++ Programming
    Replies: 6
    Last Post: 07-31-2003, 10:04 AM