Reading
The C standard library automatically provides every running program with 3 I/O channels:
stdin (standard input):
    stdout (standard output):
    stderr (standard error):
    <stdio.h> contains prototypes for standard I/O functions such as printf(),
scanf(), and many many more (see K&R2, appendix B).
You can have stdin come from a file instead of the keyboard:
./isort < file_containing_a_number
And have stdout go to a file instead of the screen:
./isort > my_sorting_result
Use 2> to redirect stderr:
./myprogram 2> myerrors
Use >> to append to an existing file:
./myprogram  >> myoutput_of_multiple_runs
./myprogram 2>> myerrors_of_multiple_runs
Use 2>&1 to have stderr go to the same place that stdout` is going to:
./myprogram > my_output_and_errors 2>&1
But the following is not the same thing:
# this does NOT work
./myprogram 2>&1 > my_output_and_errors
So here is how you have your valgrind output appended to your README.txt:
valgrind --leak-check=yes ./myprogram >> README.txt 2>&1
A pipe connects stdout of one program to stdin of another program:
prog1 | prog2 | prog3
You can throw redirections in there too:
prog1 < input_file | prog2 | prog3 > output_file
Or equivalently:
cat input_file | prog1 | prog2 | prog3 > output_file
You can include prog1’s stderr in the flow like this:
cat input_file | prog1 2>&1 | prog2 | prog3 > output_file
[A little demo of manipulating isort output.]
int scanf(const char *format, ...)
int n;
double x;
char a[100];
scanf("%d", &n);
scanf("%lf", &x);
scanf("%s", a);  // Never do this; it's UNSAFE!
scanf("%99s", a);  // Now it's safe, but ugly.
Most conversions skip leading white space ("%c" is an exception).
Type man 3 scanf for details.
Error in K&R2, p157: it says that white spaces in the format string are ignored, which is not true.
int printf(const char *format, ...)
        %d: int
        %u: unsigned int
        
        %ld: long
        %lu: unsigned long
        %s: string (char *)
        %f: double
        %g: double (trailing zeros not printed)
        %p: memory address (void *)
man 3 printf for even more.scanf() and printf() take variable number of arguments. Such functions
are called variadic functions, and their argument list ends with “…”
int sscanf(const char *input_string, const char *format, ...)
input_string rather than stdinint sprintf(char *output_buffer, const char *format, ...)
output_buffer rather than stdoutoutput_buffer better be pointing to a large enough memory bufferint snprintf(char *output_buffer, size_t size, const char *format, ...)
sprintf()EOF
A special value indicating end-of-file, usually #defined to be -1.
getchar(), and other similar functions, returns an int rather than an
unsigned char, so that it can return EOF.
FILE *fopen(const char *filename, const char *mode)
Opens a file, and returns a FILE * that you can pass to other file-related
functions to tell them on which file they should operate. FILE * is an
example of an “opaque handle”.
mode:
    NULL if file could not be opened for some reasonchar *fgets(char *buffer, int size, FILE *file)
reads at most size - 1 characters into buffer, stopping if newline is
read (the newline is included in the characters read), and terminating the
buffer with '\0'
returns NULL on EOF or error (you can call ferror() afterwards to find
out if there was an error).
Never use the similar gets() function; it’s UNSAFE!
int fputs(const char *str, FILE *file)
writes str to file.
returns EOF on error.
int fscanf(FILE *file, const char *format, ...)
int fprintf(FILE *file, const char *format, ...)
scanf() & printf()fclose(FILE *file)
stdin, stdout, stderr
These are all FILE * objects that have been pre-opened for you.
printf(...) is the same as fprintf(stdout, ...)
Example:
/*
  * ncat <file_name>
  *
  *   - reads a file line-by-line, 
  *     printing them out with line numbers
  */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "%s\n", "usage: ncat <file_name>");
        exit(1);
    }
    char *filename = argv[1];
    FILE *fp = fopen(filename, "r");
    if (fp == NULL) {
        perror(filename);
        exit(1);
    }
    char buf[100];
    int lineno = 1;
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        printf("%4d ", lineno++);
        if (fputs(buf, stdout) == EOF) {
            perror("can't write to stdout");
            exit(1);
        }
    }
    if (ferror(fp)) {
        perror(filename);
        exit(1);
    }
    fclose(fp);
    return 0;
}
Three types of buffering:
stderrstdout when it’s connected to a terminal screenfflush(fp) manually flushes the buffer for fp (which is a FILE *).
setbuf(fp, NULL) turns off buffering for fp.
Add 'b' to mode parameter in fopen():
FILE *fp = fopen(filename, "rb");
FILE *fp = fopen(filename, "wb");
...
In UNIX, there is no distinction between text and binary files, so 'b' has
no effect.
In Windows, 'b' suppresses newline translation that it normally performs
for text files:
"\r\n" into "\n""\n" into "\r\n"int fseek(FILE *file, long offset, int whence)
Sets the file position for next read or write. The new position, measured in
bytes, is obtained by adding offset bytes to the position specified by
whence. If whence is set toSEEK_SET, SEEK_CUR, or SEEK_END, the
offset is relative to the start of the file, the current position
indicator, or end-of-file, respectively.
returns 0 on success, non-zero on error
size_t fread(void *p, size_t size, size_t n, FILE *file)
reads n objects, each size bytes long, from file into the memory
location pointed to by p.
returns the number of objects successfully read, which may be less
than the requested number n, in which case feof() and ferror() can
be used to determine status.
size_t fwrite(const void *p, size_t size, size_t n, FILE *file)
writes n objects, each size bytes long, from the memory location
pointed to by p out to file.
returns the number of objects successfully written, which will be
less than n when there is an error.