Last Updated: 2021-02-07 Sun 19:47

CSCI 4061 Lab03: Input and Expanding Buffers

CODE DISTRIBUTION: lab03-code.zip

  • Download the code distribution
  • See further setup instructions below

CHANGELOG:

Sun Feb 7 07:46:35 PM CST 2021
The files alphabet.txt and nums.txt were initially missing from lab03-code.zip but have now been added to it.

1 Rationale

At times programs must deal with an input situation wherein an unknown amount of input must be accepted and stored in a single input pass. This problem is reflected in the following program specification:

Read an arbitrary length string from the user and print its characters back in reverse order.

In such a case, two common constraints are at play:

  1. The program cannot pre-allocate sufficient space as it may run out for long inputs.
  2. The input is presented only once so it cannot be counted then read again.

Dynamic data structures like Linked Lists can solve such problems by allocating nodes on demand. However, many problems such as printing in reverse are handled more succinctly with arrays. With arrays, one typically allocates some space initially and reads the input into it. If one runs out of space, allocate a larger space, copy data over to the larger space, and continue reading.

This lab demonstrates a standard technique to do this in which an input array (buffer) is repeatedly expanded to make space for input. This technique will be useful for an upcoming project.

Grading Policy

Credit for this Lab is earned by completing the exercises here and submitting a Zip of the work to Gradescope. Students are responsible to check that the results produced locally via make test are reflected on Gradescope after submitting their completed Zip. Successful completion earns 1 Engagement Point.

Lab Exercises are open resource/open collaboration and students are encouraged to coopearte on labs. Students may submit work as groups of up to 5 to Gradescope: one person submits then adds the names of their group members to the submission.

See the full policies in the course syllabus.

2 Codepack

The codepack for this lab is linked at the top of this document. Always download it and unzip/unpack it. It should contain the following files which are briefly described.

File Use Description
QUESTIONS.txt EDIT Questions to answer: fill in the multiple choice selections in this file.
print_reverse.c Study C file to study to answer QUIZ questions
file_reverse.c CREATE Create and complete the program for the CODE portion of the lab
QUESTIONS.txt.bk Backup Backup copy of the original file to help revert if needed
Makefile Build Enables make test and make zip
testy Testing Test running scripts
test_lab03.org Testing Tests for this lab

3 QUESTIONS.txt File Contents

Below are the contents of the QUESTIONS.txt file for the lab. Follow the instructions in it to complete the QUIZ and CODE questions for the lab.

                           __________________

                            LAB 03 QUESTIONS
                           __________________





Lab Instructions
================

  Follow the instructions below to experiment with topics related to
  this lab.
  - For sections marked QUIZ, fill in an (X) for the appropriate
    response in this file. Use the command `make test-quiz' to see if
    all of your answers are correct.
  - For sections marked CODE, complete the code indicated. Use the
    command `make test-code' to check if your code is complete.
  - DO NOT CHANGE any parts of this file except the QUIZ sections as it
    may interfere with the tests otherwise.
  - If your `QUESTIONS.txt' file seems corrupted, restore it by copying
    over the `QUESTIONS.txt.bk' backup file.
  - When you complete the exercises, check your answers with `make test'
    and if all is well, create a zip file with `make zip' and upload it
    to Gradescope. Ensure that the Autograder there reflects your local
    results.
  - IF YOU WORK IN A GROUP only one member needs to submit and then add
    the names of their group.


QUIZ Questions on print_reverse.c
=================================

  Analyze the `print_reverse.c' application. Compile and run it as shown
  below
  ,----
  | // DEMO:
  | > make print_reverse
  | gcc -Wall -Werror -g  -o print_reverse print_reverse.c
  | 
  | > ./print_reverse               # interactive run
  | hello world                     # typed input
  |                                 # press Ctrl-d to end input
  | dlrow olleh                     # output from program
  | 
  | # non-interactive runs via pipes
  | > printf "0123456789" | ./print_reverse
  | ...
  | 
  | > printf "here is everything I have" | ./print_reverse
  | ...
  `----

  Answer the following Questions about the techniques used in this
  program. You may need to consult the Manual Page / Documentation on
  some functions to answer confidently.


Location of buf
~~~~~~~~~~~~~~~

  The variable `buf' is used to store character data that is read from
  standard input in `print_reverse'.  Which part of memory are these
  characters stored?

  - ( ) The Stack: `buf' is declared as a local array near the top of
    `main()' so exists in `main()''s stack frame.
  - ( ) The Heap: `buf' points to an array that is `malloc()''d on the
    heap near the start of main.
  - ( ) Globals: `buf' is declared outside of any function and is
    therefore in the Globa/Static/Data portion of program memory.
  - ( ) Based on the way that `buf' is declared, it is impossible to say
    where in memory it exists.


Expansion of buf
~~~~~~~~~~~~~~~~

  The `realloc()' function is used to change the size of the memory area
  associated with `buf'.  According to your read of the code and the
  manual page for this function, which of the following is returned by
  `realloc()'?

  - ( ) It will return `NULL' if it is not possible to find a larger
    space for `buf'
  - ( ) It will return the same pointer `buf' if that space can be
    expanded in place.
  - ( ) It will return a pointer to a new memory of the requested size
    where the contents of `buf' have already been copied with the old
    pointer being automatically `free()''d.
  - ( ) `realloc()' could return any of these.


Resizing Rate
~~~~~~~~~~~~~

  Which of the following is used as the "rate" of expansion for the
  buffer?
  - ( ) If there is insufficient space in `buf', it is resized to be 1
    character larger than its previous size.
  - ( ) If there is insufficient space in `buf', it is resized to be 10
    characters larger than its previous size.
  - ( ) If there is insufficient space in `buf', it is resized to be
    150% of its previous size.
  - ( ) If there is insufficient space in `buf', it is resized to be
    200% of its previous size.

  Note that expanding by 150% or 200% each iteration leads to an "append
  item" operation that has an Amortized computation complexity O(1).
  This approach is often used in data structures such as Python Lists,
  Java's ArrayList / StringBuffer, or other "dynamic array" data
  structures. <https://en.wikipedia.org/wiki/Dynamic_array>


CODE Adapt to file_reverse.c
============================

  Create a new file called `file_reverse.c' and adapt the approach taken
  in `print_reverse.c' to print the contents of a file in reverse order,
  character by character.

  1. The provided `Makefile' will compile `file_reverse.c' to the
     program `file_reverse'
  2. `file_reverse' should take a command line argument which is the
     name of a file to print in reverse order.
  3. If no command line argument is given, print a usage message and
     exit with code 1 as demonstrated below.
  4. Open the file provided on the command line using the C standard
     library. Scan data into a character array and expand the array as
     needed using the techniques demoed in print_reverse.
  5. When the entire file has been read in, print the contents in
     reverse order.
  6. Make sure to clean up any memory used through heap allocation or
     opening files.

  NOTE: If you are not familiar with how to use `argc / argv' to deal
  with command line arguments, get help from a colleague or staff member
  to review this technique.

  The tests provided via `make test-code' use the files `alphabet.txt'
  and `nums.txt'. A correctly written program will behave as
  demonstrated below.

  ,----
  | >> ./file_reverse               # run with no args
  | usage: file_reverse <file>      # print usage message
  | 
  | >> echo $?                      # show return code
  | 1                               # 1 - error while running program
  | 
  | >> ./file_reverse alphabet.txt  # print alphabet.txt in reverse
  | 
  | z y x w v u t s r q p o n m l k j i h g f e d c b a
  | Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
  | 
  | >> echo $?                      # check return code
  | 0                               # 0 for no problems
  | 
  | >> ./file_reverse nums.txt      # print nums.txt in reverse
  | 
  | 52
  | 42
  | 32
  | 22
  | 12
  | 02
  | 91
  | 81
  | 71
  | 61
  | 51
  | 41
  | 31
  | 21
  | 11
  | 01
  | 9
  | 8
  | 7
  | 6
  | 5
  | 4
  | 3
  | 2
  | 1
  `----

4 Submission

Follow the instructions at the end of Lab01 if you need a refresher on how to upload your completed lab zip to Gradescope.


Author: Chris Kauffman (kauffman@umn.edu)
Date: 2021-02-07 Sun 19:47