쇼샤의 금융 전산망 프로세서 2.4Ver.

에센 빌헬름 쇼샤(1).jpg
쇼샤
관련 문서
[ 펼치기 · 접기 ]

설명

쇼샤의 금융 전산망의 11번째 버전이며 현재 만들어진 프로세서 중 가장 최신의 버전이다.
해당 코드는 2025년 11월달 중반에 확립이 된 것으로 추정된다.

  • 본 코드의 제작권은 쇼샤에 있으나, 모두가 사용 가능하게 공개된 코드이다.

코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> 

#define MAX_STOCKS 20 // 최대 주식 종목 수
#define MAX_USERS 100
#define FILE_NAME "stocks.csv"
#define USER_FILE "users.csv"

// 주식 구조체 정의
typedef struct {
    char name[30];
    double price;
    double lastChangeRate; // 추가: 마지막 가격 변동률 (%)
} Stock;

// 사용자 구조체 정의
typedef struct {
    char username[30];
    double balance;           // 보유 자산
    double avgPrice[MAX_STOCKS]; // 평균 매수가
    int quantity[MAX_STOCKS];  // 보유 수량
} User;

// 전역 화폐 변수 및 백업 데이터
char currentCurrency[10] = "€"; // 화폐 문자열 길이를 10으로 늘려 직접 입력 대응
double backupPrices[MAX_STOCKS];
int pricesBackedUp = 0; // 가격 변동 무르기 플래그

// 주식 종목 및 초기 가격 데이터
const char* initial_stock_names[MAX_STOCKS] = {
    "FedEx", "DHL", "Amazon", "UPS", "Coupang",
    "CJ Logistics", "Hanjin", "DSV A/S",
    "Singapore Post", "Yamato Holdings",
    NULL
};

double initial_prices[MAX_STOCKS] = {
    230.5, 45.0, 3400.0, 200.0, 23.5,
    12.3, 15.5, 100.8, 2.4, 17.2,
    0.0
};

// 함수: 초기 주식 데이터 설정
void initializeStocks(Stock stocks[], int* stockCount) {
    *stockCount = 0;
    for (int i = 0; initial_stock_names[i] != NULL && i < MAX_STOCKS; i++) {
        strncpy(stocks[i].name, initial_stock_names[i], sizeof(stocks[i].name) - 1);
        stocks[i].name[sizeof(stocks[i].name) - 1] = '\0';
        stocks[i].price = initial_prices[i];
        stocks[i].lastChangeRate = 0.0; // 초기 변동률 0
        (*stockCount)++;
    }
}

// 함수: 주식 데이터 로드 (파일 읽기)
void loadStockData(Stock stocks[], int* stockCount) {
    FILE* file = fopen(FILE_NAME, "r");
    if (file == NULL) {
        initializeStocks(stocks, stockCount);
        return;
    }
    char line[100];
    *stockCount = 0;
    while (fgets(line, sizeof(line), file) && *stockCount < MAX_STOCKS) {
        int sscanfResult = sscanf(line, "%[^,],%lf,%lf", stocks[*stockCount].name, &stocks[*stockCount].price, &stocks[*stockCount].lastChangeRate);

        if (sscanfResult < 2) continue;
        if (sscanfResult == 2) stocks[*stockCount].lastChangeRate = 0.0;

        (*stockCount)++;
    }
    fclose(file);
}

// 함수: 주식 데이터 저장
void saveStockData(Stock stocks[], int stockCount) {
    FILE* file = fopen(FILE_NAME, "w");
    if (file == NULL) {
        perror("파일 저장 실패");
        return;
    }
    for (int i = 0; i < stockCount; i++) {
        fprintf(file, "%s,%.2f,%.2f\n", stocks[i].name, stocks[i].price, stocks[i].lastChangeRate);
    }
    fclose(file);
}

// 사용자 데이터 로드
void loadUserData(User users[], int* userCount, int stockCount) {
    FILE* file = fopen(USER_FILE, "r");
    if (file == NULL) {
        *userCount = 0;
        return;
    }
    char line[4096];
    if (fgets(line, sizeof(line), file) == NULL) {
        *userCount = 0;
        fclose(file);
        return;
    }
    *userCount = atoi(line);

    for (int i = 0; i < *userCount; i++) {
        if (fgets(line, sizeof(line), file) == NULL)
            break;

        char* token;
        token = strtok(line, ",");
        if (token != NULL) {
            strncpy(users[i].username, token, sizeof(users[i].username) - 1);
            users[i].username[strcspn(users[i].username, "\n")] = '\0';
        }
        else {
            users[i].username[0] = '\0';
        }

        token = strtok(NULL, ",");
        if (token != NULL)
            users[i].balance = atof(token);
        else
            users[i].balance = 0.0;

        for (int j = 0; j < stockCount; j++) {
            token = strtok(NULL, ",");
            if (token != NULL)
                users[i].quantity[j] = atoi(token);
            else
                users[i].quantity[j] = 0;

            token = strtok(NULL, ",");
            if (token != NULL)
                users[i].avgPrice[j] = atof(token);
            else
                users[i].avgPrice[j] = 0.0;
        }
    }
    fclose(file);
}

// 함수: 사용자 데이터 저장
void saveUserData(User users[], int userCount, int stockCount) {
    FILE* file = fopen(USER_FILE, "w");
    if (file == NULL) {
        perror("파일 저장 실패");
        return;
    }
    fprintf(file, "%d\n", userCount);
    for (int i = 0; i < userCount; i++) {
        fprintf(file, "%s,%.2f", users[i].username, users[i].balance);
        for (int j = 0; j < stockCount; j++) {
            fprintf(file, ",%d,%.2f", users[i].quantity[j], users[i].avgPrice[j]);
        }
        fprintf(file, "\n");
    }
    fclose(file);
    printf("사용자 데이터를 저장했습니다.\n");
}

// 함수: 사용자 목록 출력
void printUserList(User users[], int userCount) {
    printf("--- 사용자 목록 ---\n");
    if (userCount == 0) {
        printf("등록된 사용자가 없습니다.\n");
        return;
    }
    printf("%-5s %-20s\n", "번호", "이름");
    printf("---------------------------\n");
    for (int i = 0; i < userCount; i++) {
        printf("%-5d %-20s\n", i + 1, users[i].username);
    }
    printf("---------------------------\n");
}

// 함수: 사용자 추가 (기본 자산 4000 지급)
void addUser(User users[], int* userCount, int stockCount) {
    if (*userCount >= MAX_USERS) {
        printf("사용자 수 초과!\n");
        return;
    }
    User newUser;
    printf("새 사용자 이름 입력: ");
    fgets(newUser.username, sizeof(newUser.username), stdin);
    newUser.username[strcspn(newUser.username, "\n")] = '\0';

    if (strlen(newUser.username) == 0) {
        printf("이름이 입력되지 않았습니다. 다시 시도해주세요.\n");
        return;
    }

    newUser.balance = 4000;
    for (int i = 0; i < stockCount; i++) {
        newUser.quantity[i] = 0;
        newUser.avgPrice[i] = 0.0;
    }
    users[*userCount] = newUser;
    (*userCount)++;
    printf("새 사용자 추가 완료! 기본 자산: 4000%s 지급\n", currentCurrency);
}

// 함수: 사용자 삭제
void deleteUser(User users[], int* userCount) {
    if (*userCount == 0) {
        printf("삭제할 사용자가 없습니다.\n");
        return;
    }
    printf("삭제할 사용자 번호 입력:\n");
    printUserList(users, *userCount);
    int deleteIndex;
    if (scanf("%d", &deleteIndex) != 1) {
        printf("잘못된 선택!\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');
    deleteIndex--;
    if (deleteIndex < 0 || deleteIndex >= *userCount) {
        printf("잘못된 사용자 번호입니다.\n");
        return;
    }

    for (int i = deleteIndex; i < *userCount - 1; i++) {
        users[i] = users[i + 1];
    }
    (*userCount)--;
    printf("사용자가 삭제되었습니다.\n");
}

// 함수: 사용자 이름 변경
void changeUsername(User users[], int userCount) {
    printf("이름을 변경할 사용자 번호를 선택하세요:\n");
    printUserList(users, userCount);
    int userIndex;
    if (scanf("%d", &userIndex) != 1 || userIndex < 1 || userIndex > userCount) {
        printf("잘못된 선택!\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');
    userIndex--;
    printf("새 사용자 이름 입력: ");
    char newUsername[30];
    fgets(newUsername, sizeof(newUsername), stdin);
    newUsername[strcspn(newUsername, "\n")] = '\0';

    if (strlen(newUsername) == 0) {
        printf("이름이 입력되지 않아 변경하지 않습니다.\n");
        return;
    }

    strncpy(users[userIndex].username, newUsername, sizeof(users[userIndex].username) - 1);
    users[userIndex].username[sizeof(users[userIndex].username) - 1] = '\0';
    printf("사용자 이름이 %s로 변경되었습니다.\n", users[userIndex].username);
}

// 함수: 주식 매수
void buyStock(User* user, Stock stocks[], int stockCount) {
    int choice, amount;
    printf("\n[ 주식 구매 ]\n");
    printf("%-5s %-20s %-10s\n", "번호", "주식명", "현재가");
    printf("----------------------------------\n");
    for (int i = 0; i < stockCount; i++) {
        printf("%-5d %-20s %.2f%s\n", i, stocks[i].name, stocks[i].price, currentCurrency);
    }
    printf("----------------------------------\n");
    printf("구매할 주식 번호 입력: ");
    if (scanf("%d", &choice) != 1 || choice < 0 || choice >= stockCount) {
        printf("잘못된 입력입니다.\n");
        while (getchar() != '\n');
        return;
    }
    printf("구매 수량 입력: ");
    if (scanf("%d", &amount) != 1 || amount <= 0) {
        printf("잘못된 수량!\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');
    double cost = stocks[choice].price * amount;
    if (cost > user->balance) {
        printf("잔액이 부족합니다! 현재 잔액: %.2f%s\n", user->balance, currentCurrency);
        return;
    }
    user->balance -= cost;
    if (user->quantity[choice] > 0) {
        user->avgPrice[choice] = (user->avgPrice[choice] * user->quantity[choice] + cost) /
            (user->quantity[choice] + amount);
    }
    else {
        user->avgPrice[choice] = stocks[choice].price;
    }
    user->quantity[choice] += amount;
    printf("%s %d주 구매 완료!\n", stocks[choice].name, amount);
    printf("남은 잔액: %.2f%s\n", user->balance, currentCurrency);
}

// 주식 가격표 출력 함수 (요청 1, 2 반영: 여백 추가 및 % 기호 출력)
// [수정된 함수] 주식 가격표 출력
void printStockPriceTable(Stock stocks[], int stockCount) {
    printf("\n==== 증권 시장 ====\n");
    // 헤더 열 너비 조정: '가격' 열 너비 조정 및 '변동률' 열 너비 조정
    printf("%-5s %-20s %-15s %-10s\n", "번호", "주식명", "가격", "변동률(%%)");
    printf("==============================================\n");
    for (int i = 0; i < stockCount; i++) {
        char price_with_currency[30];

        // 1. 가격 + 화폐 단위 문자열을 먼저 만듦 (예: "123.45€")
        snprintf(price_with_currency, sizeof(price_with_currency), "%.2f%s", stocks[i].price, currentCurrency);

        // 2. 가격(화폐 단위 포함)을 출력하기 위해 최소 15칸을 확보하고 왼쪽 정렬
        // 3. 변동률은 최소 10칸 확보 후 왼쪽 정렬하고 '%' 기호 추가
        printf("%-5d %-20s %-15s %-10.2f%%\n",
            i, stocks[i].name, price_with_currency, stocks[i].lastChangeRate);
    }
    printf("==============================================\n");
}

// 함수: 주식 매도
void sellStock(User* user, Stock stocks[], int stockCount) {
    int choice, amount;
    printf("\n[ 주식 판매 ]\n");
    printf("%-5s %-20s %-10s %-10s\n", "번호", "주식명", "보유수량", "현재가");
    printf("------------------------------------------\n");
    for (int i = 0; i < stockCount; i++) {
        printf("%-5d %-20s %-10d %.2f%s\n", i, stocks[i].name, user->quantity[i], stocks[i].price, currentCurrency);
    }
    printf("------------------------------------------\n");
    printf("판매할 주식 번호 입력: ");
    if (scanf("%d", &choice) != 1 || choice < 0 || choice >= stockCount) {
        printf("잘못된 선택!\n");
        while (getchar() != '\n');
        return;
    }
    if (user->quantity[choice] == 0) {
        printf("보유 수량이 없습니다!\n");
        while (getchar() != '\n');
        return;
    }
    printf("판매 수량 입력: ");
    if (scanf("%d", &amount) != 1 || amount <= 0 || amount > user->quantity[choice]) {
        printf("잘못된 수량!\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');
    double revenue = stocks[choice].price * amount;
    user->balance += revenue;
    user->quantity[choice] -= amount;
    if (user->quantity[choice] == 0) {
        user->avgPrice[choice] = 0;
    }
    printf("%s %d주 판매 완료!\n", stocks[choice].name, amount);
    printf("총 판매 금액: %.2f%s, 현재 잔액: %.2f%s\n", revenue, currentCurrency, user->balance, currentCurrency);
}

// 함수: 수익률 계산 및 출력
void printProfitRates(User* user, Stock stocks[], int stockCount) {
    printf("\n==== %s 님의 포트폴리오 ====\n", user->username);
    printf("현금 잔고: %.2f%s\n", user->balance, currentCurrency);
    printf("-------------------------------------------------------------------------\n");
    printf("%-20s %-10s %-10s %-10s %-12s\n", "주식명", "보유수량", "매수평균가", "현재가", "수익률(%%)");
    printf("-------------------------------------------------------------------------\n");
    double totalAssetValue = user->balance;
    for (int i = 0; i < stockCount; i++) {
        if (user->quantity[i] > 0) {
            double profitRate = ((stocks[i].price - user->avgPrice[i]) / user->avgPrice[i]) * 100;
            // 수정: 수익률 출력 시 % 기호 추가
            printf("%-20s %-10d %-10.2f %-10.2f %-10.2f%%\n",
                stocks[i].name, user->quantity[i], user->avgPrice[i], stocks[i].price, profitRate);
            totalAssetValue += user->quantity[i] * stocks[i].price;
        }
    }
    printf("-------------------------------------------------------------------------\n");
    printf("총 자산 가치: %.2f%s\n", totalAssetValue, currentCurrency);
    printf("=========================================================================\n");
}

// 함수: 주식 가격 일괄 변경
void updateAllStockPricesSequentially(Stock stocks[], int stockCount) {
    printf("\n--- 주식 가격 일괄 변경 ---\n");

    // 가격 변경 전에 현재 가격 백업
    for (int i = 0; i < stockCount; i++) {
        backupPrices[i] = stocks[i].price;
    }
    pricesBackedUp = 1;

    for (int i = 0; i < stockCount; i++) {
        double change;
        printf("[%s] 현재 가격: %.2f%s\n", stocks[i].name, stocks[i].price, currentCurrency);
        printf("변경할 가격 비율(%%) 입력: ");

        if (scanf("%lf", &change) != 1) {
            printf("잘못된 금액 입력!\n");
            while (getchar() != '\n');
            return;
        }
        while (getchar() != '\n');

        stocks[i].price += stocks[i].price * (change / 100.0);

        if (stocks[i].price < 0.01) {
            stocks[i].price = 0.01;
        }

        stocks[i].lastChangeRate = change;

        // 수정: % 기호 추가
        printf("-> %s의 가격이 %.2f%% 변경되어 현재 가격: %.2f%s\n\n",
            stocks[i].name, change, stocks[i].price, currentCurrency);
    }
}

// 함수: 사용자 자산 강제변경
void changeUserBalance(User* user, Stock stocks[], int stockCount) {
    int choice;
    printf("\n--- 사용자 자산 강제 변경 ---\n");
    printf("1. 현금 잔액 변경\n");
    printf("2. 특정 주식 보유 수량 변경\n");
    printf("선택: ");
    if (scanf("%d", &choice) != 1 || (choice != 1 && choice != 2)) {
        printf("잘못된 선택입니다.\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');

    if (choice == 1) {
        double newBalance;
        printf("현재 잔액: %.2f%s\n", user->balance, currentCurrency);
        printf("새로운 잔액 입력: ");
        if (scanf("%lf", &newBalance) != 1 || newBalance < 0) {
            printf("잘못된 입력입니다.\n");
            while (getchar() != '\n');
            return;
        }
        while (getchar() != '\n');
        user->balance = newBalance;
        printf("현금 잔액이 %.2f%s로 변경되었습니다.\n", user->balance, currentCurrency);
    }
    else if (choice == 2) {
        int stockIndex, newQuantity;
        printf("\n주식 목록:\n");
        for (int i = 0; i < stockCount; i++) {
            printf("%d. %s (현재 보유: %d주)\n", i, stocks[i].name, user->quantity[i]);
        }
        printf("변경할 주식 번호 입력: ");
        if (scanf("%d", &stockIndex) != 1 || stockIndex < 0 || stockIndex >= stockCount) {
            printf("잘못된 선택입니다.\n");
            while (getchar() != '\n');
            return;
        }
        while (getchar() != '\n');
        printf("현재 보유 수량: %d주\n", user->quantity[stockIndex]);
        printf("새로운 보유 수량 입력: ");
        if (scanf("%d", &newQuantity) != 1 || newQuantity < 0) {
            printf("잘못된 입력입니다.\n");
            while (getchar() != '\n');
            return;
        }
        while (getchar() != '\n');
        user->quantity[stockIndex] = newQuantity;
        if (newQuantity == 0) {
            user->avgPrice[stockIndex] = 0.0;
        }
        printf("%s의 보유 수량이 %d주로 변경되었습니다.\n", stocks[stockIndex].name, user->quantity[stockIndex]);
    }
}

// 새로운 주식 상장 함수
void listNewStock(Stock stocks[], int* stockCount, User users[], int userCount) {
    if (*stockCount >= MAX_STOCKS) {
        printf("최대 주식 수에 도달했습니다. 더 이상 상장할 수 없습니다.\n");
        return;
    }

    printf("\n--- 신규 주식 상장 ---\n");
    char newName[30];
    double newPrice;
    printf("상장할 기업 이름 입력: ");
    fgets(newName, sizeof(newName), stdin);
    newName[strcspn(newName, "\n")] = '\0';

    if (strlen(newName) == 0) {
        printf("이름이 입력되지 않아 취소합니다.\n");
        return;
    }

    printf("초기 가격 입력: ");
    if (scanf("%lf", &newPrice) != 1 || newPrice <= 0) {
        printf("잘못된 가격입니다. 상장 취소.\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');

    strncpy(stocks[*stockCount].name, newName, sizeof(stocks[*stockCount].name) - 1);
    stocks[*stockCount].name[sizeof(stocks[*stockCount].name) - 1] = '\0';
    stocks[*stockCount].price = newPrice;
    stocks[*stockCount].lastChangeRate = 0.0;

    for (int i = 0; i < userCount; i++) {
        users[i].quantity[*stockCount] = 0;
        users[i].avgPrice[*stockCount] = 0.0;
    }

    (*stockCount)++;
    printf("%s 주식이 %.2f%s의 가격으로 신규 상장되었습니다!\n", newName, newPrice, currentCurrency);
}

// 주식 상장폐지 함수
void delistStock(Stock stocks[], int* stockCount, User users[], int userCount) {
    if (*stockCount <= 0) {
        printf("상장폐지할 주식이 없습니다.\n");
        return;
    }

    printf("\n--- 주식 상장폐지 ---\n");
    printf("상장폐지할 주식 번호를 선택하세요:\n");
    printf("%-5s %-20s %-10s\n", "번호", "주식명", "현재가");
    printf("----------------------------------\n");
    for (int i = 0; i < *stockCount; i++) {
        printf("%-5d %-20s %.2f%s\n", i, stocks[i].name, stocks[i].price, currentCurrency);
    }
    printf("----------------------------------\n");

    int choice;
    printf("선택: ");
    if (scanf("%d", &choice) != 1 || choice < 0 || choice >= *stockCount) {
        printf("잘못된 선택입니다.\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');

    char delistedName[30];
    strncpy(delistedName, stocks[choice].name, sizeof(delistedName) - 1);
    delistedName[sizeof(delistedName) - 1] = '\0';

    for (int i = 0; i < userCount; i++) {
        if (users[i].quantity[choice] > 0) {
            double liquidationValue = users[i].quantity[choice] * stocks[choice].price;
            users[i].balance += liquidationValue;
            printf("사용자 %s의 %s 주식 %d주가 %.2f%s에 청산되어 잔고에 합산되었습니다.\n",
                users[i].username, delistedName, users[i].quantity[choice], liquidationValue, currentCurrency);
        }
    }

    for (int i = choice; i < (*stockCount) - 1; i++) {
        stocks[i] = stocks[i + 1];
    }
    (*stockCount)--;
    printf("주식 %s가 상장폐지되었습니다.\n", delistedName);
}

// [수정된 기능] 화폐 표기 선택 (요청 3 반영: 직접 문자열 입력)
void setCurrency() {
    char newCurrency[10];
    printf("\n--- 화폐 표기 선택 ---\n");
    printf("현재 화폐 단위: %s\n", currentCurrency);
    printf("새로운 화폐 단위 문자열 입력 (최대 9자, 예: $, ₩, ¥, BTC): ");

    // fgets로 문자열을 입력받고 개행 문자를 제거
    fgets(newCurrency, sizeof(newCurrency), stdin);
    newCurrency[strcspn(newCurrency, "\n")] = '\0';

    if (strlen(newCurrency) == 0) {
        printf("입력된 값이 없어 변경하지 않습니다.\n");
        return;
    }

    // 전역 변수에 복사
    strncpy(currentCurrency, newCurrency, sizeof(currentCurrency) - 1);
    currentCurrency[sizeof(currentCurrency) - 1] = '\0';

    printf("화폐 단위가 %s로 변경되었습니다.\n", currentCurrency);
}

// [추가 기능] 가격 변동 무르기 (Undo)
void undoStockPriceChange(Stock stocks[], int stockCount) {
    if (!pricesBackedUp) {
        printf("이전 가격 변동 기록이 없습니다.\n");
        return;
    }

    printf("\n--- 주식 가격 변동 무르기 ---\n");
    for (int i = 0; i < stockCount; i++) {
        stocks[i].price = backupPrices[i];
        stocks[i].lastChangeRate = 0.0;
    }
    pricesBackedUp = 0;
    printf("주식 가격이 이전 상태로 복구되었습니다.\n");
    printStockPriceTable(stocks, stockCount);
}

// [추가 기능] 계좌 이체
void transferBalance(User users[], int userCount, int currentUser) {
    int receiverIndex;
    double amount;

    printf("\n--- 계좌 이체 ---\n");
    printf("현재 사용자: %s (잔액: %.2f%s)\n", users[currentUser].username, users[currentUser].balance, currentCurrency);

    printf("\n이체받을 사용자 번호 입력:\n");
    printUserList(users, userCount);
    if (scanf("%d", &receiverIndex) != 1 || receiverIndex < 1 || receiverIndex > userCount) {
        printf("잘못된 선택!\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');
    receiverIndex--;

    if (currentUser == receiverIndex) {
        printf("자기 자신에게 이체할 수 없습니다.\n");
        return;
    }

    printf("이체할 금액 입력: ");
    if (scanf("%lf", &amount) != 1 || amount <= 0) {
        printf("잘못된 금액입니다. 이체 취소.\n");
        while (getchar() != '\n');
        return;
    }
    while (getchar() != '\n');

    if (amount > users[currentUser].balance) {
        printf("잔액이 부족합니다! 이체 실패.\n");
        return;
    }

    users[currentUser].balance -= amount;
    users[receiverIndex].balance += amount;

    printf("\n이체 완료!\n");
    printf("%s -> %s 에게 %.2f%s 이체되었습니다.\n",
        users[currentUser].username, users[receiverIndex].username, amount, currentCurrency);
    printf("%s 남은 잔액: %.2f%s\n", users[currentUser].username, users[currentUser].balance, currentCurrency);
    printf("%s 최종 잔액: %.2f%s\n", users[receiverIndex].username, users[receiverIndex].balance, currentCurrency);
}


// 메인 함수
int main() {
	system("chcp 65001");
    system("cls");
    Stock stocks[MAX_STOCKS];
    User users[MAX_USERS];
    int userCount = 0;
    int stockCount = 0;
    int currentUser = -1;

    loadStockData(stocks, &stockCount);
    loadUserData(users, &userCount, stockCount);

    printf("======================================\n");
    printf("      가상 주식 거래 시스템에 오신 것을 환영합니다!\n");
    printf("======================================\n");

    int mainChoice;
    while (1) {
        printf("\n");
        printf("================ [ 메인 메뉴 ] ================\n");
        printf("  --- 사용자 관리 ---\n");
        printf("    1. 사용자 선택\n");
        printf("    2. 사용자 추가\n");
        printf("    3. 사용자 삭제\n");
        printf("    4. 사용자 이름 변경\n");
        printf("  --- 증권시장 관리 ---\n");
        printf("    5. 주식 상장 (새로운 기업 추가)\n");
        printf("    6. 주식 상장폐지\n");
        printf("    7. 주식 가격 일괄 변경\n");
        printf("    8. 증권시장 출력\n");
        printf("  --- 기타 기능 ---\n");
        printf("    9. 화폐 표기 선택 (현재: %s)\n", currentCurrency);
        printf("   10. 가격 변동 무르기 (UNDO)\n");
        printf("   11. 사용자 데이터 강제 저장\n");
        printf("   12. 프로그램 종료\n");
        printf("==============================================\n");
        printf("선택: ");
        if (scanf("%d", &mainChoice) != 1) {
            printf("잘못된 입력입니다.\n");
            while (getchar() != '\n');
            continue;
        }
        while (getchar() != '\n');

        switch (mainChoice) {
        case 1: {
            if (userCount == 0) {
                printf("사용자가 없습니다. 먼저 사용자를 추가해주세요.\n");
                continue;
            }
            printf("\n--- 사용자 선택 ---\n");
            printUserList(users, userCount);
            printf("사용자 번호 입력 (1부터 %d까지): ", userCount);
            if (scanf("%d", &currentUser) != 1 || currentUser < 1 || currentUser > userCount) {
                printf("잘못된 선택입니다.\n");
                currentUser = -1;
                while (getchar() != '\n');
                continue;
            }
            while (getchar() != '\n');
            currentUser--;
            printf("--> 현재 선택된 사용자: %s\n", users[currentUser].username);

            int userMenuChoice = 0;
            int exitUserMenu = 0;
            while (1) {
                exitUserMenu = 0;
                printf("\n--- [ 사용자 메뉴 - %s ] ---\n", users[currentUser].username);
                printf("1. 주식 구매\n");
                printf("2. 주식 판매\n");
                printf("3. 수익률 확인\n");
                printf("4. 사용자 자산 강제변경\n");
                printf("5. 계좌 이체\n");
                printf("6. 메인 메뉴로 돌아가기\n");
                printf("----------------------------------\n");
                printf("선택: ");
                if (scanf("%d", &userMenuChoice) != 1) {
                    printf("잘못된 입력!\n");
                    while (getchar() != '\n');
                    break;
                }
                while (getchar() != '\n');

                switch (userMenuChoice) {
                case 1: buyStock(&users[currentUser], stocks, stockCount); break;
                case 2: sellStock(&users[currentUser], stocks, stockCount); break;
                case 3: printProfitRates(&users[currentUser], stocks, stockCount); break;
                case 4: changeUserBalance(&users[currentUser], stocks, stockCount); break;
                case 5: transferBalance(users, userCount, currentUser); break;
                case 6: exitUserMenu = 1; break;
                default: printf("잘못된 선택입니다.\n"); break;
                }
                if (exitUserMenu) {
                    saveUserData(users, userCount, stockCount);
                    saveStockData(stocks, stockCount);
                    break;
                }
            }
            break;
        }
        case 2: addUser(users, &userCount, stockCount); saveUserData(users, userCount, stockCount); break;
        case 3: deleteUser(users, &userCount); saveUserData(users, userCount, stockCount); break;
        case 4: changeUsername(users, userCount); saveUserData(users, userCount, stockCount); break;
        case 5: listNewStock(stocks, &stockCount, users, userCount); saveStockData(stocks, stockCount); saveUserData(users, userCount, stockCount); break;
        case 6: delistStock(stocks, &stockCount, users, userCount); saveStockData(stocks, stockCount); saveUserData(users, userCount, stockCount); break;
        case 7: updateAllStockPricesSequentially(stocks, stockCount); saveStockData(stocks, stockCount); break;
        case 8: printStockPriceTable(stocks, stockCount); break;
        case 9: setCurrency(); break;
        case 10: undoStockPriceChange(stocks, stockCount); saveStockData(stocks, stockCount); break;
        case 11: saveUserData(users, userCount, stockCount); break;
        case 12:
            saveUserData(users, userCount, stockCount);
            saveStockData(stocks, stockCount);
            printf("프로그램을 종료합니다.\n");
            return 0;
        default:
            printf("잘못된 선택입니다.\n");
            break;
        }
    }
    return 0;
}
— 쇼샤

설명문

가국 통장 및 주식시장 전산화 프로그램 Ver.2.4
- 제작자: 쇼샤

-----------------------------------------------------------------

사용법
1. 가상 이용자들의 통장을 전산화하여 관리함
2. 가상 주식시장을 전산화하여 관리함

-----------------------------------------------------------------

주의할점
1. 저거 사용하면 자동적으로 한셀같은 파일(CSV 파일) 2개가 나올텐데 직접 수정할수 없고, 수정하면 망하는 파일이니 건들지말것.

2. 포함된 파일과 2개의 셀파일이 같이 있을것.
예)배경화면에 다 나와있음 => ○
예)한 파일에 몰려있음 => ○
예)셀 파일 2개를 파일집에 묵고 메인파일을 배경화면에 둠 => ×

3. 주식 계산할시 사용하는 숫자는 %임.
예)25 -> +25.00%
예) -12.45 -> -12.45%


-----------------------------------------------------------------

Ver.2.3->Ver.2.4 설명
1. 주식시장표에 %값도 산출하게함.
2. 딱 1번 변동값 되돌릴 수 있게 만듬.
3. 화폐를 마음대로 커스텀 가능하게 만듬
4. 사용자 계좌간 계좌이체기능 추가

-----------------------------------------------------------------

이상.
Essen Wilhelm Shosha.