CS1101c 2009/2010 Semester 1 - Lab 11

for Week 13, Wednesday, 11th Nov 2009

Back to index page

Introduction

This is your really last take home lab exercise. Even though there are no more sit in labs, you are strongly encouraged to attempt this question to prepare yourself for your final exam.

In general, you should use the standard I/O using scanf for input and printf for output in your programs, unless otherwise stated.

If you have any questions, you may post your queries in the IVLE forum. You should take note that your program output should exactly match the output given in the sample run.

Deadline

There is no deadline for your take home labs. However you are encouraged to practice them as early as possible.


Task 1 Database

Background

A database is a structured collection of records or data that is stored in a computer system. The structure is achieved by organizing the data according to a database model. The model in most common use today is the relational model. You will study more about this in a future module (CS2102).

In this exercise we want to write a simple database system for a social networking website (such as friendster or facebook). To simplify the problem, we would only store the few basic information of each user (as a single struct) below:

In addition, you may have more fields in your struct as you desire. For example you may need an additional field called num_friends which keeps track of the total number of friends in the friends array. (You may also indicate the last element in the array by setting -1 in the array slot after the last friend, i.e. like how strings use the null character to denote the last element of the string).

Database file

The  first line contains a single integer n which denotes the number of users.

The next n lines contain the user information, each field is separated by a space. The format of each line is as follows:

You may assume a maximum of 1000 users.

Input and Output

The first line of the input is a single string denoting the filename of the database.

The second line of the input is the login credentials of a user in the following order:

There are two outcomes after the login line: successful (where the user id and password matches an entry in the database) or unsuccessful (where user id and password does not match any entry in the database)

Unsuccessful login

You should output the line "Login failed." and end the program.

Successful login (for a normal user)

You should output the line "Welcome <nickname>, you have n friends. They are:", followed by the nicknames of all the user's names in a single line each. After which you may exit the program.

An example output:

Welcome Awe, you have 5 friends. They are:
Max
Jerm
Bastion
Asurians
Leyar

Successful login (for an administrative)

You should output the line "Welcome <nickname>, please specify function:". Following which you should repeatedly prompt the user to enter a command with some parameters.

An example output:

Welcome Jake, please specify function:

More on this on part 3 write-up.

Assumptions

Assume the following is true:

See notes on how  to obtain the friend's nicknames.

Part 1

Write a function to read in the database from the file.

Part 2

Write a function to output the friends of a user.

Part 3

Implement the administrative functionalities of your program. Your administrator should be able to do the  following:

Sample Run

We are using the database as follows:

5
1000 000 0 Jake 28 0
1001 aaa 1 Max 45 3 1002 1003 1004
1002 bbb 1 Jerm 32 2 1004 1003
1003 ccc 1 Bastion 17 0
1004 ddd 1 Asurians 57 3 1001 1002 1003

Sample run using interactive input (user's input shown in blue; output shown in bold purple):

database.txt
1002 bbb

Welcome Jerm, you have 2 friends. They are:
Asurians
Bastion

The first 5 lines of the above sample run shows the database of the system.  We can see the Bastion have not added any friends yet. The logged in user is Jerm and the order we print his friends is shown as 1004 followed by 1003 (which is Asurians, then Bastion). You are reminded to be careful in your output (case sensativity, spaces, full stops must be exactly in place.)

Another sample run is shown below:

database.txt
1002 eee

Login failed.

In the above mentioned run, we note that the password for user 1002 is incorrect, therefore we print Login failed.

Another sample run is shown below:

database.txt
1005 bbb

Login failed.

In the above mentioned run, we note that user 1005 does not exist, therefore we print Login failed.

Another sample run is shown below:

database.txt
1003 ccc

Welcome Bastion, you have 0 friends. They are:

Another sample run is shown below:

database.txt
1000 000
Welcome Jake, please specify function: viewall
1000 000 0 Jake 28 0
1001 aaa 1 Max 45 3 1002 1003 1004
1002 bbb 1 Jerm 32 2 1004 1003
1003 ccc 1 Bastion 17 0
1004 ddd 1 Asurians 57 3 1001 1002 1003

Welcome Jake, please specify function: changepwd 1001 fff
Password for 1001 changed.
Welcome Jake, please specify function:
viewall
1000 000 0 Jake 28 0
1001 fff 1 Max 45 3 1002 1003 1004
1002 bbb 1 Jerm 32 2 1004 1003
1003 ccc 1 Bastion 17 0
1004 ddd 1 Asurians 57 3 1001 1002 1003
Welcome Jake, please specify function: changepwd 1009 fff
Invalid user id.
Welcome Jake, please specify function: quit

Files

Your program should be coded in a single file called "Database.c". You are provided with an almost complete skeletal file which you may download here (also downloaded automatically when you click on setup and develop on CourseMarker). The database is also provided to you here.

You may change the skeletal file in any manner you wish such as: rewrite any functions, change the return types or modify the function arguments etc. However the coded solution is done using the skeletal file provided with no changes necessary.

Regardless of your decision, you are advised not to modify the main method as it has fully coded the input and output for you. (If you feel that you need to make a change, please feel free to do so).

Note: All the test cases are provided here. The emphasis of this lab is not on the output correctness but on learning how to use structs, so do not worry if your output is not exactly the same as what is required.

How to start

You might be confused on how to start working on this exercise. Here are the steps on how I wrote the solution for this exercise. How you do it may differ.

  1. First, write the required codes to read in the data file. For testing purposes, you might want to first only read (store) in the user id.
  2. Write a function to print out the total number of users (to ensure step 1 is partially correct).
  3. Next write the codes to print all the user ids that has been loaded. This is to ensure that you have read in the data correctly.
  4. Modify (1) to now read in all the data
  5. Modify (3) to now print all the data that has been loaded. If something goes wrong, you can double check which fields might have resulted in your error.
  6. Next implement the part for login purposes. Try printing out the nickname of the logged in user.
  7. Next implement the part for a non-admin user, print out all the friend's nicknames
  8. Finally implement the part for the admin user, implement viewall (you should find that you can simply call the function you have written in step (3)!)
  9. Implement changepwd
  10. Implement quit

Printing the list of friends

It is mentioned that in the struct, for each user you have an array containing the login_id of his/her friends. However after the user has logged in, you are supposed to print out the nicknames of a user's friends. The method to do this is as follows:

For each friend f in friends[]
  For each user u in users[]
    if f is equals u.user_id
      Output u.nickname

From the pseudo-code above, what we are doing is that since the friend array stores the user id of all friends, we can simply check each friend against all the user's user_id for matches and if found we can output the found nickname.

Changing the password of a user

When changing the password of a user as an administrator, you are required to change the string pointed to by the struct representing the user. The best way to do this is to write a method with a pointer to this struct. In this way, when the values pointed by the pointer is changed, it is also reflected in the main method.

Additional Info

You should note that the get_login function returns a pointer to the required struct.