IC221: Systems Programming (SP15)


Home Policy Calendar

6-Week Practicum Solutions for Spring 2014

Table of Contents

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;
}