Problems 5
  1. Theory
    1. What is EOF in the context of fscanf? Hints:
      man scanf | grep -A 1 EOF
      
      and wikipedia article end of file.
    2. What is the meaning of the following makefile variables CC, CFLAGS, CXXFLAGS, CPPFLAGS, LDFLAGS, LDLIBS.
    3. What will the following makefile print (after running command make)
      CFLAGS = -Wall -Ofast -std=c1x
      C = F
      all:
      	echo CFLAGS
      	echo $CFLAGS
      	echo $(C)FLAGS
      	echo $(CFLAGS)
      
    4. Suppose you have your whole C-program in one file main.c. Which of the following makefiles will compile and link the program into the executable file main?
      1. all: main
        
      2. main: main.c
        
      3. main: main.o
        
      4. all: main
        main: main.o
        main.o: main.c
        
      5. all: main
        main.o: main.c
        main: main.o
        
      6. main.o: main.c
        all: main
        main: main.o
        
      7. main: main.c
        	cc main.c -o main
        
      8. main: main.c
        	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
        
      9. all: main
        main: main.o
        	cc main.o -o main
        main.o: main.c
        	cc -c main.c -o main.o
        
      Remember that the tabulator-sign before the command may not be copy-pasted correctly.
    5. Suppose your main function, contained in the file main.c, calls the functions foo and bar which are contained correspondingly in the files foo.c and bar.c. Which of the following makefiles will correctly compile and link your program into the executable file main after the command make?
      1. main: main.o foo.o bar.o
        
      2. main: foo.o main.o bar.o
        
      3. main: foo.o main.o bar.o
        	cc foo.o main.o bar.o -o main
        
      4. main: main.o foo.o bar.o
        	$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
        
      5. main: main.o foo.o bar.o
        main.o: main.c
        foo.o: foo.c
        	cc -c $^ -o $@
        bar.o: bar.c
        
      6. main: main.o foo.o bar.o
        	cc main.o foo.o bar.o -lm -o main
        main.o: main.c
        	cc -c main.c
        foo.o: foo.c
        	cc -c foo.c
        bar.o: bar.c
        	cc -c bar.c
        
      7. obj = main.o foo.o bar.o
        main: $(obj)
        
      8. Suppose there is the following preprocessor directive at the beginning of the file,
        #define PI 3.1415927
        
        what is the effect of it?
        1. The compiler creates a variable PI of type double and stores the value 3.1415927 in it.
        2. All occurences of the token 'PI' in the file are substituted with the token '3.1415927'.
  2. Practice. These exercises should be done using the make untility and makefile(s).
    1. Build a program that reads a set of numbers from the file input.dat and writes the cosines of these numbers to the file output.dat. Hint:
      double x;
      FILE* in = fopen("input.dat","r");
      if(in == NULL){ fprintf(stderr,"error: could not open file\n"); return -1;}
      FILE* out = fopen("output.dat","w");
      while( fscanf(in,"%lg",&x) != EOF ) fprintf(out,"%lg\n",cos(x));
      
      makefile ($@ stands for the name of the target):
      CFLAGS = -Wall -std=c99
      LDLIBS = -lm
      output.dat: prog5B1 input.dat ; ./prog5B1 ; cat $@    # 'cat' is used here to see the content of the target in the terminal
      input.dat: makefile ; echo '1.0 1.1 1.2' > input.dat
      clean: ; $(RM) input.dat output.dat prog5B1
      
    2. Do the same, but now using standard input, standard output and redirections. Hint:
      double x;
      while( fscanf(stdin,"%lg",&x) != EOF ) fprintf(stdout,"%lg\n",cos(x));
      
      or even shorter,
      double x;
      while( scanf("%lg\n",&x) != EOF ) printf("%lg\n",cos(x));
      
      In the makefile:
      out2.dat: prog5B2 input.dat; cat input.dat | ./prog5B2 > out2.dat
      
      or without using the input file,
      out2.dat: prog5B2 makefile ; echo '1.0 1.1 1.2' | ./prog5B2 > out2.dat
      
    3. Do the same, but now the input should be done via command-line-arguments. Hints:
      for(int i=1; i<argc; i++) printf("%lg\n",cos(atof(argv[i])));
      
      In the makefile (the automatic variable $@ stands for the name of the target of the rule):
      out3.dat: prog5B3 makefile ; ./prog5B3 1.0 1.1 1.2 > $@
      
    4. Similar to 3D vectors from Problems-3 and matrices from Problems-4 implement arbitrary-length vectors using the structure typedef struct {int size; double* data;} vector; with the following functions:
      vector* vector_alloc(int size);
      void vector_free(vector* v);
      void vector_set(vector* v, int i, double x); /* v_i=x */
      double vector_get(vector* v, int i); /* returns v_i */
      double* vector_get_ptr(vector* v, int i); /* returns pointer to v_i */
      void vector_set_all(vector* v, double x); /* for every i v_i=x */
      int vector_fprintf(FILE* stream, const char* format, vector* v);
      	/* prints the elements of v to the specified stream using the specified
      	format; returns 0 for success, -1 otherwise */
      int vector_fscanf(FILE* stream, const char* format, vector* v);
      	/* reads (*v).size elements form the stream into the vector v;
      	returns 0 for success, -1 otherwise */
      void vector_add(vector* v, vector* u);
      void vector_subtract(vector* v, vector* u);
      void vector_scale(vector* v, double a);
      int vector_equal(const vector* v, const vector* u);
      
      Use assert.h for range checking.