Differences between revisions 10 and 12 (spanning 2 versions)
Revision 10 as of 2019-06-12 13:05:26
Size: 5749
Comment:
Revision 12 as of 2019-06-12 13:16:49
Size: 6030
Comment:
Deletions are marked like this. Additions are marked like this.
Line 136: Line 136:
 ==== User prompting ====
 Using ''stdin'' usually means you do not have a user prompt.
Line 174: Line 176:
The following does the same thing: If you create a data file ''input.txt'' that contains the string ''10'', then the following will generate the same output text file.
Line 179: Line 181:
This also does the same thing: As we saw before, you can let ''echo'' generate data and use that in a pipe. This also generates the same output text file.

C I/O

Program input

There are 3 main sources of input for programs:

  1. from the command line
    • you get access to data on the command line by using argc and argv[][]

  2. from standard input (also called stdin)

    • stdin can be the keyboard, a data file, or the output of another program

  3. from an 'internally-defined' file
    • open a file, use fscanf(), and don't forget to close the file

1. command line

To read from the command line:

  • include argc and argv in your parameter list for main().

  • use sscanf() to read the arguments (it stands for 'string scanf()')

    • the first argument of a sscanf() is a string

Here is a program that counts from 1 to num, where num is provided by the user on the command line

   1 // countc.c
   2 // reads an integer from the command line and counts
   3 #include <stdio.h>
   4 #include <stdlib.h>
   5 
   6 int main(int argc, char *argv[]) {
   7    int num = 0;
   8    if (argc < 2 || sscanf(argv[1], "%d", &num) != 1) { // num is defined here
   9       fprintf(stderr,"Usage: %s integer\n", argv[0]);
  10       return EXIT_FAILURE;
  11    }
  12    for (int i=1; i<=num; i++) {
  13       printf("%d ", i);
  14    }
  15    printf("\n");
  16    return EXIT_SUCCESS;
  17 }

Notice the program prints a 'Usage' message if an integer argument is missing (discussed in next session)

To execute the program:

prompt$ dcc -o countc countc.c

prompt$ ./count
Usage: ./countc integer

prompt$ ./countc !t#q
Usage: ./countc integer

prompt$ ./countc 10
1 2 3 4 5 6 7 8 9 10

2. standard input

To read from standard input (usually called simply stdin)

  • a scanf() is used (instead of sscanf())

    • a scanf() misses the string argument of a sscanf()

  • so where does num comes from?

    • ... the default 'channel' stdin

   1 //counts.c
   2 // reads an integer from stdin and counts
   3 #include <stdio.h>
   4 #include <stdlib.h>
   5 
   6 int main(void) {
   7    int num;
   8    if (scanf("%d", &num) != 1) {
   9       fprintf(stderr, "Usage: a number expected\n");
  10       return EXIT_FAILURE;
  11    }
  12    // the rest of the program is exactly the same as the command-line version
  13    for (int i=1; i<=num; i++) {
  14       printf("%d ",i);
  15    }
  16    printf("\n");
  17    return EXIT_SUCCESS;
  18 }

Notice the Usage message this time is simpler than the command-line version above

  • ... because we did not declare argc and argv, and so cannot use argv[0] this time!!

    • we could have if we wanted to of course

There are many ways to 'test' a program that reads stdin.

  1. Using the keyboard
     prompt$ dcc -o counts counts.c
     prompt$ ./counts
     10
     1 2 3 4 5 6 7 8 9 10

    where the integer 10 was typed on the keyboard by the user, and the program generates the count from 1 to 10.

  2. Using a data file, input.txt say, which contains the integer 10 (followed by a newline).

     prompt$ more input.txt
     10
    
     prompt$ ./counts < input.txt
     1 2 3 4 5 6 7 8 9 10
  3. Using a pipe command. A pipe command joins the stdout of a program to the stdin of another program. If we have a program called write10.c:

       1  // write10.c
       2  // just print the string 10
       3  #include <stdio.h>
       4  #include <stdlib.h>
       5 
       6  int main(void) {
       7     printf("10\n");
       8     return EXIT_SUCCESS;
       9  }
    

    then we can pipe its stdout to the stdin of our counting program

     prompt$ dcc -o write10 write10.c
     prompt$ dcc -o counts counts.c
     prompt$ ./write10 | ./counts
     1 2 3 4 5 6 7 8 9 10

    But you can actually generate a string much more easily in UNIX using echo

     prompt$ echo "10" | ./counts
     1 2 3 4 5 6 7 8 9 10
    ==== User prompting ====

    Using stdin usually means you do not have a user prompt.

3. A file

A program can open and close, and read from, and write to, a file that is 'internally' defined.

This is generally done when you have large volumes of stored data, or complex data or non-printable data.

  • these rarely happen in this course

Program output

There are two standard output 'channels', standard output stdout and standard error stderr.

  • both are normally defined as the screen

printf() writes to stdout, hence the screen

fprintf(), which stands for file-printf, writes to a file, which could be stderr

  • for example, in countc.c the 'Usage' message went to stderr:

       1  fprintf(stderr,"Usage: %s integer\n", argv[0]);
    
    • you could argue over whether it should go to stderr (maybe just a printf would have been enough)

    • stderr is normally reserved for serious errors

There is convention here:

  • standard input is scanf(),

    • from a string is sscanf(), and it has an 'extra' first argument that is a string

  • standard output is printf(),

    • to a file is fprintf(), and it has an 'extra' first argument that is a 'channel' (file)

Like stdin, we can re-direct stdout to a file. For example:

dcc -o counts counts.c
./counts > output.txt
10

(where the integer 10 is input by the user) will result in the count from 1 to 10 going to the file output.txt

If you create a data file input.txt that contains the string 10, then the following will generate the same output text file.

./counts < input.txt > output.txt

As we saw before, you can let echo generate data and use that in a pipe. This also generates the same output text file.

echo "10" | ./counts > output.txt

Input/output design considerations

The vast majority of program can be written just using these i/o system calls

  • - scanf() to read from stdin - sscanf() to read from the command line - printf() to write to stdout - fprintf() to write to stderr

Lec01IO (last edited 2019-06-17 17:54:09 by AlbertNymeyer)