ASSIGNMENT REPORT
1
C Programming Assignment Report
Khoi Quy Nguyen
Ho Chi Minh University of Technology
Author Note
Course name: Introduction to Programming CO1003, HK182
Begin date: 18 February, 2019
Due date: 22 May, 2019
Submission date: 22 May, 2019
ASSIGNMENT PROGRESS REPORT
2
Abstract
This is the report of our team’s approach to the assignment. The requirement was to write
a customer relationship management program for an enterprise, which was divided into 4 parts:
customer information, information of commercial transactions, product details and subtasks. In
total, 4 data structures and 21 functions were created. Despite adversities throughout the project,
we were able to communicate well and finished the project 20 days prior to the (recently
changed) deadline, which was due 22 May. However, minor changes was needed so we
submitted again at 22 May.
ASSIGNMENT PROGRESS REPORT
3
Method
Participants
As listed from the instructor’s attribution beforehand, our team has 4 members:
-
Nguyen Quy Khoi (Student ID: 1852158)
-
Pham Phu Duy Khuong (Student ID: 1652327)
-
Quach Duc Khuong (Student ID: 1652328)
-
Mai Huy Gia Khiem (Student ID: 1652297)
Assessments and Measures
Test description and Results:
(Nguyen Quy Khoi)
1. (20 February) Create 4 structure data types: Date
, Customer
, Product
,
Transaction.
-
In this task, the structure data types were created according to the assignment’s
requirement.
2. (25 February) Check for validation date.
-
In this task, function isLeapYearis used to check for leap year, which occurs
every 4 years (does not include the years divisible by 100) and century leap year,
which occurs every 400 years starting from year 1 AC. This function uses
operation %.
-
Restrain limit of days corresponding to each month (months with 31 days, 30 days
and February).
ASSIGNMENT PROGRESS REPORT
4
Input: 29/2/2019
Input: 28/2/2019
Output: 0
Output: 1
Functions used for date validation: isLeapYear
, isValidDate
.
3. (Added on May 14) Check if a given string only contains alphabets and spaces (function
isName
). The function operates based on known functions from the library ctype.h
using for loop.
4. (Added on May 14) Check if a given string only contains alphabets, digits, spaces and
commas (function isArray
). The function operates based on known functions from the
library ctype.husing for loop.
5. Get information from 3 different parts: getCustomerInformation
,
getProdDetailInformation
, createTransaction
.
-
(20 March) In function getCustomerInformationand
getProdDetailInformation
, the information is validated using functions
isValid
, isNameand isArray
.
-
(23 March) In function createTransaction
, transaction types are written in
array of strings instead of enumerate data type for simplicity. The types are then
attached an order from 0 to 2 using variable choice
, which was validated by
function inputNumber(this part was helped by Quack Duc Khuong). The rest
are checked using while loop, function isValidDate
, isValid
.
6. (27 March) Display product details (function displayProdDetail
) if requested.
7. (27 March) Display customer information (function customerDataBase
) if
requested.
ASSIGNMENT PROGRESS REPORT
5
8. (27 March) Display product availability (function productDataBase
) if requested.
9. (27 March) Display transaction details (function transactionDataBase
) if
requested.
10. (14 May) Write project report
(Mai Huy Gia Khiem)
1. (23 February) Check if a given string with known length only contains digits which were
written in ASCII code (function isValid
).
2. (25 February) Return a number from user input which is smaller than a given limit
(function inputNumber
, validation loop included). The function is used in case of
incorrect input from users.
3.
(13 March) Given the selection menu constituting customer, product, transaction and
save (in order to end the process of inputting information), let the user choose one of the
options (function inputData
, validation loop included). The function serves as an
information input menu for users.
(Pham Phu Duy Khuong)
1. (18 February) Proposing possible strategies for the assignment.
2. (27 February) After having finished inputting information, let the user choose to retrieve
1 of these options: customer, product in stock, transaction and exit (function
displayMenu
, validation loop included). The function serves as a menu for retrieving
any information from the data.
ASSIGNMENT PROGRESS REPORT
6
3. (4 March) Comparison between processing date and starting date (function
compareDate
). If the variable processDateis “smaller” than startDate
, replace
processDatewith startDate
.
4. (28 March) Complete subtask 1 (function doTask1
). In order to search for customers
whose number of transactions and value are the highest, the parameters in function
doTask1 must include transaction information, customer ID as well as the limit for each
requirement. The logic is as follows:
-
Find customers with the highest number of transactions: As first, sort out every
customer and transaction by comparing customers.idand
transactions.custID
. This was done with nested for loops (using twice).
The inner for loop counts the number of transaction of each customer while the
outer one increases based on how many customers are there from the input data.
Inside the loop, a conditional function checks whether the countervariable is
larger than maxTransaction
. If it is the case, maxTransactionwill have
its value changed to counter
. In addition, the integer array indexwill change
correspondingly to the condition.
-
Find customers with the highest value: Overall, the code is fairly similar to the
aforementioned process. The only difference is that the loop will sort out any
customer who does not satisfy both conditions. This part is possible because of
the data from array indexin the previous loop.
-
After having finished the requirements, function customerDataBaseis used
to display subtask 1.
ASSIGNMENT PROGRESS REPORT
7
5. (28 March) Complete subtask 2 (function doTask2
).
This task uses similar technique from doTask1to search for the most valued product.
(Quach Duc Khuong)
1. (18 February) Proposing possible strategies for the assignment.
2. (28 March) Complete subtask 3 (function doTask3
).
This task is similar to doTask2
. Task 3 and task 4 were done by both Duc Khuong and
Duy Khuong.
3. (28 March) Complete subtask 4 (function doTask4
).
This task is similar to doTask1
. The only difference is the output of the function, which
displays city names instead of customer information. Because of several similarities
between task 1 and task 4, Duc Khuong and Duy Khuong did both together.
4. (28 March) Complete subtask 5 (function doTask5
)
-
Similar to the array above, transaction types are written in array of strings instead
of enumeration. For each transaction, if its type is similar to a chosen type, the
corresponding element in the array sameTypewill have the same structure data.
-
After that, the next for loop will sort out the elements in the array in ascending
order and print out the result using function transactionDataBase
.
ASSIGNMENT PROGRESS REPORT
8
(The whole team)
Main function:
-
As planned in the first week, the main function would be a combination of switch case,
for and while loop. Although the deadline for function completion was set to be 15 March
at first, we went idle for 2 weeks in March. As a result, it was put off until 28 March.
-
In the first half of April, which was a 2-week off from school, we completed the main
function. The only obstacle we faced was case 3 for inputting transaction data. It was
resolved as follows:
+ The input data is restrained by conditional operator. If the condition returns True,
we will check for transaction date and starting date using function
compareDate(done by Pham Phu Duy Khuong).
+ If a customer chooses several different products, the initial quantity of the each
product is reduced until they are out of stock (done by Quach Duc Khuong).
-
After having finished the switch case statement, the last thing to do is to display desired
data from user (done by Quach Duc Khuong) and write down functions for 5 subtasks.
Results
Almost every task was finished.
Noticeable flaws: We did not check for identical ID numbers and phone numbers while inputting
data. As a result, conflicts will occur if user input for IDs happens to be the same with preceding
ones.
ASSIGNMENT PROGRESS REPORT
9
Full source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_DATA 10
typedef struct {
int day;
int month;
int year;
} Date;
typedef struct{
char id[9];
char name[100];
char phone[13];
char address[200];
char city[100];
Date startDate;
} Customer;
typedef struct {
char id[9];
char name[100];
char model[100];
unsigned int quantity;
float unitPrice;
} Product;
typedef struct {
char id[9];
char custID[9];
char type[7];
float value;
Product prod;
Date processDate;
int quantity;
} Transaction;
ASSIGNMENT PROGRESS REPORT
Customer getCustomerInformation();
Product getProdDetailInformation();
Transaction createTransaction(Customer customer, Product prod);
int isArray(char str[]);
int isName(char str[]);
int isLeapYear(int year);
int isValidDate(Date inDate);
int isValid(char str[], int strLength);
int inputNumber(int limit);
int inputData();
int displayMenu();
Date compareDate(Date, Date);
void customerDataBase(Customer customers[], int size);
void productDataBase(Product products[], int size);
void transactionDataBase(Transaction transactions[], int size);
//void displayCustomerMenu(Customer);
//void displayProdMenu(Product);
//void displayTransactionMenu(Transaction);
void displayProdDetail(Product);
//void displayCustomerInformation();
//void displayTransactionInformation();
void doTask1(Transaction transactions[], int transNum, Customer
customers[], int custNum);
void doTask2(Transaction transactions[], int transNum);
void doTask3(Transaction transactions[], int transNum);
void doTask4(Transaction transactions[], int transNum, Customer
customers[], int custNum);
void doTask5(Transaction transactions[], int transNum);
int main()
{
Customer customers[MAX_DATA];
Product products[MAX_DATA];
Transaction transactions[MAX_DATA];
int isExit = 0;
int custNum = 0;
10
ASSIGNMENT PROGRESS REPORT
11
int prodNum = 0;
int transNum = 0;
// Menu for inputing data
while (!isExit) {
int userChoice = inputData();
switch (userChoice) {
case 1:
if (custNum < MAX_DATA)
customers[custNum++] = getCustomerInformation();
break;
case 2:
if (prodNum < MAX_DATA)
products[prodNum++] = getProdDetailInformation();
break;
case 3:
if (transNum < MAX_DATA && custNum > 0 && prodNum > 0) {
printf("Choose customer and product for
transaction\n");
for (int i = 0; i < custNum; i++)
printf("%d.%s\t", i + 1, customers[i].name);
printf("\n");
for (int i = 0; i < prodNum; i++)
printf("%d.%s:%d left\t", i + 1, products[i].name,
products[i].quantity);
printf("\n");
printf("***Choose customer\n");
int custChoice = inputNumber(custNum) - 1;
printf("***Choose product\n");
int prodChoice = inputNumber(prodNum) - 1;
// check for first transaction of a customer
int firstTime = 1;
for (int i = 0; i < transNum; i++) {
if (strcmp(transactions[i].custID,
customers[custChoice].id) == 0) {
firstTime = 0;
break;
}
}
if (products[prodChoice].quantity == 0) {
printf("Out of stock\n");
break;
}
ASSIGNMENT PROGRESS REPORT
12
transactions[transNum] =
createTransaction(customers[custChoice], products[prodChoice]);
if (firstTime) {
printf("Congratulation!!! Your first transaction
has been formed!!! Welcome to business!!!\n");
customers[custChoice].startDate =
transactions[transNum].processDate;
}
customers[custChoice].startDate =
compareDate(customers[custChoice].startDate,
transactions[transNum].processDate);
if (strcmp(transactions[transNum].type, "whole") == 0)
{
// buy all products in stock
transactions[transNum].quantity =
products[prodChoice].quantity;
} else if (strcmp(transactions[transNum].type,
"retail") == 0) {
// buy 1 product
transactions[transNum].quantity = 1;
} else if (strcmp(transactions[transNum].type,
"other") == 0) {
// buy a specific number of products
printf("***Number of products to buy\n");
transactions[transNum].quantity =
inputNumber(products[prodChoice].quantity);
}
transactions[transNum].prod.quantity =
transactions[transNum].quantity;
transactions[transNum].value =
transactions[transNum].quantity * products[prodChoice].unitPrice;
products[prodChoice].quantity -=
transactions[transNum].quantity;
transNum++;
} else {
if (custNum == 0 && prodNum == 0)
printf("We don't have anything to do!!! We need to
start-up !!!\n");
else if (custNum == 0)
printf("Don't have any customer!!! Go out and find
someone !!!\n");
ASSIGNMENT PROGRESS REPORT
13
else if (prodNum == 0)
printf("Don't have any product!!! Go out and buy
something !!!\n");
}
break;
case 4:
isExit = 1;
printf("SAVED!!!\n");
break;
default:
break;
}
}
// Menu for displaying data
isExit = 0;
while (!isExit) {
int userChoice = displayMenu();
switch (userChoice) {
case 1:
//displayCustomerMenu();
customerDataBase(customers, custNum);
break;
case 2:
//displayProdMenu();
productDataBase(products, prodNum);
break;
case 3:
//displayTransactionMenu();
transactionDataBase(transactions, transNum);
break;
case 4:
isExit = 1;
break;
default:
break;
}
}
doTask1(transactions, transNum, customers, custNum);
doTask2(transactions, transNum);
doTask3(transactions, transNum);
ASSIGNMENT PROGRESS REPORT
doTask4(transactions, transNum, customers, custNum);
doTask5(transactions, transNum);
return 0;
}
Customer getCustomerInformation() {
Customer customer;
getchar();
printf("Input customer information\n");
do {
printf("1/ Input customer ID: ");
gets(customer.id);
} while (!isValid(customer.id, 8));
do {
printf("2/ Input customer name: ");
gets(customer.name);
} while (!isName(customer.name));
do {
printf("3/ Input customer contact phone: ");
gets(customer.phone);
} while (!isValid(customer.phone, 12));
do {
printf("4/ Input customer address: ");
gets(customer.address);
} while (!isArray(customer.address));
do {
printf("5/ Input customer city: ");
gets(customer.city);
} while (!isName(customer.city));
customer.startDate.day = 0;
customer.startDate.month = 0;
customer.startDate.year = 0;
return customer;
}
Product getProdDetailInformation() {
Product prod;
getchar();
printf("Input product information\n");
do {
printf("1/ Input product ID: ");
gets(prod.id);
14
ASSIGNMENT PROGRESS REPORT
15
} while (!isValid(prod.id, 8));
do {
printf("2/ Input product name: ");
gets(prod.name);
} while (!isName(prod.name));
do {
printf("3/ Input product model: ");
gets(prod.model);
} while (!isArray(prod.model));
printf("4/ Input product quantity: ");
scanf("%d", &prod.quantity);
printf("5/ Input product unit price: ");
scanf("%f", &prod.unitPrice);
return prod;
}
Transaction createTransaction(Customer customer, Product prod) {
Transaction transaction;
char type[3][7] = {"whole", "retail", "other"};
int choice = -1;
printf("Input transaction detail\n");
getchar();
do {
printf("1/ Input transaction ID: ");
gets(transaction.id);
} while (!isValid(transaction.id, 8));
strcpy(transaction.custID, customer.id);
do {
printf("2/ Input transaction processing date in form of
dd/mm/yyyy: ");
scanf("%d/%d/%d", &transaction.processDate.day,
&transaction.processDate.month, &transaction.processDate.year);
} while (!isValidDate(transaction.processDate));
printf("3/ Choose the type of transaction\n1. Whole\n2. Retail\n3.
Other\n");
choice = inputNumber(3);
strcpy(transaction.type, type[choice - 1]);
transaction.prod = prod;
//
printf("%d/%d/%d\n", transaction.processDate.day,
transaction.processDate.month, transaction.processDate.year);
return transaction;
}
ASSIGNMENT PROGRESS REPORT
16
int isName(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i]) != 0 || isspace(str[i]) != 0) continue;
else return 0;
}
return 1;
}
int isArray(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i]) != 0 || isspace(str[i]) != 0 ||
isdigit(str[i]) != 0 || str[i] == ',') continue;
else return 0;
}
return 1;
}
int isLeapYear(int year) {
if (year % 4 != 0)
return 0;
else if (year % 100 != 0)
return 1;
else if (year % 400 != 0)
return 0;
else
return 1;
}
int isValidDate(Date inDate) {
if (inDate.day < 0 || inDate.month < 0 || inDate.year < 0 ||
inDate.day > 31 || inDate.month > 12)
return 0;
if (inDate.month == 2) {
if (isLeapYear(inDate.year)) {
if (inDate.day > 29)
return 0;
} else {
if (inDate.day > 28)
return 0;
}
}
ASSIGNMENT PROGRESS REPORT
17
if (inDate.month == 1 || inDate.month == 3 || inDate.month == 5 ||
inDate.month == 7 || inDate.month == 8 || inDate.month == 10 ||
inDate.month == 12) {
if (inDate.day > 31)
return 0;
} else {
if (inDate.day > 30)
return 0;
}
return 1;
}
int isValid(char str[], int strLength) {
int inStrLength = strlen(str);
if (inStrLength != strLength)
return 0;
for (int i = 0; i < strLength; i++) {
int convert = (int) str[i];
if (convert > 57 || convert < 48)
return 0;
}
return 1;
}
int inputNumber(int limit) {
int userChoice = -1;
while (1) {
printf("Please select: ");
int flag = scanf("%d", &userChoice);
if (flag == EOF) {
while (fgetc(stdin) != '\n') {}
continue;
}
else if (flag == 0) {
while (fgetc(stdin) != '\n')
continue;
}
else if (userChoice < 1 || userChoice > limit) {
while (fgetc(stdin) != '\n')
continue;
}
else
ASSIGNMENT PROGRESS REPORT
18
break;
}
return userChoice;
}
int inputData() {
printf("**************************************************\n");
printf("Select information you want to input\n");
printf("1. Customer\n");
printf("2. Product\n");
printf("3. Transaction\n");
printf("4. Save\n");
int userChoice = -1;
while (1) {
printf("Please select: ");
int flag = scanf("%d", &userChoice);
if (flag == EOF) {
while (fgetc(stdin) != '\n') {}
continue;
}
else if (flag == 0) {
while (fgetc(stdin) != '\n')
continue;
}
else if (userChoice < 1 || userChoice > 4) {
while (fgetc(stdin) != '\n')
continue;
}
else
break;
}
printf("**************************************************\n");
return userChoice;
}
int displayMenu() {
printf("**************************************************\n");
printf("Select information you want to retrieve\n");
printf("1. Customer\n");
printf("2. Product in stock\n");
printf("3. Transaction\n");
printf("4. Exit\n");
ASSIGNMENT PROGRESS REPORT
19
int userChoice = -1;
while (1) {
printf("Please select: ");
int flag = scanf("%d", &userChoice);
if (flag == EOF) {
while (fgetc(stdin) != '\n') {}
continue;
}
else if (flag == 0) {
while (fgetc(stdin) != '\n')
continue;printf("*****Task5*****\n");
}
else if (userChoice < 1 || userChoice > 4) {
while (fgetc(stdin) != '\n')
continue;
}
else
break;
}
printf("**************************************************\n");
return userChoice;
}
Date compareDate(Date custDate, Date transDate) {
if (custDate.year < transDate.year) {
return custDate;
} else if (custDate.year == transDate.year) {
if (custDate.month < transDate.month)
return custDate;
else if (custDate.month == transDate.month) {
if (custDate.day < transDate.day)
return custDate;
else
return transDate;
} else
return transDate;
} else
return transDate;
}
void displayProdDetail(Product prod) {
printf("Product Details List\n");
ASSIGNMENT PROGRESS REPORT
printf("Product
printf("Product
printf("Product
printf("Product
printf("Product
20
ID: %s\n", prod.id);
name: %s\n", prod.name);
model: %s\n", prod.model);
quantity: %d\n", prod.quantity);
unit price: %.2f\n", prod.unitPrice);
}
void customerDataBase(Customer customers[], int size) {
for (int i = 0; i < size; i++) {
printf("%d/ %s\t%s\t%s\t%s\t%s\t%d/%d/%d\n", i + 1,
customers[i].id, customers[i].name, customers[i].phone,
customers[i].address, customers[i].city,
customers[i].startDate.day,
customers[i].startDate.month, customers[i].startDate.year);
}
}
void productDataBase(Product products[], int size) {
for (int i = 0; i < size; i++) {
printf("%d/ %s\t%s\t%s\t%d in stock\t%.2f\n", i + 1,
products[i].id, products[i].name, products[i].model,
products[i].quantity, products[i].unitPrice);
}
}
void transactionDataBase(Transaction transactions[], int size) {
for (int i = 0; i < size; i++) {
printf("%d/ %s\t%s\t%s\t%s\t%.2f\t%d/%d/%d\n", i + 1,
transactions[i].id, transactions[i].custID, transactions[i].prod.name,
transactions[i].type, transactions[i].value,
transactions[i].processDate.day,
transactions[i].processDate.month, transactions[i].processDate.year);
displayProdDetail(transactions[i].prod);
printf("\n");
}
}
void doTask1(Transaction transactions[], int transNum, Customer
customers[], int custNum) {
int maxTransaction = -1;
int index[MAX_DATA];
int indexSize = -1;