Skip to content
Maxwell Talley edited this page Sep 13, 2017 · 6 revisions
  • FILE fopen(const char *path, const char *mode);
    • Used to open a file
    • path is the path to the file
    • mode is the file access mode (read, write, append, or read/write)
    • read == "r"
    • write == "w"
    • append == "a"
    • binary == "b" (necessary when using binary files in windows; otherwise a no-op)
    • Returns NULL on failure
  • int fclose(FILE *fp);
    • Closes a file previously opened by fopen()
  • int fprintf(FILE *stream, const char *format, ...);
    • Just like printf(), but first parameter is a FILE *
  • int fscanf(FILE *stream, const char *format, ...);
    • Analogous to printf, but for reading
    • To read an int (from standard input: fscanf(stdin, "%d", &i);)
  • char *fgets(char *s, int size, FILE *stream);
    • Reads one line at a time, up to size bytes, where size if the ammount of storage available in s; analogous function called gets()
  • size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    • Writes binary data to file from ptr, each element is size bytes, there are nmemb elements, write to stream
    • Returns the total number of elements successfully returned as a size_t object. If this number is different from nmemb, it will throw an error.
  • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    • Analogous to fwrite, but reads
  • int fseek(FILE *stream, long int offset, int whence)
    • stream: file object
    • offset: number of bytes to offset from whence
    • whence: position from whence offset is added. Specified by one of the following:
      • SEEK_SET -- beginning of file
      • SEEK_CUR -- current position of the file pointer
      • SEEK_END -- end of file

Example

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

typedef enum action {
  read_binary,
  read_text,
  write_binary,
  write_text
} action_t;

int main(int argc, char *argv[])
{
  action_t action;
  FILE *f;
  /* This is called an "anonymous structure".  Notice how it doesn't *
   * have a name.  The instance, s, has a name (s), but the type     *
   * does not!                                                       */
  struct {
    char i;
    char j;
  } s = { 1, 2 };

  if (argc != 3) {
    fprintf(stderr, "Wrong number of paramenters\n");
    return -1;
  }

  if (argv[1][0] != '-') {
    fprintf(stderr, "Bad argument format\n");
    return -1;
  }

  /* I did it this way (below) to illustrate indexing individual *
   * characters in the argument vector.  Far more robust would   *
   * be to use strcmp(), for example:                            *
   *    if (!strcmp(argv[1], "-wt")) {                           *
   *      action = write_text;                                   *
   *    } else if ...                                            *
   * Using the above technique obviates the need for the if      *
   * statement above.  We can instead have a final else to       *
   * handle errors.                                              */
  if (argv[1][1] == 'w') {
    if (argv[1][2] == 't') {
      action = write_text;
    } else {
      action = write_binary;
    }
    f = fopen(argv[2], "w");
  } else {
    if (argv[1][2] == 't') {
      action = read_text;
    } else {
      action = read_binary;
    }
    f = fopen(argv[2], "r");
  }
  if (!f) {
    fprintf(stderr, "Couldn't open file\n");
    return -1;
  }

  /* We almost finished in class, but three of these cases were not *
   * filled in.  Go ahead and try this out.  We'll look at the      *
   * other three and take questions on Friday.                      */
  switch (action) {
  case read_text:
    fscanf(f, "%hhd %hhd", &s.i, &s.j);
    printf("%d %d\n", s.i, s.j);
    break;
  case read_binary:
    fread(&s, sizeof (s), 1, f);
    printf("%d %d\n", s.i, s.j);
  break;
  case write_text:
    fprintf(f, "%d %d\n", s.i, s.j);
    break;
  case write_binary:
    /* We did this one in class, but not the three above. */
    fwrite(&s, sizeof (s), 1, f);
    break;
  }

  /* What happens if you write a file as binary, then try to read it as *
   * text?  If you write as text and try to read as binary?  In either  *
   * case, nothing good.  There is nothing to protect you from this.    */

  return 0;
}
Clone this wiki locally