Category Archives: pr2_en

PR2EN3: Structures

Lab materials

In the lab, a sample solution will be written together and commented where data fill be read from the file and stored in a struct array. This is also published as a code example for those not participating in the labReading from a file into structure array

Lab tasks

In this lab, you have one task which is expanded by three extra tasks.

Lab task [W03-1]: employee search

The purpose of this task is to introduce you to using structures. The task will mimic a very basic employee database where the user can search for employees and that also supports commands.

Data file

Download the test data from the following link https://blue.pri.ee/ttu/files/iax0584/andmefailid/3_data_short.zip

Data file is composed of randomly generated data.

Requirements

  • Read employee data from the file
    • Reading the data file more than once within your program is not permitted.
    • File has one record per line
    • Every data field is separated by a space. All data fields are single word.
    • Data structure in the file:
      <eID> <first_name> <last_name> <city>
  • The data needs to be kept in the memory as a struct array
  • Program must work in a situation where the exact number of records is unknown and can change (e.g. somebody gets employed, fired or leaves)
    • Create a reasonable limit in your program and test
    • If the data file is longer than the allowed limit, print a corresponding message. Behavior after this is up to you.
  • The program must allow for repeated searches and processing of commands without restarting the application
  • Allow the operator to perform searches based on the city name
    • Program will output all employees in the city
    • Show how many matches were found (E.g. [0 / 91])
    • Search must be repeatable without exiting and restarting the program
    • In the base task, print all the data available – eID, last name, first name, city
  • There must be support for commands
    • Commands should start with a “:” to identify them from city searches
    • Command “:all” must print all people in the database, without any filtering
    • Command “:exit” must close the program

Hints

The command parser sounds “scary”, while the solution is extremely simple. All of this you learned in Programming 1 in the strings class. This is a 3-step process

  1. Identify that user entered a command (check that the 0-th character is ‘:’) – this was an example on the slide
  2. Make a pointer to the second character ( char *command = input + 1; )-  this is pointer arithmetic from week 1, also used in week 2 for the file extension
  3. Compare the command to known commands

Example output

The first example is about command handling. If it cannot recognize a command, it states so. If a command is entered without a colon, it will search instead (default behavior).

The second example shows how searching is handled.

Note that the output of “:list” command is not shown due to it being somewhat long.

The last example shows the program when all extra tasks have been completed. This is wrapped in a spoiler to reduce the size on normal vieweing.

Click me to see the complete output

Extra task 1 [W03-2]: List available cities

Requirements

  • List all the cities present in the file
  • List of the cities must be generated based on the data file (cannot be hardcoded into the program)
  • List of cities must be ordered alphabetically
  • Add a command “:list” to your command parser.
  • Operator must be able to repeatedly print out the list during the runtime of the program
  • The list of the cities can only be composed once per execution of the program

Extra task 2 [W03-3]: Better search

Requirements

  • The search must be case-insensitive. Searching for either  TALLINN  or tallinn  must print all employees living in Tallinn.
  • Search must support partial matches. E.g. when searching for  all , you should display employees living both in Kallaste and Tallinn.
  • Both features must working at the same time. The last result should also be obtainable by entering ALL or aLL.
    NB! Notice that :all  is a command printing everyone and all  is a search phrase printing people in Tallinn and Kallaste.

Extra task 3 [W03-4]: Parse the eID

Requirements

  • Do not display the eID in the output of your program
  • Display the employees date of birth with the format d. MMMM yyyy

Official information about eID: https://www.riigiteataja.ee/akt/114022017005

Short description of it in English: https://en.wikipedia.org/wiki/National_identification_number#Estonia

Click me to see date and time format guide

m – Minutes from 0 to 59.
mm – Minutes from 00 to 59. Minutes from 0 to 9 are prefixed with a zero.

h – Hour from 1 – 12.
hh – Hour from 01 to 12. Hours from 1 to 9 are prefixed with a zero.
H – Hour from 0 – 23
HH – Hour from 00 – 23. Hours from 0 to 9 are prefixed with a zero.

d – Day from 1 to 31
dd – Day from 01 to 31. Days from 1 to 9 are prefixed with a zero.
ddd – Day as a short name (Mon, Tue, Wed, …)
dddd – Day as a long name (Monday, Tuesday, Wednesday, …)

M – Month from 1 to 12
MM – Month from 01 to 12. Months from 1 – 9 are prefixed with a zero.
MMM – Month as a short name (Jan, Feb, Mar, Apr, …)
MMMM – Month as a full name (January, February, March, …)

y – Year from 0 to 99
yy – Year from 00 to 99
yyy – Year with a minimum of 3 digits (1 -> 001; 15 -> 015; 145 -> 145; 1949 -> 1949)
yyyy – Year with 4 digits

After the class, you should

  • Know how to declare a new structure type
  • Know how to pick members for a structure
  • Know what is structure padding and how it affects the size of the structure
  • Know what affects the final size of a structure
  • Know which structure member access exist and be able to use the dot operator
  • Know how to create an array of structures and read data from a file into that array of structures
  • Know how to assign structures
  • Know how to give existing types new names (use typedef)

Additional content

PR2EN1: Pointers

Lab materials

Reminder on style

  • Coding style must be uniform throughout all the code files
  • Your code should be easily readable and maintainable
  • Prefer simple over bloated and overengineered code
  • Divide your code into functions
    • Functions should be simple, short, do only one thing and do it well
    • Keep computational and input/output functions separate. If a function produces a result, it should avoid side effects if possible.
    • Functions should be easily reusable. This will help you during the test and the exam.
    • main function should be the first function in a file. All user-defined functions should be positioned after the main function.
  • Use reasonably fast algorithms within the ones we’ve studies so far
  • Avoid global variables in most situations, there are a few where it’s okay and those situations will be mentioned separately during the course.

Tasks

There are two lab tasks in this class. The first task focuses on passing data using pointers and the second task is about how arrays and pointers work together. Second task is divided into two parts and extended by an extra task.

Lab task 1 [W01-1]: Pointer to a variable

This is a classical swap the two values in a function task. Try to solve this task by instructions and slides alone, without using outside help or materials.

Download the starter code here: https://blue.pri.ee/ttu/files/iax0584/aluskoodid/t1_swap_template.c

Theory nugget 1: stderr standard stream

This semester we will start to separate error outputs from normal outputs. All error outputs will go to stderr standard error stream. This is common for most programming languages, including C. It allows to filter out errors from the normal output, look up “redirect stderr to file” for more information.

Old way: print all errors to stdout  standard output stream: printf("Error! ....");

From now on: print all errors to stderr  standard error stream: fprintf(stderr, "Error! ...");

Theory nugget: New macros introduced in the starter code

When reading through the starter code, you’ll notice a new element  __FUNCTION__  – this is a string that prints the function name where it is used. It will be resolved when you compile the code – do not attempt to modify it. Starting from C99 standard, you can also use  __func__  – both achieve the same thing.

In addition, there are two more macros that are often used for debugging code:

  • __LINE__ prints the line number where the macro is used
  • __FILE__ prints the name of the file where the macro is used

Using those, we could write something like

This makes it easier to observe in which file, in which function and on which line an error occurred.

Requirements
  • Use the starter code provided
  • All parts you need to complete are marked with TODO  in the starter code
  • Create two functions according to function comments in the starter code. One to read values, second to swap values. Call the functions.
  • Print out the memory addresses where the data is stored in three different locations
    1. In the main()  function, show where the variables are declared at in memory
    2. In the reading function, show the addresses where you are storing the values to
    3. In the swap function, show the location where the values are you are swapping
  • Explain the significance of the address values when defending!
Testing

Lab task 2 part 1 [W01-2]: Pointer to an array

The purpose of the second task is to show how arrays and pointers are related to each other. In addition, we will explore pointer arithmetic and and do a reminder from last semester, where we learned about files and command line arguments.

The program needs a data file that contains integers. Create the data file yourself! Numbers can either be separated by spaces or newlines.

Requirements

Create a program that fulfills the following requirements

  • Reads 10 integers from a file and stores them into an array
  • The name of the file is read as a command line argument
  • Show the array base address in the main function
  • Print out the read integers and their memory addresses
  • Find the minimum and maximum value from the array

Additional requirements that must be met

  • During this task, you are not permitted to use square brackets []  for indexing the array (limitation does not apply to declaring an array). Use pointer arithmetic in all functions
  • The program is halted if the file doesn’t exist or it was unable to read integers from the file – i.e. file contains something else
  • You must complete the list of functions specified in the requirements
  • All functions must be called from the main()  function
  • The minimum and maximum value must be printed in the main()  function
  • All error messages must be printed to the stderr  standard stream.

Create the following functions

  • Create a function, that reads 10 numbers  from a file and stores them in an array.
    • Optional: if you wish, you can print out the addresses during reading for self-checking and comparison against other functions
    • Parameters: array, the array size (limit), name of input file
    • Return: how many numbers were read
    • You must avoid reading more numbers than can fit into the array
    • You can use the following partial solution for the function and fill in the gaps highlighted by TODO. It should be relatively similar to week 8 in programming one, but with the addition of the file
    • Additional hint: For a readable solution of calling this function, you can store the command line argument in a pointer as follows:
  • Create a function that prints out all numbers and their memory addresses
    • Parameters: name of the array, number of integers read from the file
  • Create a function that  find both the minimum and maximum number
    • You can only call this function once – it must find both results in one go and store them
    • Function can’t return anything, i.e. the function return type must be void .
    • Assume that only one minimum and maximum exists
    • Use the concept of pointers from task 1 to solve getting multiple values from a function.
      • Do not use an array to store min/max values!
      • Do not print the results in this function.
Testing

When testing the base task, test for four different results

  1. Command line arguments are missing, program prints an error and closes
  2. File does not open, program prints an error and closes
  3. There are no integers in the file, program prints an error and closes
  4. There are some integers in the file. At most 10 will be read and printed. Minimum and maximum value will be printed.

Lab task 2 part 2 [W01-3]: Interpretation of array concept

The purpose of the second part of the task is to make sure you understood the concept that an array can be interpreted as the pointer to the first member.

Requirements
  • Create (or reuse 😉 ) a function that is able to print n numbers and their memory addresses in the array.
  • The function can only have two parameters.
  • The function must be built in a way that it is able to print any arbitrary array
  • To demonstrate that you wrote this function correctly (and understood the topic correctly), call the function 3 times, so that
    • it will print out all members of the array
    • it will print out elements 0 to 4
    • it will print out elements 3 – 9
  • NB! What happens if you got less numbers from the file?

Hint 1: Think before acting! This part of the task is about the concept of pointers and arrays rather than creating some very clever and devious solution! Do not attempt to over-engineer the solution!

Hint 2: The text preceding the printed array members should be printed in the main() function, before the function call.

Testing

Part two has two possible results

  1. Array is long enough, program will print the requested sequences
  2. Array does not contain enough members, program will print an error.

The example shows expected output if enough members were read.

Extra task [W01-4]: MinMax task with addresses

In this task, we will recreate the minmax function from part 1 of task 2 . We add the ability to also print the memory addresses and indexes for the minimum and maximum value.

You are recommended to leave the original implementation in place and create a new function.

Requirements
  • Create a new function to find the locations of the minimum and maximum elements in the array in one go.
  • The return type of this function must be void .
  • The function must have 4 parameters
    • Array
    • Length of the array
    • 2 pointers or double pointers – figure out what to store in them!
  • In the main function, print out the following results
    • The min and max value
    • The addresses of where the min and max are stored in the array
    • The index of min and max value in the array.
    • NB! You must calculate the results, not loop through the array
Testing

Expected output of extra task

After the class, you should

  • Understand the requirements for this subject, including how to get a grade
  • Understand what a pointer is
  • Understand the significance of memory addresses
  • Understand virtual and physical addresses
  • Know what affects the address length
  • Know the extra memory requirements for explicit use of pointers
  • Be able to declare pointers
  • Know the coding style aspects of declaring and using pointers
  • Know what’s the importance of pointer data types
  • Know the significance and use for NULL pointers
  • Know the two pointer operators and where to use them
  • Have some understanding of possible use cases for pointers
  • Know how to use pointer arithmetic
  • Have a better understanding of the scanf arguments and how pointers come into play here
  • Understand why we said that arrays were editable when passed to a function, but variables were not
  • Be able to pass the addresses of variables to functions as pointers
  • Be able to edit multiple variables in a function
  • Understand the concept of double pointers
  • Know how to use a ternary operator
  • Know how to use GCC macros for listing the name of the file, function and line number
  • Know how and when to use stderr standard stream

Additional content

PR2EN2: Enumerations

Lab materials

Tasks

The lab has two tasks. These tasks cover a lot of topics from Programming 1, but are enriched with the enumeration topic introduced this week.  Both tasks also benefit from the pointers covered last week.

Lab task [W02-1]: File categorization

In this task, you will create a utility that will be able to count how many files of each category exist (e.g. how many image files in a directory and its subdirectories).  We will only create the part that categorizes files and counts the totals.

To find the names of files, we will use knowledge from the Linux task last semester. We will use a tool called find  to find the files recursively and pipe them to our program. By doing this, we will be able to index and categorize any amount of files recursively in all subdirectories.

Note: To demonstrate the potential of combining programs you need have access to a bash environment. Easiest way is to test in the university environment (use the lab computer, remote desktop or create an SSH tunnel to one of our servers or lab computers).

Requirements

Create a program that

  • Accepts an unknown number of file names from the standard input ( stdin ).
    • You are not allowed to preemptively ask for number of inputs or have a designated string to stop reading inputs.
    • To stop reading the strings and show the statistics, listen for the EOF  (end of file) signal.
  • Categorizes those files to groups based on the identifiable extensions and counts how many files in each category.
  • Display how many files were in each category.
  • Categories must be identified as enumeration type in code.
  • One of the functions you need to have is specified for you. It needs to  take the file extension as a parameter and returns the enum of the category. Proposed function prototype:
    enum FileCategory GetFileCategory(char *extension);
  • Your program can provide a prompt when started (i.e. instructions), but must not write anything to the output in between inputs.
Categories and extensions

This is a list of categories that you are expected to test against. The results of files using these extensions is also given as a test set.

  • Archives: zip, rar, 7z, tar, gz
  • Data: csv, xls, xlsx, ods
  • Documents: pdf, doc, docx, rtf, odt
  • Code: c, h, cpp, hpp, py
  • Text: txt
  • Images: jpg, jpeg, png, svg,
  • Other: all files with extensions, but not in the previously listed types
  • No extension
Template for the task

In order to give you a bit better idea on the expected structure and how the reading and processing would work, you are provided a template to base your task on.

Recommended steps for solving the task
  1. Add a function that will fix the trailing newline in the read string
    e.g.. void FixTrailingNewline(char *str);
  2. Add a function that will find the location of the last point ( . ) symbol in the string to identify the start of the file extension.
    e.g. int GetLastPointPos(char *str);
  3. Add the category enumeration to your code and create an initialized array of counters for the categories.
  4. Add a function to print the array of counters (result)
    e.g. void PrintFileCntPerCategory(int *categoryCounters, int numOfCategories);
  5. Add a function that will, based on the given extension, find the category of the file.
    NB! Look at the flying object identification code example for inspiration!
    e.g.  enum FileCategory GetFileCategory(char *extension);
Hints and warnings:
  • Check out the additional enum example on this page. It is based on a similar categorization task, it will offer quite a few ideas on code structure.
  • You should recognize various subtasks from last semester – i.e. parts of the first and second strings lab task and age classifier home work.
  • If you add a count item after the last enumerated item, it will tell you the number of items in the list. This will only work if you allow it to automatically number all items!

    This allows you to automatically declare the correct length array for counters.

  • By using what you learned about pointers last week (i.e. pointer arithmetic),  you can use the location of the point symbol as an offset to calculate the address where the extension starts. That new address would also be pointing at a string.
  • The length of the reading loop is of unknown length. fgets()  returns NULL  when EOF  (end of file, indicating no more inputs) is reached.
  • fgets()  stores the trailing newline character which needs to be corrected for.
  • Input for your program comes from a pipe to your programs stdin
  • To quickly test without the command line, you can hit ctrl+d  to send the EOF  signal
Testing manually when creating the program

To test manually, we can run the program normally, type in the names of files, pressing enter after each file name. Once done, hit ctrl+d  to send the EOF (end of file) signal.

Testing correctness

To test the correctness, we will index a folder that I have prepared for you. If you are on the lab computer, you can access it directly over the network. If you are using your own computer, download the archive provided and change the path for find . Your numbers for each category should match the ones presented in this example.

We use a tool called find  to search for files and folders and limit it to only show files and print without the path. First we show the location where we are searching in, then we specify to only show files (omit folders) and we then print the names of files without the path. The output of find (from stdout , standard output stream) will be piped into our programs stdin  (standard input stream).

Command executed: find ~/M/risto.heinsar/lab_cat/ -type f -printf '%f\n' | ./task1_category

Hint: if you’re curious, you can also test your own P drive and add extensions and/or categories.

Backup of the test files

Note: if you are unable to demonstrate the correctness due to networking issues or want to test on your own device, you can can demonstrate the correctness by using the following the archived version of the directory structure.

https://blue.pri.ee/ttu/files/iax0584/andmefailid/2_1_file_cat_directory_structure.zip

The structure is the same as on the M drive.

Lab task 2 [W02-2]: Distance conversion

You have been provided activity data from a group of employees in an international company. The data files are provided after the requirements section. Your task is to convert the data in the files to the desired output units, show the results of the conversion and provide basic statistics.

Requirements
  • Program takes two command line arguments
    • First argument is the name of the input file
    • Second argument is the desired output unit of distance (available options: m  for meters, ft  for feet and km  for kilometers)
  • Input file is a basic ASCII text file (first command line argument).
    • Each line in the file contains one entry
    • Each entry consist of two fields, separated by a space: <distance> <unit>
    • Distances are given as real numbers
    • Units are given as strings. Units in the input file can only be in feet or meters.
  • Calculate and display all distances, converted to the desired output unit
  • Calculate and output the average and total distances walked.
  • All distances are shown with 2 places after the comma.
  • Units must be handled using enums. Recommended list is provided:
  • Conversion coefficients are also provided
  • Look at hints for getting ideas how the functions might look like for more optimum code division.
Data files

There are 3 files provided for you to test your program with. Look under the paragraph Testing for what you should look out for when testing with each of the files!

Download the test files: https://blue.pri.ee/ttu/files/iax0584/andmefailid/2_2_converter_data.zip

Hints and tricks
Hint 1: Conversion function

Remember to not overcomplicate your functions. Your convert function should only handle conversion from one unit type to another. Do not try to decode the string into a unit in that function.  Just pass it the decoded enum types and the value that needs converison.

E.g. some ideas for the prototype of that function

Hint 2: Decoding the unit

To decode both the input and the output units, use the same function – both are strings with just the unit. It should be a function that would return the unit type.

E.g.   enum Unit GetDistanceUnitType(char *unit);

Hint 3: Printing the units

There are a lot of units in play. Printing the correct one can be a bit tricky. There are two ideas to help you with:

Option 1: Create a function to print the unit and call it when you need it. Call it whenever you need to print the correct unit according to the task.

Option 2: Create a function that will return you a pointer to a string containing the unit.  Since it is written as a constant, it will be available in the memory after the function returns. It makes this really convenient to use it in print statements – e.g. printf("%.2f %s\n, distance, ReturnPrintableUnit(unit));

Testing

This program has a lot of ways it can go wrong. Make sure to test for all constraints!

Test 1 – 3: Invalid arguments

This test actually is comprised of 3 different tests, but all of them have wrong arguments passed to the program.

Test 4, 5: Problematic arguments

The next two tests are about parsing the arguments themselves and making sure that both the file exist and the unit is within the allowed list.

Test 6: empty file

The purpose of this test is to make sure that our program does not crash when there is no data to process.

task2_data1.txt contents:

And the results for this data file: 

Test 7 – 9: Conversion tests

In these tests we will go over all of the possible input and output unit conversions. We use a simple data file that allows us to easily observe if our answers are correct.

task2_data2.txt contents:

And the results for this data file:

Test 10: Different file

The emphasis for this test is to test your program with a different data file – just different length and units to make sure that nothing got passed us by.

task2_data3.txt contents:

And the results for this data file:

Sidenote: did you notice what we didn’t test for, but cold also be improtant?

Extra task [W02-3]: comprehensive converter

The extra task is based on lab task 2 and must be an extension of the base task. Disregard the concept of “walking” and consider the task as just a distance converter with statistics.

Requirements
  • Add support for additional distance units
    • Yard (yd)
    • Inch (in)
    • Decimeter (dm)
  • You must allow all 6 units to be both inputs and outputs for the program.
  • Design the conversions in a expandable fashion so that if we would add additional units, it wouldn’t require large overhauls of the code. The complexity of adding another unit must not expand the codebase exponentially!

Warning! Even though the expected  method for conversion is simple to implement and manage, it may increase the error of the final result due to rounding of the conversion coefficients outside of metric system. Be careful with tasks requiring high precision!

After the class, you should

  • Have gone over many of the topics covered last semester, including command line arguments, parsing strings, reading from files etc
  • Be able to work with enumerations
    • Declaring new enum types
    • Know how the auto-numeration for enums works
    • Declaring variables based on enum types
    • Pass enums to functions, return enums from functions

Additional content

Note: most sites explaining enumerations can’t even follow the same coding style on a single page! Use the style guide provided by us!

2. lab: pointers

Lab content

 

After the class, you should be able to

  • Understand what a pointer is
  • Declare different types of pointers
  • Understand some of the use cases for pointers
  • Understand what a NULL pointer is
  • Understand the dereference and address operators
  • Understand why some variables when reading with scanf() required & and some didn’t
  • Find the address of any variable
  • Pass addresses of variables to functions (by reference)
  • Better understand the difference of passing arguments to functions by value and by reference (originally simplified as copy, original)
  • Understand how arrays are actually passed to functions and thus why we can alter them without any extra steps
  • Understand pointer arithmetics
  • Know what a memory address looks like
  • Understand that there are different width memory addresses and why  it is like that

Additional content