Last Updated: 2019-02-07 Thu 14:27

CSCI 2021: C Text and Binary I/O

CHANGELOG: Empty

1 Rationale

The below Problem/Solutions were part of a past lab which demonstrated some basic techniques and common problems associated with C's I/O functions, particularly fread() and fwrite(). They are provided to supplement the treatment of these topics in lecture and support development on Assignment 1.

Associated Reading / Preparation

C reference material on fread() / fwrite() for binary I/O. For a full reference on these functions, you may consult the manual pages on a system or online here:

2 Problems / Solutions

A

  FILE *fin = fopen(...,"r");
  int buf[4];             // store 4 ints from file in this array 
  fread(buf, 4, 1, fin);  // want to read 4 ints from fin into buf (error)

Describe why the marked line is an error and provide a correction.

Solution   solution

The 2nd argument of fread() is the size of each element to be read while the third argument is how many to read. If the intent is to read 4 integers, ensure that the proper size is set using sizeof(int) and the number of ints to read is specified as below.

  fread(buf, sizeof(int), 4, fin);

Alternatively, one could read the integers in one at a time as in the following.

for(int i=0; i<4; i++){
  fread(&buf[i], sizeof(int), 1, fin);
}

B

Describe why the below code does not actually write the entire double array buf to a file properly.

  FILE *fout = fopen(...,"w");
  int length = ...;
  double *buf = malloc(length*sizeof(double)); 
  // fill in buf with values
  for(int i=0; i<length; i++){              // write doubles from buf one at a time
    fwrite(buf, sizeof(double), 1, fout);   // error
  }

Solution   solution

One double is being written at each call to fwrite(). Since the pointer buf does not change, it will always be the 0th double in the array. To fix this, advance forward in buf by providing an offset using code like:

    fwrite(&buf[i], sizeof(double), 1, fout);   
    // OR
    fwrite(buf+i,  sizeof(double), 1, fout);   

C

Describe why the following code could potentially cause unexpected problems.

  FILE *fin = fopen(...,"r");
  char buf[100];             // store up to 100 characters
  int pos = 0;
  while(1){
    int result = fscanf(fin, "%d", &buf[pos]);
    if(result == EOF){
      break;
    }
    pos++;
  }
  // error in logic, may overflow buf: why?

Solution   solution

Reading an unknown number of characters into a buffer size 100 is dangerous. If there are more than 100 characters, the ready may overflow the buffer clobbering arbitrary memory locations. This may corrupt other data or cause a segmentation fault.

Fix with either a limit like:

  while(pos < 100){
    int result = fscanf(fin, "%d", &buf[pos]);
    if(result == EOF){
      break;
    }
    pos++;
  }

or by counting and allocating using malloc() as per the assignment.

D

Describe why the code below gets a compiler error.

// read two binary ints from given file, return pointer to them
int *read_2_ints(char *fname){  
  FILE *fin = fopen(fname,"r");
  int buf[2];
  fread(buf, sizeof(int), 2, fin);
  fclose(fin);
  return buf;  // compile error
}

Solution   solution

You cannot return a stack allocated array from a function. Use malloc() for this as in:

// read two binary ints from given file, return pointer to them
int *read_2_ints(char *fname){  
  FILE *fin = fopen(fname,"r");
  int *buf = malloc(sizeof(int)*2);
  fread(buf, sizeof(int), 2, fin);
  fclose(fin);
  return buf;
}

Author: Chris Kauffman (kauffman@umn.edu)
Date: 2019-02-07 Thu 14:27