230 likes | 345 Views
240-222 Computer Programming Techniques Semester 1, 1998. 11. Pointers and Structures. Objective of these slides: to discuss how pointers are used with structs. Overview. 1. A struct can contain Strings 2. Shuffling Cards 3. Pointers to structs 4. Updating a struct.
E N D
240-222 Computer Programming TechniquesSemester 1, 1998 11. Pointers and Structures Objective of these slides: to discuss how pointers are used with structs
Overview 1. A struct can contain Strings 2. Shuffling Cards 3. Pointers to structs 4. Updating a struct
1. A struct can Contain Strings struct card{ char *face; char *suit;}; :struct card a = {"Three", "Hearts"}; :printf("%s", a.suit); /* prints Hearts */
2. Shuffling Cards Sec. 10.7 #include <stdio.h>#include <stdlib.h>#include <time.h>struct card { char *face; char *suit;};typedef struct card Card;void filldeck(Card [], char *[], char *[]);void shuffle(Card []);void deal(Card []); continued
int main(){ Card deck[52]; char *face[] = {"Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine","Ten","Jack", "Queen", "King"}; char *suit[] = {"Hearts", "Diamonds", "Clubs", "Spades"}; srand(clock()); /* set random num */ filldeck(deck, face, suit); shuffle(deck); deal(deck); return 0;} continued
void filldeck(Card wdeck[], char *wface[], char *wsuit[])/* initialise the deck of cards */{ int i; for (i = 0; i <= 51; i++) { wdeck[i].face = wface[i % 13]; wdeck[i].suit = wsuit[i / 13]; }} continued
void shuffle(Card wdeck[])/* randomly rearrange the deck of cards */{ int i, j; Card temp; for (i = 0; i <= 51; i++) { j = rand() % 52; /* get rand num */ if (i != j) { temp = wdeck[i]; wdeck[i] = wdeck[j]; wdeck[j] = temp; } }} continued
void deal(Card wdeck[])/* display the deck */{ int i; for (i = 0; i <= 51; i++) printf("%5s of %-8s%c", wdeck[i].face, wdeck[i].suit, (i + 1) % 2 ? '\t' : '\n');}
Output (see fig. 10.4): Eight of Diamonds Ace of HeartsEight of Clubs Five of Spades : :
3. Pointers to Structs struct card a, *c;a = {"Four", "Spades"};c = &a; :printf("%s", c->suit); /* prints Spades */ c->suit is equivalent to (*c).suit
Example #include <stdio.h> /* fig 10.2 */struct card { char *face; char *suit;}; continued
int main(){ struct card a; struct card *aptr; a.face = "Ace"; a.suit = "Spades"; aptr = &a; printf("%s of %s\n%s of %s\n%s of%s\n", a.face, a.suit, aptr->face, aptr->suit, (*aptr).face, (*aptr).suit); return 0;}
Output: Ace of SpadesAce of SpadesAce of Spades
4. Updating a struct • Code fragment: struct card { char *face; char *suit;};int main(){ struct card a; a.face = “Three; printf(“%s”, a.face);}
Discussion • This code works, so what is the problem? • Answer: the scope of “Three” • at the end of main(), “Three” goes out of scope and is deleted • this does not matter for this example because the scope of main() is the entire program
A More Dangerous Example int main(){ struct card a; a = initialise(); printf(“%s”, a.face); : printf(“%s”, a.face);}struct card initialise(void){ struct card b; b.face = “Three”; return b;}
Discussion • The scope of “Three” is initialise(), and so will be deleted after initialise() returns • return copies out the b struct, including its two pointers • a is assigned the pointers, but what do they point at? • the deletion may not happen immediately, but depend on the memory usage of the rest of the program • the first printf() may work, sometimes!
First Solution struct card1( char face[10]; char suit[10];};int main(){ struct card1 a; a = initialise1(); : printf(“%s”, a.face);}struct card1 initialise1(void){ struct card1 b; strcpy(b.face, “Three”); return b;}
Discussion • The general solution is to make a copy of the string • “Three” is copied into the fixed size array b.face using strcpy() • that array is copied out as part of the b struct using return
Second Solution struct card( char *face; /* no fixed size */ char *suit;};int main(){ struct card a; a = initialise2(); : printf(“%s”, a.face);}struct card initialise2(void){ struct card b;b.face = (char *)malloc(6); strcpy(b.face, “Three”); return b;}
Discussion • The second solution still uses copying, but now calls malloc() to make dynamic memory • return only copies out the pointers inside b • but malloc’ed memory is not deleted even though the scope of b is initialise2() • so a.face will point to the malloc’ed memory from initialise2()
Third Solution struct card( char *face; /* no fixed size */ char *suit;};int main(){ struct card a; initialise3(&a); : printf(“%s”, a.face);}void initialise3(struct card *ap){ ap->face = (char *)malloc(6); strcpy(ap->face, “Three”); }
Discussion • The third solution uses malloc() to make dynamic memory, but for the a struct. • pass in a pointer to a, and alter a via the pointer (this is how C implements call-by-reference). • this is the most common coding style for manipulating structs inside functions