Data structures in the C language. examples of using

Lecture



Structures ("records") are aggregates of disparate data (fields of different types); unlike arrays, where all elements are of the same type.

  struct {
             int x , y ;  / * two integer fields * /
             char s [10];  / * and one for the string * /
     } s1 ;
A structural type may have a name:
  struct XYS {
             int x , y ;  / * two integer fields * /
             char str [10];  / * and one for the string * /
     };
Here we declared the type, but did not take any variable of this type (although we could). Now we will describe a variable of this type and a pointer to it:
  struct XYS s2 , * sptr = & s2 ;
Access to the fields of the structure is made by the field name (and not by the index, as in arrays):
The name is a _ structured variable . field name _
pointer _ to _ structure -> field name _

i.e

  not a
     #define WT 0 struct {int weight , height ;  } x ;
     #define GROWTH 1 x .  height = 175;
     int x [2];  x [GROWTH] = 175;
for example
  s1 .  x = 13;
     strcpy ( s2 . str , "Finish");
     sptr -> y = 27;
A structure may contain other types of structures as fields:
  struct XYS_Z {
             struct XYS xys ;
             int z ;
     } a1 ;
     a1 .  xys .  x = 71;  a1 .  z = 12;

A structure of the same type cannot be contained as a field — recursive definitions are prohibited. But fields are often used - references to structures of the same type (or other). This allows you to organize lists of structures:

  struct node {
             int value ;
             struct node * next ;
     };
Arrays of structures are often used:
  struct XYS array [20];  int i = 5, j;
     array [ i ].  x = 12;
     j = array [ i ].  x ;
Static structures can be described with initialization by listing the values ​​of their fields in {}, separated by commas:
  extern struct node n2 ;
     struct node n1 = {1, & n2 },
                 n2 = {2, & n1 },
                 n3 = {3, NULL};

In this example, n2 is described in advance so that & n2 in the initialization string n1 is defined.

Structures of the same type can be assigned entirely (which corresponds to the assignment of each of the fields):

  struct XYS s1 , s2 ;  ...
     s2 = s1 ;
Unlike arrays, which can not be assigned entirely:
  int a [5], b [5];  a = b ;  / * ERROR!  * /
Example of referring to structure fields:
  typedef struct _Point {
         short x, y;  / * point coordinates * /
         char * s;  / * point mark * /
     } Point;
     Point p;  Point * pptr;  short * iptr;
     struct _Curve {
       Point points [25];  / * broken vertex * /
       int color;  / * line color * /
     } aLine [10], * linePtr = & aLine [0];
             ...
     pptr = & p;  / * pointer to p structure * /
     px = 1;  py = 2;  ps = "Grue";
     linePtr-> points [2] .x = 54;  aLine [5] .points [0] .y = 17;
  Expanded value
     --------- + ------------ + ------------ + ----------- + - --------
     px |  pptr-> x |  (* pptr) .x |  (& p) -> x |  one
     --------- + ------------ + ------------ + ----------- + - --------
                                      & p-> x |  mistake
     ----------- + ---------------- + ------------------ + - --------
     iptr = & p.x |  iptr = & pptr-> x |  iptr = & (pptr-> x) |  field address
     ----------- + ---------------- + -------- + --------- + - --------
     * pptr-> s |  * (pptr-> s) |  * ps |  ps [0] |  'G'
     ----------- + ---------------- + -------- + --------- + - --------
     pptr-> s [1] |  (& p) -> s [1] |  ps [1] |  'r'
     ----------- + ---------------- + ------------------ + - --------
              & p-> s [1] |  mistake
     ----------- + ---------------- + ------------------ + - --------
     (* pptr) .s |  pptr-> s |  ps |  "Grue"
     ----------- + ---------------- + ------------------ + - --------
     * pptr.s |  mistake
     ----------------------------------------------- + - --------
  Generally (& p) -> field = p.field
                    pptr-> field = (* pptr) .field

Joins are aggregates of data that can store data values ​​of different types in the same place .

  struct a {int x , y ;  char * s ;  } A ;
             union b {int i ;  char * s ;  struct a aa ;  } B ;
  Structure:
        ________________________
     A: |  Ax int |  Three fields
        ------------------------ located in a row.
        |  Ay int |  It turns out as if
        ------------------------ "card" with graphs.
        |  As char * |
        -----------------------
     And the field combinations are located "in parallel",
     in one place in memory.
        _______________________________________________________
     B: |  Bi int |  Bs char * |  B.aa: B.aa.x int |
        ----------- |  |  struct a: B.aa.y int |
                   --------------- |  : B.aa.s char * |
                                  | ___________________________ |

It is like a "box" in which you can put the value of any type of the above, but not ALL TOGETHER ("both this and that", as with structures), but by QUEUE ("or / or"). Its size is large enough to accommodate the largest of the listed data types.

We can put a value in the union and interpret it as a different data type that is sometimes used in machine-dependent programs. Here is an example that ascertains the byte order in short numbers:

  union lb {
             char s [2];  short i ;
      } x ;
      unsigned hi , lo ;
      x .  i = (02 << 8) |  01;
      hi = x .  s [1];  lo = x .  s [0];
      printf ("% d% d \ n", hi , lo );
or so:
  #include <stdio.h>
     union {
             int i ;
             unsigned char s [sizeof (int)];
     } u;
     void main () {
             unsigned char * p;
             int n;
             u.  i = 0x12345678;
             for (n = 0, p = u. s ; n <sizeof (int); n ++, p ++) {
                     printf ("% 02X", * p);
             }
             putchar ('\ n');
     }
or the word order in long numbers:
  union xx {
       long l ;
       struct ab {
         short a ;  / * low word * /
         short b ;  / * high word * /
       } ab ;
     } c ;
     main () {/ * on the IBM PC 80386 type 00020001 * /
       c .  ab .  a = 1;  c .  ab .  b = 2;  printf ("% 08lx \ n", c . l );
     }

5.1.

Find errors in the description of the structural template:
  structure {int arr [12],
                         char string,
                         int * sum
                       }

5.2.

Develop a structural template that would contain the name of the month, a three-letter abbreviation of the month, the number of days in the month and the number of the month. Initialize it for a non-leap year.

  struct month {
              char name [10];  / * or char * name;  * /
              char abbrev [4];  / * or char * abbrev;  * /
              int days;
              int num;
       };
       struct month months [12] = {/ * index * /
              {"January", "Jan", 31, 1}, / * 0 * /
              {"February", "Feb", 28, 2}, / * 1 * /
                     ...
              {"December", "Dec", 31, 12}, / * 11 * /
       }, * mptr = & months [0];  / * or * mptr = months * /
       main () {
             struct month * mptr;
             printf ("% s \ n", mptr [1] .name);
             printf ("% s% d \ n", mptr-> name, mptr-> num);
       }

Write a function that saves the months array to a file; a function that reads it from a file. Use fprintf and fscanf .

What is the difference in the reading function when the name field is described as char name [10] and as char * name ?

Answer: in the second case, to save the read string, you must order the memory dynamically with the help of malloc () and save the string in it with the help of strcpy (), since memory for storing the string itself in the structure is not reserved (but only for a pointer to it).

Find the error in the operators of the function main (). Why is printed not "February", but some kind of garbage? Note: where does the mptr pointer, described in main (), point to? Answer: in "it is not known where" is a local variable (and not receiving the initial value - it contains garbage), and not the same thing as the mptr pointer described above! Remove the mptr description from main .

Note that to print all or several fields of a structure, you should EXACTLY enumerate in printf () all the necessary fields and specify the formats corresponding to the types of these fields. There is no format or standard function that allows you to print all the fields at once (however, such a function can be written by you for a specific type of structure). Also, there is no format for scanf () that would introduce the entire structure. You can enter only in parts - each field separately.

5.3.

Write a program that returns the total number of days of the year up to this month by month number.

5.4.

Redo the previous program so that it returns the total number of days of the year up to this month using the name of the month written in letters. In the program, use the strcmp () function.

5.5.

Redo the previous program so that it requests the user day, month, year and gives the total number of days in the year up to that day. Month can be indicated by the number, name of the month or its abbreviation.

5.6.

Create a structure for the employee's account file, which would contain the following information: surname, name, patronymic; year of birth; home address; Place of work, position; salary; date of receipt for work.

5.7.

What does the program print?
  struct man {
             char name [20];
             int salary;
     } workers [] = {
             {"Ivanov", 200},
             {"Petrov", 180},
             {"Sidorov", 150}
     }, * wptr, chief = {"chief", 550};
     main () {
        struct man * ptr, * cptr, save;
        ptr = wptr = workers + 1;
        cptr = & chief;
        save = workers [2];  workers [2] = * wptr;  * wptr = save;
        wptr ++;  ptr--;  ptr-> salary = save.salary;
        printf ("% c% s% s% s% s \ n% d% d% d% d \ n% d% d% c \ n",
          * workers [1] .name, workers [2] .name, cptr-> name,
            ptr [1] .name, save.name,
              wptr-> salary, chief.salary,
                (* ptr). salary, workers-> salary,
          wptr - ptr, wptr - workers, * ptr-> name);
     }
Answer:
  S Petrov Head Sidorov Sidorov
     180 550 150 150
     2 2 and

5.8.

Disassemble the following example:
  #include <stdio.h>
     struct man {
             char * name, town [4];  int salary;
             int addr [2];
     } men [] = {
             {"Vasya", "Msc", 100, {12, 7}},
             {"Grisha", "Len", 120, {6, 51}},
             {"Peter", "Rig", 140, {23, 84}},
             {NULL, "", -1, {-1, -1}}
     };
     main () {
        struct man * ptr, ** ptrptr;
        int i;
        ptrptr = & ptr;
        * ptrptr = & men [1];  / * men + 1 * /
        printf ("% s% d% s% d% c \ n",
                 ptr-> name,
                       ptr-> salary,
                             ptr-> town,
                                  ptr-> addr [1],
                                       ptr [1] .town [2]);
        (* ptrptr) ++;
        / * copy * ptr to men [0] * /
        men [0] .name = ptr-> name;  / * (char *) # 1 * /
        strcpy (men [0] .town, ptr-> town);  / * char [] # 2 * /
        men [0]. salary = ptr-> salary;  / * int # 3 * /
        for (i = 0; i <2; i ++)
            men [0]. addr [i] = ptr-> addr [i];  / * array # 4 * /
        / * print the array of structures * /
        for (ptr = men; ptr-> name; ptr ++)
            printf ("% s% s% d \ n",
                     ptr-> name, ptr-> town, ptr-> addr [0]);
     }
Pay attention to such moments:
  1. How to work with a pointer to a pointer ( ptrptr ).
  2. When copying structures with separate fields, the fields of scalar types (int, char, long, ..., pointers) are copied by an assignment operation (see the lines marked # 1 and # 3). Fields of vector types (arrays) are copied using a loop that sends an array elementwise (line # 4). Strings (arrays of letters) are sent by the standard strcpy function (line # 2). All this applies not only to the fields of structures, but also to variables of such types. Structures can also be copied not by fields, but entirely: men [0] = * ptr ;
  3. Writing the arguments to the printf () function with a ladder allows you to see better which format each argument matches.
  4. When printing an array of structures, we print not a definite number of them (equal to the size of the array), but use the NULL pointer in the name field of the last structure as a sign of the end of the array.
  5. In the town field, we store strings of 3 letters, but select an array of 4 bytes for storage. This is necessary because the string "Msc" consists not of 3x, but of 4x bytes: 'M', 's', 'c', '\ 0'.

When working with structures and pointers, drawings can be a great help. Here's how (for example) you can draw the data from this example (the men array is not all shown):

  --ptr-- --ptrptr- ptr |  * | <------ | --- * |
             --- | --- --------- |
               / ========= men [0] ==
              / men: | name |  * --- | -----> "Vasya"
              |  | --------------- |
              |  | town | M | s | c | \ 0 |
              |  | --------------- |
              |  | salary |  100 |
              |  | --------------- |
              |  | addr |  12 |  7 |
              \ ---------------- \ ========= men [1] ==
                \ -> | name |  * --- | -----> "Grisha"
                       ............

5.9.

Make a program "reference to the periodic table", which by the name of the chemical element would give its characteristics. Initialize the table with an array of structures.


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Algorithmization and programming. Structural programming. C language

Terms: Algorithmization and programming. Structural programming. C language