17.1 修改16.3节的程序inventory.c,使其可以对数组inventory进行动态内存分配,并且在以后填满时重新进行内存分配。初始使用malloc为拥有10个part结构的数组分配足够的内存空间。当数组没有足够的空间给新的零件时,使用realloc函数来使内存数量加倍。在每次数组变满时重复加倍操作步骤。
#include#include #include "readline.h" #define NAME_LEN 25 struct part { int number; char name[NAME_LEN+1]; int on_hand; } *inventory; int max_parts = 10; int num_parts = 0; int find_part(int number); void insert(void); void search(void); void update(void); void print(void); int main(void) { char code; if ((inventory = malloc(max_parts * sizeof(struct part))) == NULL) { printf("Error: malloc failedn"); exit(EXIT_FAILURE); } for (;;) { printf("Enter operation code: "); scanf(" %c", &code); while (getchar() != 'n') ; switch (code) { case 'i': insert(); break; case 's': search(); break; case 'u': update(); break; case 'p': print(); break; case 'q': return 0; default: printf("Illegal coden"); } printf("n"); } return 0; } int find_part(int number) { int i; for (i = 0; i < num_parts; i++) if (inventory[i].number == number) return i; return -1; } void insert(void) { int part_number; if (num_parts == max_parts) { if ((inventory = realloc(inventory, sizeof(struct part) * (max_parts *= 2))) == NULL) { printf("Error: realloc failedn"); exit(EXIT_FAILURE); } } printf("Enter part number: "); scanf("%d", &part_number); if (find_part(part_number) >= 0) { printf("Part already exists.n"); return; } inventory[num_parts].number = part_number; printf("Enter part name: "); read_line(inventory[num_parts].name, NAME_LEN); printf("Enter quantity on hand: "); scanf("%d", &inventory[num_parts].on_hand); num_parts++; } void search(void) { int i, number; printf("Enter part number: "); scanf("%d", &number); i = find_part(number); if (i >= 0) { printf("Part name: %sn", inventory[i].name); printf("Quantity on hand: %dn", inventory[i].on_hand); } else printf("Part not found.n"); } void update(void) { int i, number, change; printf("Enter part number: "); scanf("%d", &number); i = find_part(number); if (i >= 0) { printf("Enter change in quantity on hand: "); scanf("%d", &change); inventory[i].on_hand += change; } else printf("Part not found.n"); } void print(void) { int i; printf("Part Number Part Name " "Quantity on Handn"); for (i = 0; i < num_parts; i++) printf("%7d %-25s%11dn", inventory[i].number, inventory[i].name, inventory[i].on_hand); }
17.2 修改16.3节的程序inventory.c,使得p命令在显示零件前调用qsort对inventory数组排序。
inventory.c
#include#include #include "readline.h" #include "quicksort.h" #include "inventory.h" int max_parts = 10; int num_parts = 0; int find_part(int number); void insert(void); void search(void); void update(void); void print(void); int compare_parts(const void *p, const void *q); int main(void) { char code; if ((inventory = malloc(max_parts * sizeof(struct part))) == NULL) { printf("Error: malloc failedn"); exit(EXIT_FAILURE); } for (;;) { printf("Enter operation code: "); scanf(" %c", &code); while (getchar() != 'n') ; switch (code) { case 'i': insert(); break; case 's': search(); break; case 'u': update(); break; case 'p': print(); break; case 'q': return 0; default: printf("Illegal coden"); } printf("n"); } return 0; } int find_part(int number) { int i; for (i = 0; i < num_parts; i++) if (inventory[i].number == number) return i; return -1; } void insert(void) { int part_number; if (num_parts == max_parts) { if ((inventory = realloc(inventory, sizeof(struct part) * (max_parts *= 2))) == NULL) { printf("Error: realloc failedn"); exit(EXIT_FAILURE); } } printf("Enter part number: "); scanf("%d", &part_number); if (find_part(part_number) >= 0) { printf("Part already exists.n"); return; } inventory[num_parts].number = part_number; printf("Enter part name: "); read_line(inventory[num_parts].name, NAME_LEN); printf("Enter quantity on hand: "); scanf("%d", &inventory[num_parts].on_hand); num_parts++; } void search(void) { int i, number; printf("Enter part number: "); scanf("%d", &number); i = find_part(number); if (i >= 0) { printf("Part name: %sn", inventory[i].name); printf("Quantity on hand: %dn", inventory[i].on_hand); } else printf("Part not found.n"); } void update(void) { int i, number, change; printf("Enter part number: "); scanf("%d", &number); i = find_part(number); if (i >= 0) { printf("Enter change in quantity on hand: "); scanf("%d", &change); inventory[i].on_hand += change; } else printf("Part not found.n"); } void print(void) { int i; qsort(inventory, num_parts, sizeof(struct part), compare_parts); printf("Part Number Part Name " "Quantity on Handn"); for (i = 0; i < num_parts; i++) printf("%7d %-25s%11dn", inventory[i].number, inventory[i].name, inventory[i].on_hand); } int compare_parts(const void *p, const void *q) { return ((struct part *)p)->number - ((struct part *)q)->number; }
inventory.h
#ifndef INVENTORY_H #define INVENTORY_H #define NAME_LEN 25 struct part { int number; char name[NAME_LEN+1]; int on_hand; } *inventory; #endif
17.3 修改17.5节的程序inventory2.c,增加一个e命令(擦除)以允许用户从数据库中删除一个零件。#include#include #include "readline.h" #define NAME_LEN 25 struct part { int number; char name[NAME_LEN+1]; int on_hand; struct part *next; }; struct part *inventory = NULL; struct part *find_part(int number); void insert(void); void search(void); void update(void); void print(void); void erase(void); int main(void) { char code; for (;;) { printf("Enter operation code: "); scanf(" %c", &code); while (getchar() != 'n') ; switch (code) { case 'i': insert(); break; case 'e': erase(); break; case 's': search(); break; case 'u': update(); break; case 'p': print(); break; case 'q': return 0; default: printf("Illegal coden"); } printf("n"); } } struct part *find_part(int number) { struct part *p; for (p = inventory; p != NULL && number > p->number; p = p->next) ; if (p != NULL && number == p->number) return p; return NULL; } void insert(void) { struct part *cur, *prev, *new_node; new_node = malloc(sizeof(struct part)); if (new_node == NULL) { printf("Database is full; can't add more parts.n"); return; } printf("Enter part number: "); scanf("%d", &new_node->number); for (cur = inventory, prev = NULL; cur != NULL && new_node->number > cur->number; prev = cur, cur = cur->next) ; if (cur != NULL && new_node->number == cur->number) { printf("Part already exists.n"); free(new_node); return; } printf("Enter part name: "); read_line(new_node->name, NAME_LEN); printf("Enter quantity on hand: "); scanf("%d", &new_node->on_hand); new_node->next = cur; if (prev == NULL) inventory = new_node; else prev->next = new_node; } void erase(void) { struct part **pp = &inventory; struct part *temp; int n; printf("Enter part number: "); scanf("%d", &n); while(*pp) { if ((*pp)->number == n) { temp = *pp; *pp = (*pp)->next; free(temp); return; } pp = &(*pp)->next; } printf("Part number %d not found in databasen", n); return; } void search(void) { int number; struct part *p; printf("Enter part number: "); scanf("%d", &number); p = find_part(number); if (p != NULL) { printf("Part name: %sn", p->name); printf("Quantity on hand: %dn", p->on_hand); } else printf("Part not found.n"); } void update(void) { int number, change; struct part *p; printf("Enter part number: "); scanf("%d", &number); p = find_part(number); if (p != NULL) { printf("Enter change in quantity on hand: "); scanf("%d", &change); p->on_hand += change; } else printf("Part not found.n"); } void print(void) { struct part *p; printf("Part Number Part Name " "Quantity on Handn"); for (p = inventory; p != NULL; p = p->next) printf("%7d %-25s%11dn", p->number, p->name, p->on_hand); }
17.4 修改15.3节的程序justify,重新编写line.c文件使其存储链表中的当前行。链表中的每个结点存储一个单词。用一个指向包含第一个单词的结点的指针变量来替换原有的line数组,当行为空时该变量存储空指针。
justify.c
#include#include "line.h" #include "word.h" #define MAX_WORD_LEN 20 int main(void) { char word[MAX_WORD_LEN+2]; int word_len; clear_line(); for (;;) { read_word(word, MAX_WORD_LEN+1); word_len = strlen(word); if (word_len == 0) { flush_line(); return 0; } if (word_len > MAX_WORD_LEN) word[MAX_WORD_LEN] = '*'; if (word_len + 1 > space_remaining()) { write_line(); clear_line(); } add_word(word); } }
line.c
#include#include #include #include "line.h" #define MAX_LINE_LEN 60 int line_len = 0; int num_words = 0; struct node { struct node *next; char word[]; } *line = NULL; void clear_line(void) { struct node *temp; while (line != NULL) { temp = line; line = line->next; free(temp); } line_len = 0; num_words = 0; } void add_word(const char *word) { struct node *new_word, **pp = &line; if ((new_word = malloc(sizeof(struct node) + strlen(word) + 1)) == NULL) { printf("Error: malloc failedn"); exit(EXIT_FAILURE); } strcpy(new_word->word, word); new_word->next = NULL; while (*pp != NULL) pp = &(*pp)->next; *pp = new_word; line_len += strlen(word); if (num_words > 0) line_len++; num_words++; } int space_remaining(void) { return MAX_LINE_LEN - line_len; } void write_line(void) { int extra_spaces, spaces_to_insert, i; int char_count = 0; struct node *entry = line; extra_spaces = space_remaining(); while (char_count < line_len && entry != NULL) { printf("%s", entry->word); if (num_words > 1) { spaces_to_insert = extra_spaces / (num_words - 1); for (i = 1; i <= spaces_to_insert + 1; i++) putchar(' '); extra_spaces -= spaces_to_insert; } char_count += strlen(entry->word) + 1; num_words--; entry = entry->next; } putchar('n'); } void flush_line(void) { int i; struct node *entry = line; if (line_len > 0) { for (i = 0; entry != NULL; i++, entry = entry->next) { if (i > 0 && entry->next != NULL) putchar(' '); printf("%s ", entry->word); } } printf("n"); clear_line(); } line.h
#ifndef LINE_H #define LINE_H void clear_line(void); void add_word(const char *word); int space_remaining(void); void write_line(void); void flush_line(void); #endifword.c
#include#include "word.h" int read_char(void) { int ch = getchar(); if (ch == 'n' || ch == 't') return ' '; return ch; } void read_word(char *word, int len) { int ch, pos = 0; while ((ch = read_char()) == ' ') ; while (ch != ' ' && ch != EOF) { if (pos < len) word[pos++] = ch; ch = read_char(); } word[pos] = ' '; } word.h
#ifndef WORD_H #define WORD_H void read_word(char *word, int len); #endif
17.5 编写程序对用户输入的一系列单词排序:
Enter word: foo
Enter word: bar
Enter word: baz
Enter word: quux
Enter word:
In sorted order: bar baz foo quux
假设每个单词不超过20个字符。当用户输入空单词(即敲击回车键而没有录入任何单词)时停止读取。把每个单词存储在一个动态分配的字符串中,像remind2.c程序(17.2节)那样用一个指针数组来跟踪这些字符串。读完所有的单词后对数组排序(可以使用任何排序算法),然后用一个循环按存储顺序显示这些单词。提示:像remind2.c那样,使用read_line函数读取每个单词。
#include#include #include #define WORD_LEN 20 int compare_words(const void *w1, const void *w2); void *my_malloc(size_t bytes); int main(void) { char **words = NULL, *word = NULL; int i, size = 1, num_words = 0; words = (char **) my_malloc((size_t)sizeof(char *)); for (i = 0; ; i++) { word = (char *) my_malloc((size_t)WORD_LEN + 1); printf("Enter a word: "); fgets(word, WORD_LEN + 1, stdin); if (word[strlen(word) - 1] == 'n') word[strlen(word) - 1] = ' '; if (word[0] == ' ') break; *(words + i) = word; num_words++; if (size == num_words) { if ((words = (char **) realloc(words, (size_t)sizeof(char *) * (size *= 2))) == NULL) { printf("Error: realloc failedn"); exit(EXIT_FAILURE); } } } qsort(words, num_words, sizeof(char *), compare_words); printf("nIn sorted order: "); for (i = 0; i < num_words; i++) printf("%s ", *(words + i)); printf("n"); } void *my_malloc(size_t bytes) { void *p; if ((p = malloc(bytes)) == NULL) { printf("Error: malloc failedn"); exit(EXIT_FAILURE); } return p; } int compare_words(const void *w1, const void *w2) { return strcmp(*(char **)w1, *(char **)w2); }
17.6 修改编程题5,用qsort对指针数组排序。
#include#include #include #define WORD_LEN 20 int compare_words(const void *w1, const void *w2); void *my_malloc(size_t bytes); int main(void) { char **words = NULL, *word = NULL; int i, size = 1, num_words = 0; words = (char **) my_malloc((size_t)sizeof(char *)); for (i = 0; ; i++) { word = (char *) my_malloc((size_t)WORD_LEN + 1); printf("Enter a word: "); fgets(word, WORD_LEN + 1, stdin); if (word[strlen(word) - 1] == 'n') word[strlen(word) - 1] = ' '; if (word[0] == ' ') break; *(words + i) = word; num_words++; if (size == num_words) { if ((words = (char **) realloc(words, (size_t)sizeof(char *) * (size *= 2))) == NULL) { printf("Error: realloc failedn"); exit(EXIT_FAILURE); } } } qsort(words, num_words, sizeof(char *), compare_words); printf("nIn sorted order: "); for (i = 0; i < num_words; i++) printf("%s ", *(words + i)); printf("n"); } void *my_malloc(size_t bytes) { void *p; if ((p = malloc(bytes)) == NULL) { printf("Error: malloc failedn"); exit(EXIT_FAILURE); } return p; } int compare_words(const void *w1, const void *w2) { return strcmp(*(char **)w1, *(char **)w2); }
17.7 修改17.2节的remind2.c程序,使得reminders数组中的每个元素都是指向vstring结构(见17.9节)的指针,而不是指向普通字符串的指针。
#include#include #include #define MAX_REMIND 50 #define MSG_LEN 60 struct vstring { int len; char chars[]; }; int read_line(char str[], int n); int main(void) { struct vstring *reminders[MAX_REMIND]; char day_str[3], msg_str[MSG_LEN+1]; int day, i, j, num_remind = 0; for (;;) { if (num_remind == MAX_REMIND) { printf("-- No space left --n"); break; } printf("Enter day and reminder: "); scanf("%2d", &day); if (day == 0) break; sprintf(day_str, "%2d", day); read_line(msg_str, MSG_LEN); for (i = 0; i < num_remind; i++) if (strcmp(day_str, reminders[i]->chars) < 0) break; for (j = num_remind; j > i; j--) reminders[j] = reminders[j-1]; reminders[i] = malloc(sizeof(struct vstring) + 2 + strlen(msg_str) + 1); if (reminders[i] == NULL) { printf("-- No space left --n"); break; } strcpy(reminders[i]->chars, day_str); strcat(reminders[i]->chars, msg_str); reminders[i]->len = strlen(reminders[i]->chars); num_remind++; } printf("nDay Remindern"); for (i = 0; i < num_remind; i++) { for (j = 0; j < reminders[i]->len; j++) printf("%c", reminders[i]->chars[j]); printf("n"); } return 0; } int read_line(char str[], int n) { int ch, i = 0; while ((ch = getchar()) != 'n') if (i < n) str[i++] = ch; str[i] = ' '; return i; }



