Friday, September 16, 2016 Lab Notes Topics for today Redirection of input and output Command line arguments More pre-processor options Programs: Finish Program 1, begin Program 2 due next week 1. Redirection of input and output A C program has three built-in file streams: stdin, stderr and stdout. When you use scanf you are reading from stdin. When you use printf you are writing to stdout. You can write to stderr by using fprintf(stderr,.. When running programs in a Unix environment, a simple way to read data from a file into a program and to save results and/or error messages to a file without making any changes to the program source code is to use the Unix shell redirection. The following table shows how you can redirect the three streams when calling a.out. Command Stdin Stdout Stderr a.out Keyboard Screen Screen a.out < Datafile Datafile Screen Screen a.out > Results Keyboard Results Screen a.out < Datafile > Results Datafile Results Screen a.out >& Allout Keyboard Allout Allout a.out < Datafile >& Allout Datafile Allout Allout (a.out > Results) >& Errors Keyboard Results Errors (a.out < Datafile > Results) >& Errors Datafile Results Errors Comp 162 Lab Notes Page 1 of 5 September 16, 2016
Example: stdin, stdout, stderr psmith@redwood:~/comp162$ cat averages.c #include <stdio.h> // reads N followed by N integers. Outputs average. int main() int i, count, number, sum=0; scanf("%d",&count); if (count==0) fprintf(stderr,"error: Count is zero\n"); return; for (i=0; i<count; i++) scanf("%d",&number); sum+=number; printf("average of %d numbers is %5.3f\n",count,(float)sum/(float)count); psmith@redwood:~/comp162$ cat gooddata 7 34 21 12 55 90 2 83 psmith@redwood:~/comp162$ cat baddata 0 psmith@redwood:~/comp162$ gcc averages.c psmith@redwood:~/comp162$ (./a.out < gooddata > goodresults ) >& errorlist psmith@redwood:~/comp162$ cat goodresults Average of 7 numbers is 42.429 psmith@redwood:~/comp162$ cat errorlist psmith@redwood:~/comp162$ (./a.out < baddata > badresults ) >& errorlist psmith@redwood:~/comp162$ cat badresults psmith@redwood:~/comp162$ cat errorlist Error: Count is zero psmith@redwood:~/comp162$ exit Comp 162 Lab Notes Page 2 of 5 September 16, 2016
2. Command line arguments In general, the main function can have the following heading main(int argc, char *argv[]) or main(int argc, char **argv) When the program runs, the operating system: puts into argc (argument count) the number of tokens on the command line. This count includes the program name itself. Puts into the elements of array argv (argument vector) pointers to the texts of the tokens. Here is a simple program; it just echoes the components of the command line back to the standard output. Example #include <stdio.h> int main (int argc, char* argv[]) int i; printf("argc is: %d\n", argc); for (i=0; i<argc; i++) printf("argv [%d] is %s\n",i,argv[i]); Here is the compilation and a run of the program. hp9k2 22: gcc ctesta.c hp9k2 23: a.out one two three argc is: 4 argv [0] is a.out argv [1] is one argv [2] is two argv [3] is three Comp 162 Lab Notes Page 3 of 5 September 16, 2016
3. More pre-processor options The pre-processor runs before the compiler and processes lines beginning with #. Thus, it handles the #include lines. We can use #define to define symbols as in #define MAXMEM 4096 #define PI 3.14159 The pre-processor replaces instance of the symbol name by the corresponding number. For example, we could declare int memory[maxmem]. Also we can define symbols to control debugging as in the following example. #define DEBUG 1 main() int a[] = 2, 4, 3, -1, 7 ; int i,sum=0; for (i=0; i<5; i++) sum += a[i]; #ifdef DEBUG printf ("sum is now %d\n",sum); #endif printf("sum is %d\n", sum); The text between #ifdef and #endif is only included in the output from the preprocessor (and hence input to the compiler) if the symbol DEBUG is defined (ifdef) with a non-zero value. There is also #ifndef (if not defined) hp9k2 22: gcc ctestb.c hp9k2 23: a.out sum is now 2 sum is now 6 sum is now 9 sum is now 8 sum is now 15 sum is 15 To remove the debugging information from the input to the compiler we need only change the value of the symbol to 0 (or to omit its definition altogether) thus Comp 162 Lab Notes Page 4 of 5 September 16, 2016
#define DEBUG 0 main() int a[] = 2, 4, 3, -1, 7 ; int i,sum=0; for (i=0; i<5; i++) sum += a[i]; #ifdef DEBUG printf ("sum is now %d\n",sum); #endif printf("sum is %d\n", sum); Now when the program is compiled the debug statements are omitted hp9k2 26: gcc ctestb.c hp9k2 27: a.out sum is 15 You can probably see how debugging can also be controlled through command-line arguments. 4 Programs Program 1 is due today. Submit source code and testing results electronically. For program 2, breaking the solution into functions will help in development and testing. You can start with a placeholder for date-checking function isvalid int isvalid (int day, int month, int year) return 1; Then fill this out for extra credit if you have time. Consider creating a file with a test sequence then use redirection as described in section 1 above. Comp 162 Lab Notes Page 5 of 5 September 16, 2016