6-Week Practicum Solutions
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
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]); } } }
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; }