6-Week Practicum Solutions for Spring 2014
Table of Contents
1 Problem 1
BIG IDEA The isnumber program has a exit status of 0 if what it
read from stdin was a number, and an exit status of 1 if what it
read from stdin was not a number. This information is checked by
if, which only executes the then block if the exit status is 0.
#!/bin/bash for i in $@ do if echo $i | ./isnumber then echo $i fi done
2 Problem 2
BIG IDEA: When printing the list of words, there are nwords in the
list not size. The size is the size of the array, and if you
iterate up to size without checking for NULL, you will segafault
when you dereference NULL. To free each word, you must free the
string, which was duplicated, the word_t in each index of the list,
the list itself, and finally the wordlist.
#include <stdio.h> #include <stdlib.h> #include <string.h> /*********************************************************** * * Instructions: * - Complete the program below where the TODO's are * - Your program must not segfault or memory errors * **********************************************************/ ////////////////////////////////////////////////////////////////////////////// // DO *NOT* EDIT BELOW #define INIT_SIZE 10 typedef struct{ char * str; //pointer to a string int len; //length of the string } word_t; typedef struct{ word_t ** list; //array of word_t pointer int size; //size of the array int nwords; //number of words in the array } wordlist_t; //Load a list of strings from the wordlist_t * loadlist(FILE * input){ char str[1024]; int i; wordlist_t * wordlist; word_t ** tmp; //allocate wordlist struct wordlist = (wordlist_t *) calloc(1, sizeof(wordlist_t)); //initialize wordlist wordlist->list = (word_t **) calloc(INIT_SIZE, sizeof(word_t *)); wordlist->size = INIT_SIZE; wordlist->nwords = 0; i=0; while(fscanf(input, "%s", str) != EOF){ //expand if neccesary if( wordlist->size == wordlist->nwords){ tmp = (word_t **) calloc(wordlist->size * 2, sizeof(word_t *)); //new array memcpy(tmp, wordlist->list, wordlist->size * sizeof(word_t *)); //copy old array free(wordlist->list); //free old array wordlist->list = tmp; //assigne new to told wordlist->size *= 2; //update size } //allocate new node and set values wordlist->list[i] = (word_t *) calloc(1, sizeof(word_t)); wordlist->list[i]->str = strndup(str, 1024); //string duplication, up to 1024 bytes wordlist->list[i]->len = strnlen(str, 1024); //string length, up to 1024 bytes //update the number of words wordlist->nwords += 1; //increment index i++; } //return nodelist return wordlist; } /////////////////////////////////////////////////////////////////////////////////////////// // *DO* EDIT BELOW //Print a node list, be sure to match the format! void printlist(wordlist_t * wordlist){ //TODO: Complete this function int i; for(i=0;i < wordlist->nwords;i++){ //Iterate up to nwords to avoid NULL if(wordlist->list[i]){ printf("%d: %s %d\n", i, wordlist->list[i]->str, wordlist->list[i]->len); } } } //Delete a node list by free'ing all allocated memory void deletelist(wordlist_t * wordlist){ //TODO: Complete this function int i; for(i=0;i < wordlist->nwords;i++){ free(wordlist->list[i]->str); free(wordlist->list[i]); } free(wordlist->list); free(wordlist); } ////////////////////////////////////////////////////////////////////////////// // DO *NOT* EDIT BELOW int main(int argc, char * argv[]){ int i; wordlist_t * wordlist; FILE * input; //for each argument for(i=1;i<argc;i++){ //open the file if( (input = fopen(argv[i], "r")) != NULL){ //load a wordlist wordlist = loadlist(input); //print the wordlist printf("---- %s ----\n", argv[i]); printlist(wordlist); printf("\n"); //delte the wordlist deletelist(wordlist); //close the file fclose(input); }else{ //print an erro if can't open the file fprintf(stderr, "ERROR: cannot open '%s'\n", argv[i]); } } }
3 Problem 3
BIG IDEA: The file contained the raw bytes of a struct bank_entry,
so you must read those bytes into a buffer, using read(), where the
buffer is interpreted as a struct bank_entry. To read multiple bank
entries, just place the read() in a loop.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> /************************************************************ * * Instructions: * - Complete the program below where the TODO * - Your program should not segfault or have memory errors * - Your program output should exactly match the instrucitons * * When you output a bank entry, use the following prints: * * printf("Name: %s, %s\n", be.last_name, be.first_name); * printf("Bal: %d\n", be.balance); * printf("Crd: %d\n", be.credit); * ************************************************************/ struct bank_entry{ char first_name[64]; char last_name[64]; unsigned int balance; unsigned int credit; }; int main(int argc, char * argv[]){ int fd, n; struct bank_entry be; if(argc < 2){ fprintf(stderr, "ERROR: Require File\n"); return 1; } //TODO: Complete main to print the bank entry if( (fd = open(argv[1], O_RDONLY)) < 0){ perror(argv[0]); return 1; } //read sizeof(struct bank_entry)) bytes into be, in a loop while( read(fd, &be, sizeof(struct bank_entry)) > 0){ printf("Name: %s, %s\n", be.last_name, be.first_name); printf("Bal: %d\n", be.balance); printf("Crd: %d\n", be.credit); } return 0; }