CS140 Lecture notes -- An example of using the val.v field to store a pointer to a struct

  • Jim Plank
  • Directory: /home/plank/cs140/Notes/Dllist-Ex
  • Lecture notes: http://www.cs.utk.edu/~plank/plank/classes/cs140/Notes/Dllist-Ex
  • Thu Sep 27 15:49:53 EDT 2007
    We're going to use a slightly contrived Dllist example. Suppose you are a fan of Rugby and want to watch some gamees that you can download on the Internet. The problem is that there are a lot of gamees to watch and you only have so much time, so you want to watch a good game. You have access to a file with results of gamees, but you don't want so simply read that file, because you don't want to spoil the game by knowing who wins or what the score was.

    So, you decide to write a program that will read the file and give you the information that you want without giving you the information that you don't want. The program will read the results file and put each game into a Dllist. Then, the user can repeatedly enter a minimum and maximum point differential on standard input, and the program will print out all games on the dllist whose point differential falls within that range.

    Here is an example of that running. We have a results file in Air-New-Zealand-2007.txt. Here are the first four lines:

    Week_1
    26_Jul	Manawatu_v_Waikato	PalmerstonN	7:05_pm	15-41
    27_Jul	Wellington_v_Otago	Wellington	7:35_pm	68-7
    27_Jul	Taranaki_v_Tasman	NPlymouth	7:35_pm	29-17
    

    The format of the file is that each game is represented by five words: Date, teams (Home"_v_"Away), the location, the time and the score.

    Here is an example of the program in use:

    UNIX> rug_score Air-New-Zealand-2007.txt
    Enter min and max point differential: 0 1
    Northland v North_Harbour on 28_Jul/2:35_pm at Whangarei
    Counties_Manukau v North_Harbour on 10_Aug/7:35_pm at Auckland
    Manawatu v Otago on 09_Sep/2:35_pm at PalmerstonN
    Enter min and max point differential: 50 100
    Wellington v Otago on 27_Jul/7:35_pm at Wellington
    Canterbury v Manawatu on 26_Aug/2:35_pm at Christchurch
    Enter min and max point differential: <CNTL-D>
    UNIX> grep 'Manawatu_v_Otago' Air-New-Zealand-2007.txt 
    09_Sep  Manawatu_v_Otago        PalmerstonN     2:35_pm 25-25
    UNIX> grep 'Canterbury_v_Manawatu' Air-New-Zealand-2007.txt 
    26_Aug  Canterbury_v_Manawatu   Christchurch    2:35_pm 64-10
    UNIX> 
    
    The source code is in rug_score.c, and below. I am not going to comment on it much. I include it as a typical example of using the val.v field of a dllist to hold a pointer to a struct. Pay attention to how the Game is appended to the dllist, and how it is re-extracted.

    Note also the following piece's of code when reading from the score file:


        ...
          if (sscanf(is->fields[0], "%d", &i) != 1 || i <= 0 || i > 31) {
            printf("%d: Date is wrong\n", is->line);
            exit(1);
          }   
        ....
    

    This converts the first number of the date to a number and checks to see if it is between 1 and 31.


        ...
          x = strchr(is->fields[0], '_');
          if (x == NULL || strlen(x) != 4) {
            printf("%d: Date is wrong\n", is->line);
            exit(1);
          }
          sprintf(s, " %s ", x+1);
          if (strstr(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ", s) == NULL) {
            printf("%d: Date is wrong\n", is->line);
            exit(1);
          }
        ....
    

    This makes sure that the date has an underscore in it, and that there are three characters after the underscore. Then it creates a string composed of a space, the three characters after the underscore, and another space. Then it searches for that string in the big string with month names separated by spaces. If it's there, then the three characters are a valid month. If not, it's not. It's a cute trick.


        ...
          x = strchr(is->fields[4], '-');
          if (x == NULL || x == is->fields[4]) {
            printf("%d: Scores are wrong\n", is->line);
            exit(1);
          }
          if (sscanf(is->fields[4], "%d", &hscore) == 0) {
            printf("%d: Scores are wrong\n", is->line);
            exit(1);
          }
          if (sscanf(x+1, "%d", &ascore) == 0) {
            printf("%d: Scores are wrong\n", is->line);
            exit(1);
          }
        ....
    

    This converts the last word, which should be a score in the form (homescore"-"awayscore), into the two variables hscore and ascores. It tests to make sure that there is a hyphen, and that the hyphen is not the first character of the string. Then it performs the conversion.


        ...
          x = strstr(is->fields[1], "_v_");
          g->away = strdup(x+3);
          *x = '\0';
          g->home = strdup(is->fields[1]);
        ....
    

    Finally, this code converts the team string into home and away team names, by finding the substring "_v_" and using it to delineate the end of the home team name and the beginning of the away team name.