[Lập trình C] Bài tập lập trình C 4

Posted on January 18th, 2021

Tiếp tục series để ôn tập và rèn luyện kỹ năng lập trình, bài tập lập trình C 4 giới thiệu với bạn những bài tập lập trình C cơ bản giúp bạn ôn tập toàn bộ kiến thức đã học.

Chú ý: những bài tập sau đây sẽ liên quan đến nhau nên lời giải sẽ đặt chung ở dưới cùng bài viết.

Bài 1

Tạo struct Person như sau:

  • Tên: char name[25]
  • Quốc tịnh: char nationality[25]
  • Năm sinh: int birth_year
  • Tài sản ròng: float net_worth

Bài 2

Tạo menu chương trình:

+------------------------------------------------------------------+
|             BILLIONAIRES PROFILE MANAGEMENT PROGRAM              |
+------------------------------------------------------------------+
|1. Input |2. Sort |3. Analyze |4. Find |5. Save |6. Open |7. Exit |
+------------------------------------------------------------------+

Chú ý:

  • Menu hiển thị khi chương trình bắt đầu
  • Sau mỗi lựa chọn của user kết thúc, hỏi lại như sau:
Do you want to continue?
- Yes, I do. (press 'y' or 'Y')
- No, I don't. (press 'n or 'N')
- Please clear the screen ! (press 'c' or 'C') 
Your choice:

Nếu user nhấn:

  • 'y' hoặc 'Y' thì lặp lại menu
  • 'n' hoặc 'N' thì thoát chương trình
  • 'c' hoặc 'C' thì xóa màn hình

Yêu cầu user nhập lại nếu lựa chọn của user là không hợp lệ.

Bài 3

Khi user chọn option 1. Input ở menu thì làm như sau:

  • Yêu cầu nhập vào tổng số lượng Person
  • Nhập vào thông tin của mỗi Person
  • Kiểm tra tính đúng đắn của dữ liệu nhập vào theo yêu cầu sau:
    • Tuổi: age > 30, ngược lại in ra: Person age must be greater than 30
    • Tài sản ròng: 1 <= net_worth <= 100, ngược lại in ra: Networth must be between 1(billion $) and 100(billion $)

Ví dụ (chỗ ghi đậm là phần nhập vào của user):

Please input person[1]:

  • Name: Bill Gates
  • Nationality: United States
  • Birth Year: 1995
  • Net Worth: 90

Chú ý: phần này phải được viết trong một hàm với tham số đầu vào phải là con trỏ vào struct Person.

Bài 4

Sắp xếp persons theo thứ tự giảm dần của net_worth và hiển thị danh sách.

Khi user chọn option 2. Sort ở menu thì làm như sau:

  • Sắp xếp các persons theo thứ tự net_worth giảm dần
  • Hiển thị thông tin chi tiết của mỗi Person sau khi sắp xếp, ví dụ:
+------------------------------------------------------------------+
|Person Name    |Nationality    |Birth Year |Net Worth (billion $) |
+------------------------------------------------------------------+
|Bill Gates     |United States  |1955       |90.00                 |
+------------------------------------------------------------------+
|Amacio Ortega  |Spain          |1936       |76.50                 |
+------------------------------------------------------------------+
|Warren Buffet  |United States  |1930       |66.40                 |
+------------------------------------------------------------------+

Chú ý: phần này phải được viết trong một hàm với tham số đầu vào phải là con trỏ vào struct Person.

Bài 5

Phân tích dữ liệu theo quốc tịch.

Khi user chọn option 3. Analyze ở menu thì làm như sau:

  • Tính xem có bao nhiêu đến từ một quốc gia cụ thể
  • Hiển thị thống kê, ví dụ:
Statistics Result:
+ There are 2 person(s) from 'United States'
+ There are 1 person(s) from 'Spain'

Chú ý: phần này phải được viết trong một hàm với tham số đầu vào phải là con trỏ vào struct Person.

Bài 6

Tìm person theo quốc tịnh và tài sản ròng.

Khi user chọn option 4. Find ở menu thì làm như sau:

  • Yêu cầu user nhập vào quốc tịnh và một giá trị min
  • Hiển thị thông tin của tất cả các person có quốc tịch đã nhập vào với giá trị net_worth lớn hơn giá trị min.

Ví dụ:

Nationality: United States
Min Net worth (billion $): 60

Search Results:
+------------------------------------------------------------------+
|Person Name    |Nationality    |Birth Year |Net Worth (billion $) |
+------------------------------------------------------------------+
|Bill Gates     |United States  |1955       |90.00                 |
+------------------------------------------------------------------+
|Warren Buffet  |United States  |1930       |66.40                 |
+------------------------------------------------------------------+
2 person(s) found.

Chú ý: phần này phải được viết trong một hàm với tham số đầu vào phải là con trỏ vào struct Person.

Bài 7

Lưu ra file.

Khi user chọn option 5. Save ở menu thì làm như sau:

  • Yêu cầu nhập vào file name
  • Tạo file ở chế độ binary
  • Nếu không thể mở được file thì thông báo lỗi và kết thúc hàm
  • Ghi data của list các person ra file
  • Thông báo dữ liệu đã được ghi thành công
  • Đóng file

Ví dụ:

Your choice: 5
Save the list into file:
File name: C:\Users\LamPV\Downloads\person.dat
Data successfully saved into file!

Chú ý: phần này phải được viết trong một hàm với tham số đầu vào phải là con trỏ vào struct Person.

Bài 8

Mở file và hiển thị danh sách.

Khi user chọn option 6. Open ở menu thì làm như sau:

  • Yêu cầu nhập vào file name
  • Mở file ở chế độ binary
  • Nếu không thể mở được file thì thông báo lỗi và kết thúc hàm
  • Đọc dữ liệu từ file vào một mảng rồi hiển thị danh sách ra màn hình
  • Đóng file

Chú ý: user phải nhập vào danh sách person trước khi làm những option khác, trừ trường hợp Clear screen hoặc Exit.

Ví dụ:

Your choice: 6
Open file and display the list:
File name: C:\Users\LamPV\Downloads\person.dat

+------------------------------------------------------------------+
|Person Name    |Nationality    |Birth Year |Net Worth (billion $) |
+------------------------------------------------------------------+
|Bill Gates     |United States  |1955       |90.00                 |
+------------------------------------------------------------------+
|Amancio Ortega |Spain          |1936       |76.50                 |
+------------------------------------------------------------------+
|Warren Buffet  |United States  |1930       |66.40                 |
+------------------------------------------------------------------+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
	char name[25];
	char nationality[25];
	int birth_year;
	float net_worth;
} Person;

int N = 0;

// Input informations of all people
void inputData(Person *p)
{
	// Ask to enter the total number of persons
	int scanfValid;
	do {
		printf("\nEnter the total number of Persons: ");
		scanfValid = scanf("%d", &N);
		if (!scanfValid) {
			fflush(stdin);
		}
	} while(!scanfValid || N <= 0);

	// Realloc the pointer to store store N person
	p = (Person*)realloc(p, N*sizeof(Person));
	if (!p) {
		printf("Not enough memory");
		return;
	}

	// Ask to input all informations for each person
	int i;
	for(i = 0; i < N; i++) {
		printf("Please input person[%d]:\n", i+1);
		fflush(stdin);
		printf("Name: ");
		gets(p[i].name);
		printf("Nationality: ");
		gets(p[i].nationality);

		while(1) {
			fflush(stdin);
			printf("Birth Year: ");
			scanf("%d", &p[i].birth_year);

			if (p[i].birth_year <= 0) {
				continue;
			}

			// Assume that current year is 2021
			int age = 2021 - p[i].birth_year;;
			if (age <= 30) {
				printf("Person age must be greater than 30\n");
				continue;
			}

			break;
		}

		while(1) {
			fflush(stdin);
			printf("Net Worth: ");
			scanf("%f", &p[i].net_worth);

			if (p[i].net_worth < 1 || p[i].net_worth > 100) {
				printf("Networth must be between 1(billion $) and 100(billion $)\n");
				continue;
			}

			break;
		}
	}
}

// Display list
void displayTable(Person *p)
{
	int i;
	printf("\n");
	printf("+------------------------------------------------------------------+\n");
	printf("|%-15s|%-15s|%-11s|%-22s|\n", "Person Name", "Nationality", "Birth Year", "Net Worth (billion $)");
	printf("+------------------------------------------------------------------+\n");
	for(i = 0; i < N; i++) {
		printf("|%-15s|%-15s|%-11d|%-22.2f|\n", p[i].name, p[i].nationality, p[i].birth_year, p[i].net_worth);
		printf("+------------------------------------------------------------------+\n");
	}
}

// Sort persons by net_worth desending and display list
void sortData(Person *p)
{
	int i, j;
	for(i = 0; i < N - 1; i++) {
		for(j = i + 1; j < N; j++) {
			if(p[i].net_worth < p[j].net_worth) {
				Person tmp = p[i];
				p[i] = p[j];
				p[j] = tmp;
			}
		}
	}

	displayTable(p);
}

// Calculate how many persons are there from a specific nation
void analyzeData(Person *p)
{
	printf("Statistics Result:\n");

	int i;
	for(i = 0; i < N; i++) {
		// check whether a nationality is printed
		int j, isPrinted = 0;
		for(j = 0; j < i; j++) {
			if (strcmp(p[i].nationality, p[j].nationality) == 0) {
				isPrinted = 1;
				break;
			}
		}

		// if the nationality is printed, then move to the next one
		if (isPrinted) {
			continue;
		}

		// otherwise, count how many persons are there from the nationality
		int cnt = 0;
		for(j = i; j < N; j++) {
			if (strcmp(p[i].nationality, p[j].nationality) == 0) {
				cnt++;
			}
		}

		// print statistics
		printf("+ There are %d person(s) from '%s'.\n", cnt, p[i].nationality);
	}
}

// Find person by nationality and min networth
void findData(Person *p)
{
	char nationality[25];
	float net_worth;

	fflush(stdin);
	printf("Nationality: ");
	gets(nationality);
	printf("Min Net worth (billion $): ");
	scanf("%f", &net_worth);

	int i, cnt = 0;
	printf("\nSearch Results:\n");
	for(i = 0; i < N; i++) {
		if(strcmp(p[i].nationality, nationality) == 0 && p[i].net_worth > net_worth) {
			cnt++;
		}
	}
	if (cnt > 0) {
		printf("+------------------------------------------------------------------+\n");
		printf("|%-15s|%-15s|%-11s|%-22s|\n", "Person Name", "Nationality", "Birth Year", "Net Worth (billion $)");
		printf("+------------------------------------------------------------------+");
		for(i = 0; i < N; i++) {
			if (strcmp(p[i].nationality, nationality) == 0 && p[i].net_worth > net_worth) {
				printf("\n");
				printf("|%-15s|%-15s|%-11d|%-22.2f|\n", p[i].name, p[i].nationality, p[i].birth_year, p[i].net_worth);
				printf("+------------------------------------------------------------------+");
			}
		}
	}
	printf("\n%d person(s) found.\n", cnt);
}

// save list persons to file
void saveToFile(Person *p)
{
	char fileName[256];
	fflush(stdin);
	printf("Save the list into file:\n");
	printf("File name: ");
	gets(fileName);

	FILE *fp = fopen(fileName, "wb");
	if(!fp) {
		printf("ERROR: cannot open file to write!\n");
	} else {
		int i;
		for(i = 0; i < N; i++) {
			fwrite(p + i, sizeof(Person), 1, fp);
		}
		printf("Data successfully saved into file!\n");
		fclose(fp);
	}
}

// read list persons from a file
void readFromFile()
{
	char fileName[256];
	fflush(stdin);
	printf("Open file and display the list:\n");
	printf("File name: ");
	gets(fileName);

	FILE *fp = fopen(fileName, "rb");
	if(!fp) {
		printf("ERROR: cannot open file to read!\n");
	} else {
		int i;
		Person *p = (Person*) malloc(N*sizeof(Person));
		for(i = 0; i < N; i++) {
			fread(p + i, sizeof(Person), 1, fp);
		}
		displayTable(p);
		free(p);
		fclose(fp);
	}
}

int main()
{
	// Init a pointer to point to the first item of array
	Person *ps = (Person*) malloc(1*sizeof(Person));

	while(1) {
		// Show menu
		printf("+------------------------------------------------------------------+\n");
		printf("|             BILLIONAIRES PROFILE MANAGEMENT PROGRAM              |\n");
		printf("+------------------------------------------------------------------+\n");
		printf("|1. Input |2. Sort |3. Analyze |4. Find |5. Save |6. Open |7. Exit |\n");
		printf("+------------------------------------------------------------------+\n");

		// Ask to select a menu item
		int menu, scanfValid;
		do {
			printf("Your choice: ");
			scanfValid = scanf("%d", &menu);
			if (!scanfValid) {
				fflush(stdin);
			}
		} while(!scanfValid || menu < 1 || menu > 7);

		// Do user's request
		switch(menu) {
			case 1:
				inputData(ps);
				break;
			case 2:
				sortData(ps);
				break;
			case 3:
				analyzeData(ps);
				break;
			case 4:
				findData(ps);
				break;
			case 5:
				saveToFile(ps);
				break;
			case 6:
				readFromFile();
				break;
			default:
				return 0;
		}

		// Ask to continue or exit
		printf("\nDo you want to continue?\n");
		printf("- Yes, I do. (press 'y', 'Y')\n");
		printf("- No, I don't. (press 'n', 'N')\n");
		printf("- Please clear the screen ! (press 'c', 'C')\n");

		char ch;
		do {
			fflush(stdin);
			printf("Your choice: ");
			scanf("%c", &ch);
		} while(ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' && ch != 'c' && ch != 'C');

		if (ch == 'c' || ch == 'C') system("cls");
		else if (ch == 'n' || ch == 'N') return 0;
	}

	free(ps);
	return 0;
}