L-43 MCS 275 Wed 25 Apr 2001

Answers to the Review Questions on Chapter 12 and 13

  1. Define a structure to hold a person's name and height in meters and centimeters. If Bob Smith is 1m 83cm tall, we store in the structure the string "Bob Smith", and the numbers 1 and 83.
    1. Give the C code to define the structure, and use typedef to name it height.
           typedef struct height HEIGHT;
           struct height
           {
              char *name;
              int  m;
              int  cm;
           };
      
    2. Give the instruction(s) to initialize the variable bobheight of type height with the data in the example above.
           bobheight = { "Bob Smith", 1 , 83 };
      or :
           bobheight.name = "Bob Smith";
           bobheight.m = 1;
           bobheight.cm = 83;
      
    3. Define a linked list HEIGHTS modifying the structure height and using typedef.
           typedef struct heights HEIGHTS;
           struct heights
           {
              char    *name;
              int     m;
              int     cm;
              HEIGHTS *tail;
           };
      
  2. Consider the definitions
       typedef struct point POINT;                   typedef struct list LIST;
       struct point                                  struct list
       {                                             {
          double x,y;                                   POINT  p;
          char   *label;                                LIST   *tail;
       };                                            };
    
    1. Write the C code to insert a point to the front of a given list, with prototype: LIST *insert ( LIST *l, POINT p ), where insert returns the pointer to the new list.
           LIST *insert ( LIST *l, POINT p )
           {
              LIST *newl;
      
              newl = (LIST*)calloc(1,sizeof(LIST));
              newl->p = p;
              newl->tail = l;
      
              return new;
           }
      
    2. Give prototype and implementation of a function to append a point to the end of a list. Write a small interactive program to illustrate how to use this append function.
           LIST *append ( LIST *first, LIST *last, POINT p )
           {
              LIST *newp;
      
              newp = (LIST*)calloc(1,sizeof(LIST));
              newp->p = p;
              newp->tail = NULL;
      
              if (first == NULL)
                 last = newp;
              else
              {
                 last->tail = newp;
                 last = newp;
              }
      
              return last;
           }
      
      The main program to illustrate this append :
           #include <stdio.h>
           int main()
           {
              LIST *first,*last;
              POINT p;
              int n;
      
              first = NULL;
              last = NULL;
              for (;;)
              {
                 p.label = (char*)calloc(80,sizeof(char));
                 printf("  Give a point and label : ");
                 n = scanf("%f%f%s", &p.x, &p.y, p.label);
                 if (n < 3)
                    break;
                 else
                 {
                    last = append(first,last,p);
                    if (first == NULL) first = last;
                 }
              }
           }
      
    3. The function LIST *insert ( LIST *first, LIST *second, POINT p ) takes as argument two pointers to consecutive elements in a list, i.e.: first->tail == second. The function inserts the point p between first and second and returns the new value for first->tail.
           LIST *insert ( LIST *first, *second, POINT p )
           {
              LIST *new2nd;
      
              new2nd = (LIST*)calloc(1,sizeof(LIST));
              new2nd.p = p;
              new2nd->tail = second;
              first->tail = new2nd;
      
              return new2nd;
           }
      
    4. Give the C code to count the number of points, using the prototype int Count ( LIST *l ). Write two separate versions, once recursively and iteratively.

      A recursive version :

           int Count ( LIST *l )
           {
              if (l == NULL)
                 return 0;
              else
                 return 1 + Count(l);
           }
      
      An iterative version :
           int Count ( LIST *l )
           {
              LIST *p;
              int cnt = 0;
      
              for (p = l; p != NULL; p = p->tail)
                 cnt++;
      
              return cnt;
           }
      
    5. The function POINT LeftMost ( LIST *l ) returns the point in the list l with the smallest x coordinate. Give the iterative and recursive implementation.

      An iterative implementation :

           POINT LeftMost ( LIST *l )
           {
              POINT min;
              LIST *ptr;
      
              min.x = 1.0E+99;
              for (ptr = l; ptr != NULL; ptr = ptr->tail)
                 if ((ptr->p).x < min.x)
                    min = ptr->p;
      
              return min;
           }
      
      A recursive implementation :
           POINT LeftMost ( LIST *l )
           {
              POINT min,mintail;
      
              min.x = 1.0E+99;
              if (l == NULL)
                 return min;
              else
              {
                 mintail = LeftMost(l->tail);
                 if ((l->p).x < mintail.x)
                    return l->p;
                 else
                    return mintail;
              }
           }
      
    6. Define the iterative and recursive version of void Print_Labels ( LIST *l ) that prints the labels of all points, all on separate lines.

      An iterative version :

           void Print_Labels ( LIST *l )
           {
              LIST *p;
      
              for (p = l; p != NULL; p = p->tail)
                 printf("%s\n", (p->p).label);
           }
      
      A recursive verson :
           void Print_Labels ( LIST *l )
           {
              if (l != NULL)
              {
                 printf("%s\n", (l->p).label);
                 Print_Labels(l->tail);
              }
           }
      
    7. The function char *Find_Label ( LIST *l, double x, double y ) returns the label of the point with coordinates x and y. In case the point does not occur in the list, the empty string must be returned. Give the iterative and recursive implementation.

      An iterative implementation :

           char *Find_Label ( LIST *l, double x, double y )
           {
              LIST *ptr;
              char *result;
      
              for (ptr = l; ptr != NULL; ptr = ptr->tail)
                 if ( ( (ptr->p).x == x ) && ( (ptr->p).y == y ) )
                    return (ptr->p).label;
      
              result = (char*)calloc(1,sizeof(char));
              result[0] = '\0';
              return result;
           }
      
      A recursive implementation :
           char *Find_Label ( LIST *l, double x, double y )
           {
              char *result;
      
              if (l == NULL)
              {
                 result = (char*)calloc(1,sizeof(char));
                 result[0] = '\0';
                 return result;
              }
              else
                 if ( ( (l->p).x == x ) && ( (l->p).y == y ) )
                    return (l->p).label;
                 else
                    return Find_Label(l->tail,x,y);
           }
      
    8. int Position ( LIST *l, POINT p ) returns the position of the point in the list. If the point does not occur in the list, then -1 is returned. Give the iterative and recursive implementation. You may have to change the prototype for the recursive version.

      An iterative version :

           int Position ( LIST *l; POINT p )
           {
              LIST *ptr;
              int pos = -1;
              int i = 0;
      
              for (ptr = l; ptr != NULL; ptr = ptr->tail)
              {
                 if (((ptr->p).x == p.x) && ((ptr->p).y == p.y)
                    && (strcmp((ptr->p).label,p.label)==0))
                    pos = i;
                 i++;
              }
              return pos;
           }
      
      The recursive version :
           int Position ( LIST *l; POINT p; int pos )
           {
              if (l == NULL)
                 return -1;
              else
                 if (((l->p).x == p.x) && ((l->p).y == p.y)
                    && (strcmp((l->p).label,p.label)==0))
                    return pos;
                 else
                    return Position(l->tail,p,pos+1);
           }
      
    9. To give a new label to a point with coordinates x and y, we can use the function int Relabel ( LIST *l, double x, double y, char *label ), which returns the position of the point in the list if it occurs, and -1 otherwise.
           int Relabel ( LIST *l, double x, double y, char *label )
           {
              LIST *ptr;
              int i = 0;
      
              for (ptr = l; ptr != NULL; ptr = ptr->tail)
              {
                 if ( (ptr->p).x == p.x) && ((ptr->p).y == p.y) )
                 {
                    (ptr->p).label = strcpy((ptr->p).label,p.label);
                    return i;
                 }
                 i++;
              }
              return -1;
           }
      
    10. The function LIST *delete ( LIST *first, LIST *second ) takes as argument two pointers to consecutive elements in a list, i.e.: first->tail == second. The function deletes the element pointed to by second and returns the new value for first->tail.
           LIST *delete ( LIST *first, LIST *second )
           {
              first->tail = second->tail;
              free(second);
              return first-> tail;
           }
      
    11. Give the implementation of void delete ( LIST *l ) that deallocates all memory occupied by the list.
           void delete ( LIST *l )
           {
              if (l != NULL)
              {
                 delete(l->tail);
                 free((l->p).label);
                 free(l);
              }
           }
      
  3. Write a program that can be called from the command line like prompt> create filename when the executable has the name "create". If there is not already a file with the name filename, then it will be created, otherwise the user must give permission to overwrite the existing file. If permitted (or if the file did not exist already), write your name in the file in a field of 30 characters wide, right adjusted.
         #include <stdio.h>
    
         int main ( int argc, char* argv[] )
         {
            FILE *myfile;
            char c = 'y';
    
            myfile = fopen(argv[1],"r");
            if (myfile != NULL)
            {
               printf("File %s exists already.  Overwrite ? (y/n) ", argv[1]);
               scanf("%c", &c);
               fclose(myfile);
            }
            if (c == 'y')
            {
               myfile = fopen(argv[1],"w");
               fprintf(myfile,"%30s","my name");
            }
    
            return 0;
         }
    
  4. For a name given in the format lastname, firstname (for example "Smith, Bob"), give ONE scanf command to read in the string name the following data
    1. the entire name;
    2. the last name only;
    3. the first name only.
      Suppose we work with string name :
         1. scanf("%[^\n]", name);
         2. scanf("%[^,]", name);
         3. scanf("%*[^,], %[^\n]", name);
    
  5. Suppose a file contains salaries in the format
             Smith, Bob                     34023.23
             Little, Ann                    56123.32
         
    where the names occupy a field of 30 characters wide and salaries are floats written with field width 8, precision 2. In the questions below you may assume the file has been appropriately opened for the necessary operations.
    1. The function void Salaries ( FILE *sal ) displays all salaries on screen. Give its implementation.
           void Salaries ( FILE *sal )
           {
              char name[31];
              float pay;
      
              while (fscanf(sal,"%30[^\n] %f\n", name, &pay) == 2)
                 printf("%-30s %8.2f\n", name, pay);
      
           }
      
    2. Define char *BestPaid ( FILE *sal ) that returns the name of the person with the highest salary.
           char *BestPaid (FILE *sal )
           {
              char name[31];
              float pay;
              float bestpay = 0.0;
              char *best;
      
              best = (char*)calloc(31,sizeof(char));
      
              while (fscanf(sal,"%30[^\n] %f\n", name, &pay) == 2)
              {
                 if (pay > bestpay)
                 {
                    best = strcpy(best,name);
                    bestpay = pay;
                 }
              }
      
              return best;
           }
      
    3. Define FILE *TopSal ( FILE *sal, char *name, float s ) that creates a new file with the given name name containing only those names and salaries of persons with a salary higher than s. The file pointer to this new file is returned.
           FILE *TopSal ( FILE *sal, char *name, float s )
           {
              char persname[31];
              float pay;
              FILE *topsals;
           
              topsals = fopen(name,"w");
       
              while (fscanf(sal,"%30[^\n] %f\n", persname, &pay) == 2)
              {
                 if (pay > s)
                    fprintf(topsals,"%-30s %8.2f\n", persname, pay);
              }
      
              return topsals;
           }
      
    4. The function void Split ( FILE *sal, float s ) splits the data in the file in two blocks: first it lists all names and salaries strictly less than s, followed by those larger than or equal to s. All data needs to be written to the original file where sal is pointing to.
           void Split ( FILE *sal, float s )
           {
              FILE *low,*upp;
              char name[31];
              float pay;
      
              low = tmpfile();
              upp = tmpfile();
      
              while (fscanf(sal,"%30[^\n] %f\n", name, &pay) == 2)
                 if (pay < s)
                    fprintf(low,"%-30s%8.2f\n", name, pay);
                 else
                    fprintf(upp,"%-30s%8.2f\n", name, pay);
      
              rewind(sal);
              rewind(low);
              rewind(upp);
              while (fscanf(low,"%30[^\n] %f\n", name, &pay) == 2)
                 fprintf(sal,"%-30s%8.2f\n", name, pay);
              while (fscanf(upp,"%30[^\n] %f\n", name, &pay) == 2)
                 fprintf(sal,"%-30s%8.2f\n", name, pay);
           }
      
    5. With int Change ( FILE *sal, char *name, float newsal ) we change the salary of the person with given name to newsal. If name does not occur in the file, then -1 is returned, otherwise 0 is returned.
           int Change ( FILE *sal, char *name, float newsal )
           {
              char persname[31];
              float pay;
           
              while (fscanf(sal,"%30[^\n] %f", persname, &pay) == 2)
              {
                 if (strcmp(name,persname) == 0)
                 {
                    fseek(sal,-8,1);
                    fprintf(sal, "%8.2f", newsal);
                    return 0;
                 }
                 else
                    fscanf(sal,"\n");
              }
           
              return -1;
           }
      
    6. Write a function void PayRaise ( FILE *sal, float percent ) that raises the salaries in the given file with percent. You may assume the raise is never that high it exceeds the field width of 8 characters.
           void PayRaise ( FILE *sal, float percent )
           {
              char name[31];
              float pay;
           
              while (fscanf(sal,"%30[^\n] %f", name, &pay) == 2)
              {
                 pay = pay + percent*pay;
                 fseek(sal,-8,1);
                 fprintf(sal, "%8.2f", pay);
                 fscanf(sal,"\n");           /* skip new line */
              }
           }
      

FINAL EXAM in LC C3 on Monday 30 April 2001 at 1:00-3:00PM.