Last Updated: 2026-02-09 Mon 09:43

CMSC216 HW03: Basic I/O + Binary Integers

Homeworks are optional practice with no submission and no credit

CODE DISTRIBUTION: hw03-code.zip

  • Download the code distribution
  • See further setup instructions below

CHANGELOG: Empty

1 Rationale

Reading data from files is an essential skill in any programming environment and can be a bit trickier in C due to its reliance on manual memory management via malloc(). This HW discusses a standard two-pass input strategy for dealing with such situations.

Computers internally represent numbers in a binary encoding scheme such as the Two's Complement system. Character data ("strings") are also represented this way. To gain insight into how these two types relate, this HW studies some conversion routines between them.

Associated Reading / Preparation

Most C references will contain information on C's standard I/O libraries which discuss functions like fopen(), fscanf(), rewind() and fclose().

Grading Policy

Homework provides optional extra practice for students looking for it. No submission is collected and the HW is not worth any course credit. Solutions will be posted some time after the HW is posted. Students approaching course staff for additional practice problems will be asked to explain their own written answers to the QUESTIONS.txt documents in HWs before any additional problems will be constructed.

2 Codepack

The codepack for the HW contains the following files:

File Description
QUESTIONS.txt Questions to answer
twopass.c Code for Problem 1
twopass_stack.c Code for Problem 1
nums1.txt / nums2.txt Data files for Problem 1
convert.c C file for Problem 2
print_int.c CREATE this file for Problem 2

3 Questions

Analyze the files in the provided codepack and answer the questions given in QUESTIONS.txt.

                           _________________

                            HW 03 QUESTIONS
                           _________________


HWs are optional practice and there is no submission.


PROBLEM 1: Two-Pass Input and malloc()
======================================

  One frequently encounters the following situation when reading files
  - The file contains some data that is to be read into a dynamically
    allocated array
  - There is no indication of how much data is in the file

  Some file formats are designed to prevent this situation by storing
  the number of elements they contain early in the file (see the
  "Treasure Map" files in a recent lab for an example of this).
  However, programs can usually be written to handle input files without
  any size information which can make creating data files more
  convenient.

  C programs which want to read file data into an array commonly use a
  *two-pass* input strategy when the size of array needed is not known.
  1. Read through the file once to count items in the file, the allocate
     memory for an array of that size
  2. Back up to the beginning of the file and read data from the file
     into the array

  The provided program `twopass.c' demonstrates this technique along
  with several other input / formatting techniques.


A
~

  Compile and run the `twopass.c' program on the two provided text files
  `nums1.txt' and `nums2.txt'.  Paste the output the program produces
  below.


B
~

  Examine the function `read_all_doubles()' in `twopass.c' and describe
  which lines/blocks of code carry out the following actions. Use the
  provided comments in the file as a guide.

  - Opens the file for reading and checks for errors
  - Counts all the doubles in the file
  - Allocates memory for doubles in the file
  - Moves the file read position to the beginning of the file
  - Closes the file when reading is complete


C
~

  In your answer to the previous problem, you should have identified a
  use of `malloc()' in `read_all_doubles()'.  Where is this memory
  `free()''d and why? /Note: This question is similar to a lecture
  exercise on when to free() memory that has been malloc()'d./


D
~

  Examine how the doubles read from file are printed in the `main()'
  function. Discuss below the format specifiers used by `printf()' and
  the width/precision modifiers that are used to get a "table-like"
  appearance.  You may wish to consult the Manual page on `printf()'
  such as the one here:

  <http://man.he.net/?topic=printf+3&section=3>

  (Note: Unix systems have several `printf()' functions and "Section 3"
  of the manual pages describes the C version).


E
~

  An attempted alternative version of this program is present in
  `twopass_stack.c'. Analyze this version to determine how it differs
  from the original. Compile and run it to see whether it behaves
  differently.  Describe what you see and explain the source of any
  behavior differences.


Contrast: Arrays vs Linked Lists
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Two-pass I/O or a data file containing the number of elements to read
  are required when reading data into an array as the size of the array
  must usually be fixed ahead of time for maximal efficiency.  However,
  when reading into other data structures, notably Linked Lists, data
  can be "added on" efficiently to the data structure as it is read.
  This is one strength of such data structures compared to arrays but
  there are also disadvantages to consider. Understanding the tradeoffs
  between the different data structures available and choosing one that
  is most suited to the situation is an important part of good program
  design.


Optional Enrichment: Reading without Storing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  One minor irritation in `read_all_doubles()' is the following code:
  ,----
  |   double tmp;                              // temporary space to read one double
  |   ...;
  |   while(1){                                // first input pass: indefinite loop to count doubles
  |     int ret = fscanf(fin, "%lf", &tmp);    // try to read a double
  |     ...;
  |   }
  `----
  This loop is counting the doubles in an input file but discarding
  them.  Avoiding the need to allocate the `tmp' variable is desirable
  and can be done using some more advanced format specifiers in
  `fscanf() / scanf()' that indicate "read a double but do not store it
  anywhere". This allows the counting loop to happen without need for
  any additional space for doubles.

  Look how to get `fscanf()' to parse items like doubles without
  requiring space to store the result.


PROBLEM 2: Converting Strings to Numbers and Back
=================================================

A
~

  Inspect the program in the code pack called `convert.c'.  Compile and
  run it using
  ,----
  | > gcc convert.c
  | > ./a.out
  `----

  Describe briefly what kind of conversion is being done by the
  `convert()' function given.
  - A. What kind of data is input?
  - B. What result is produced by the function?
  - C. How is a success versus an error reported?
  - D. Why is this kind of conversion needed?
  - E. What built-in C function (useful for the assignment) does this
    conversion function use and how is its calling convention different
    from convert()?


B
~

  Write function called `print_int(int anint)' which uses only calls to
  `putchar(c)' to display an integer in decimal (base 10)
  format. `putchar('A')' will put the single character `A' on the
  screen.  This function will require you to repeatedly determine what
  digit of a number to print and use an appropriate character. The code
  will give insight into how C's `printf("%d",anint)' works.

  A template including a `main()' function is provided in `print_int.c'
  in the code pack. A successful run would like the following:
  ,----
  | >> gcc print_int.c
  | 
  | >> ./a.out
  | 1234
  | 8675309
  | -5
  | -789123
  | 0
  `----

Web Accessibility
Author: Chris Kauffman (profk@umd.edu)
Date: 2026-02-09 Mon 09:43