課題1:書籍販売データの処理
以下のプログラムは、書籍の販売データを管理し、販売数でランキングを表示し、総売上額を計算します。
#include <stdio.h>
#define MAX_BOOKS 10
// 書籍情報を格納する構造体
typedef struct {
char ISBN[20]; // ISBNコード
char title[80]; // 書籍タイトル
char author[80]; // 著者名
double price; // 単価
int quantity; // 販売数
} Book;
// 関数のプロトタイプ宣言
void display_books(Book books[], int count);
void sort_by_sales(Book books[], int count);
double calculate_total_sales(Book books[], int count);
int main() {
Book catalog[MAX_BOOKS] = {
{"978-4-06-523406-9", "海辺のカフカ", "村上春樹", 2100, 125},
{"978-4-16-390610-4", "1Q84 BOOK1", "村上春樹", 1800, 98},
{"978-4-16-711325-7", "ノルウェイの森", "村上春樹", 1500, 145},
{"978-4-06-293425-2", "かがみの孤城", "辻村深月", 1400, 87},
{"978-4-06-521866-1", "きのう見た夢", "伊坂幸太郎", 1600, 76},
{"978-4-06-518804-7", "羊をめぐる冒険", "村上春樹", 1700, 65},
{"978-4-06-522644-9", "国境", "辻村深月", 1300, 54},
{"978-4-06-522645-6", "ミステリと言う剧薬", "辻村深月", 1500, 43},
{"978-4-06-522646-3", "夜のピクニック", "乙一", 1400, 38}
};
printf("書籍販売ランキング(販売数順):
");
sort_by_sales(catalog, MAX_BOOKS);
display_books(catalog, MAX_BOOKS);
printf("
総売上額: %.2f円
", calculate_total_sales(catalog, MAX_BOOKS));
return 0;
}
// 書籍リストを表示する関数
void display_books(Book books[], int count) {
printf("%-20s %-30s %-20s %-10s %-10s
", "ISBN", "タイトル", "著者", "単価", "販売数");
for (int i = 0; i < count; ++i) {
printf("%-20s %-30s %-20s %-10.0f %-10d
",
books[i].ISBN, books[i].title, books[i].author, books[i].price, books[i].quantity);
}
}
// 販売数で書籍を降順にソートする関数(バブルソート)
void sort_by_sales(Book books[], int count) {
Book temp;
for (int i = 0; i < count - 1; ++i) {
for (int j = 0; j < count - i - 1; ++j) {
if (books[j].quantity < books[j + 1].quantity) {
temp = books[j];
books[j] = books[j + 1];
books[j + 1] = temp;
}
}
}
}
// 総売上額を計算する関数
double calculate_total_sales(Book books[], int count) {
double total = 0.0;
for (int i = 0; i < count; ++i) {
total += books[i].price * books[i].quantity;
}
return total;
}
課題2:日付の操作と比較
以下のプログラムは、日付を入力し、その日が年の何日目かを計算し、また2つの日付を比較します。
#include <stdio.h>
// 日付情報を格納する構造体
typedef struct {
int year; // 年
int month; // 月
int day; // 日
} Date;
// 関数のプロトタイプ宣言
void input_date(Date *date_ptr); // 日付を入力する
int get_day_of_year(Date date); // 年間通算日を返す
int compare_two_dates(Date date1, Date date2); // 2つの日付を比較する
int main() {
Date test_date;
int result;
printf("テスト1: 日付を入力し、年間通算日を表示します。
");
for (int i = 0; i < 3; ++i) {
input_date(&test_date);
printf("%d年%d月%d日は、その年の第%d日目です。
",
test_date.year, test_date.month, test_date.day, get_day_of_year(test_date));
}
printf("
テスト2: 2人の誕生日を比較します。
");
Date person1_birth, person2_birth;
for (int i = 0; i < 3; ++i) {
printf("1人目の誕生日を入力してください(例: 1990-05-15):
");
input_date(&person1_birth);
printf("2人目の誕生日を入力してください(例: 1990-05-15):
");
input_date(&person2_birth);
result = compare_two_dates(person1_birth, person2_birth);
if (result == 0) {
printf("2人は同じ日に生まれました。
");
} else if (result < 0) {
printf("1人目の方が年上です。
");
} else {
printf("1人目の方が年下です。
");
}
}
return 0;
}
// ユーザーから日付を入力する関数
void input_date(Date *date_ptr) {
printf("日付を入力してください(例: 2023-12-25): ");
scanf("%d-%d-%d", &date_ptr->year, &date_ptr->month, &date_ptr->day);
}
// うるう年かどうかを判定するヘルパー関数
int is_leap_year(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 年間通算日を計算する関数
int get_day_of_year(Date date) {
int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int total_days = date.day;
if (is_leap_year(date.year)) {
days_in_month[1] = 29; // 2月の日数を29日に変更
}
for (int i = 0; i < date.month - 1; ++i) {
total_days += days_in_month[i];
}
return total_days;
}
// 2つの日付を比較する関数(別のロジック:通算日数に変換して比較)
int compare_two_dates(Date date1, Date date2) {
// 2つの日付を基準日からの通算日数に変換
int total_days1 = date1.year * 365 + date1.day;
int total_days2 = date2.year * 365 + date2.day;
// うるう年を考慮
for (int y = 1; y < date1.year; ++y) {
if (is_leap_year(y)) total_days1++;
}
for (int y = 1; y < date2.year; ++y) {
if (is_leap_year(y)) total_days2++;
}
// 月の通算日を加算
int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (is_leap_year(date1.year)) days_in_month[1] = 29;
for (int m = 0; m < date1.month - 1; ++m) total_days1 += days_in_month[m];
if (is_leap_year(date2.year)) days_in_month[1] = 29;
for (int m = 0; m < date2.month - 1; ++m) total_days2 += days_in_month[m];
if (total_days1 < total_days2) return -1;
if (total_days1 > total_days2) return 1;
return 0;
}
課題3:ユーザーアカウントの管理
以下のプログラムは、ユーザーアカウントの情報を管理し、パスワードをマスクして表示します。
#include <stdio.h>
#include <string.h>
// ユーザー種別を定義する列挙型
enum UserType { admin, student, teacher };
// アカウント情報を格納する構造体
typedef struct {
char username[20]; // ユーザー名
char password[20]; // パスワード
enum UserType type; // アカウント種別
} Account;
// 関数のプロトタイプ宣言
void display_accounts(Account accounts[], int count); // アカウント情報を表示する
int main() {
Account user_db[] = {
{"user001", "pass123", student},
{"user002", "secure456", student},
{"user003", "qwerty789", student},
{"admin01", "admin2023", admin},
{"teacherA", "edu@2023", teacher},
{"user004", "letmein", student}
};
int num_accounts = sizeof(user_db) / sizeof(Account);
display_accounts(user_db, num_accounts);
return 0;
}
// アカウント情報を表示する関数(パスワードはマスクされる)
void display_accounts(Account accounts[], int count) {
printf("%-12s %-15s %-10s
", "ユーザー名", "パスワード", "種別");
for (int i = 0; i < count; ++i) {
printf("%-12s ", accounts[i].username);
// パスワードをアスタリスクでマスク
int pwd_len = strlen(accounts[i].password);
for (int j = 0; j < pwd_len; ++j) {
printf("*");
}
// 種別を表示
switch (accounts[i].type) {
case admin:
printf(" admin");
break;
case student:
printf(" student");
break;
case teacher:
printf(" teacher");
break;
default:
printf(" 不明");
break;
}
printf("
");
}
}
課題4:連絡先リストの管理
以下のプログラムは、連絡先リストを管理し、特定の連絡先を緊急連絡先としてマークし、氏名のアルファベット順(緊急連絡先を優先)で表示します。
#include <stdio.h>
#include <string.h>
// 連絡先情報を格納する構造体
typedef struct {
char name[20]; // 氏名
char phone[12]; // 電話番号
int is_vip; // 緊急連絡先フラグ(1: はい, 0: いいえ)
} Contact;
// 関数のプロトタイプ宣言
void mark_as_vip(Contact contacts[], int count, char name[]); // 緊急連絡先を設定
void display_contacts(Contact contacts[], int count); // 連絡先を表示
void display_sorted(Contact contacts[], int count); // ソートして表示
#define MAX_CONTACTS 10
int main() {
Contact address_book[MAX_CONTACTS] = {
{"田中太郎", "090-1234-5678", 0},
{"佐藤花子", "080-8765-4321", 0},
{"鈴木一郎", "03-5555-1111", 0},
{"高橋美咲", "070-9999-8888", 0},
{"伊藤健太", "090-2222-3333", 0},
{"中村悠", "050-4444-5555", 0},
{"山本さくら", "060-6666-7777", 0},
{"渡辺翔", "090-7777-8888", 0},
{"小林陽菜", "080-9999-0000", 0},
{"加藤健", "03-1111-2222", 0}
};
int vip_count;
char vip_name[20];
printf("元の連絡先リスト:
");
display_contacts(address_book, MAX_CONTACTS);
printf("
設定する緊急連絡先の人数を入力してください: ");
scanf("%d", &vip_count);
printf("%d人の緊急連絡先の氏名を入力してください:
", vip_count);
for (int i = 0; i < vip_count; ++i) {
scanf("%s", vip_name);
mark_as_vip(address_book, MAX_CONTACTS, vip_name);
}
printf("
連絡先リスト(氏名順、緊急連絡先を優先):
");
display_sorted(address_book, MAX_CONTACTS);
return 0;
}
// 指定された氏名の連絡先を緊急連絡先に設定する関数
void mark_as_vip(Contact contacts[], int count, char name[]) {
for (int i = 0; i < count; ++i) {
if (strcmp(contacts[i].name, name) == 0) {
contacts[i].is_vip = 1;
break; // 一致したらループを抜ける
}
}
}
// 連絡先を表示する関数
void display_contacts(Contact contacts[], int count) {
for (int i = 0; i < count; ++i) {
printf("%-10s %-15s", contacts[i].name, contacts[i].phone);
if (contacts[i].is_vip) {
printf(" *");
}
printf("
");
}
}
// 連絡先をソートして表示する関数(選択ソートを使用)
void display_sorted(Contact contacts[], int count) {
Contact sorted_list[MAX_CONTACTS];
// 元の配列をコピー
for (int i = 0; i < count; ++i) {
sorted_list[i] = contacts[i];
}
// 選択ソートでソート
for (int i = 0; i < count - 1; ++i) {
int max_idx = i;
for (int j = i + 1; j < count; ++j) {
// 緊急連絡先を優先
if (sorted_list[j].is_vip > sorted_list[max_idx].is_vip) {
max_idx = j;
}
// 緊急フラグが同じ場合は氏名で比較
else if (sorted_list[j].is_vip == sorted_list[max_idx].is_vip) {
if (strcmp(sorted_list[j].name, sorted_list[max_idx].name) < 0) {
max_idx = j;
}
}
}
// 最大要素を先頭に持ってくる
if (max_idx != i) {
Contact temp = sorted_list[i];
sorted_list[i] = sorted_list[max_idx];
sorted_list[max_idx] = temp;
}
}
display_contacts(sorted_list, count);
}