C 언어 그룹(GROUP)알고리즘.c
group_algorithm_with_file_io.c
// Visual Studio에서 보안 경고를 무시하도록 설정 (fopen 등에서 경고 방지)
#define _CRT_SECURE_NO_WARNINGS
// C 표준 라이브러리 헤더 포함
#include <stdio.h> // 파일 입출력 관련 함수: fopen, fclose, printf, fprintf 등
#include <stdlib.h> // 표준 유틸리티 함수: atoi, exit 등
#include <string.h> // 문자열 처리 함수: strcmp, strcpy
#include <stdbool.h> // bool, true, false 사용을 위한 헤더
// 상수 정의
#define MAX_RECORDS 100 // 최대 레코드 수
#define INPUT_FILE_PATH "C:\\Temp\\abc1229.txt" // 입력 파일 경로
#define OUTPUT_FILE_PATH "C:\\Temp\\abc1229_.txt" // 출력 파일 경로
// 구조체 정의: 상품명 + 판매량으로 구성된 레코드
typedef struct
{
char product_name[6]; // 상품명 (최대 5자 + 종료 문자 '\0')
int quantity; // 판매량 (정수)
} record_t;
// 파일 존재 여부 확인 함수
// fopen으로 파일을 열어보고 성공하면 true, 실패하면 false 반환
bool file_exists(const char* path) {
FILE* file = fopen(path, "r"); // 읽기 모드로 열기 시도
if (file != NULL) {
fclose(file); // 파일이 존재하므로 닫고 true 반환
return true;
}
return false; // 파일 열기 실패 → 존재하지 않음
}
// 입력 파일이 없을 경우 샘플 데이터를 자동으로 생성
void create_sample_input_file()
{
FILE* file = fopen(INPUT_FILE_PATH, "wt"); // 텍스트 쓰기 모드로 파일 열기
if (file == NULL)
{
perror("입력 파일 생성 실패"); // 파일 생성 오류 출력
exit(EXIT_FAILURE); // 프로그램 강제 종료
}
// 샘플 데이터 (상품명은 5자리, 숫자는 최대 3자리로 자릿수 고정)
const char* lines[] = {
"RADIO 5",
"TV 6",
"PHONE 3",
"RADIO 2",
"PHONE 2",
"TV 10",
"PHONE 11",
"TV 7",
"PHONE 4"
};
// 배열에 있는 샘플 데이터를 한 줄씩 파일에 저장
for (int i = 0; i < sizeof(lines) / sizeof(lines[0]); i++)
{
fprintf(file, "%s\n", lines[i]);
}
fclose(file); // 파일 닫기
printf("샘플 입력 파일이 생성되었습니다: %s\n", INPUT_FILE_PATH);
}
// fscanf를 이용해 파일에서 레코드 읽기
int read_records(FILE* input_file, record_t* records)
{
int count = 0;
while (count < MAX_RECORDS)
{
// 서식 설명:
// "%5s" : 최대 5글자까지 문자열 읽기 (공백 없이)
// "%3d" : 최대 3자리 정수 읽기 (숫자 앞에 공백 있어도 허용)
int result = fscanf(input_file, "%5s%3d", records[count].product_name, &records[count].quantity);
if (result != 2) // 두 개 모두 못 읽으면 반복 중지
break;
count++; // 유효한 레코드 수 증가
}
return count; // 실제 읽은 레코드 수 반환
}
// 상품명을 기준으로 오름차순 정렬 (선택 정렬 방식)
void sort_records(record_t* records, int count)
{
for (int i = 0; i < count - 1; i++)
{
for (int j = i + 1; j < count; j++)
{
// 문자열 비교: i번째보다 j번째가 사전순으로 앞서면 교환
if (strcmp(records[i].product_name, records[j].product_name) > 0)
{
// 값 교환
record_t temp = records[i];
records[i] = records[j];
records[j] = temp;
}
}
}
}
// 동일한 상품명을 가진 항목을 묶어 판매량을 합산
int group_records(const record_t* records, int count, record_t* grouped)
{
int group_count = 0;
int group_total = 0;
for (int i = 0; i < count; i++)
{
group_total += records[i].quantity; // 현재 항목의 판매량을 누적
// 그룹의 마지막 항목인지 확인
bool is_last = (i == count - 1);
bool boundary = is_last || strcmp(records[i].product_name, records[i + 1].product_name) != 0;
if (boundary)
{
// 그룹 정보를 grouped 배열에 저장
strcpy(grouped[group_count].product_name, records[i].product_name);
grouped[group_count].quantity = group_total;
group_count++;
group_total = 0; // 다음 그룹을 위해 초기화
}
}
return group_count; // 그룹 개수 반환
}
// 콘솔에 레코드 배열을 출력
void print_records(const record_t* records, int count)
{
for (int i = 0; i < count; i++)
{
// 상품명은 왼쪽 정렬, 수량은 오른쪽 정렬
printf("%-5s%3d\n", records[i].product_name, records[i].quantity);
}
}
// 파일에 레코드 배열을 출력
void write_records(FILE* file, const record_t* records, int count)
{
for (int i = 0; i < count; i++)
{
fprintf(file, "%-5s%3d\n", records[i].product_name, records[i].quantity);
}
}
// main 함수: 프로그램 시작점
int main(void)
{
record_t records[MAX_RECORDS]; // 원본 데이터 저장용 배열
record_t grouped[MAX_RECORDS]; // 그룹화된 결과 저장용 배열
// [0] 파일이 없으면 샘플 데이터 자동 생성
if (!file_exists(INPUT_FILE_PATH))
{
create_sample_input_file();
}
// 파일 열기
FILE* input_file = fopen(INPUT_FILE_PATH, "rt"); // 텍스트 읽기 모드
FILE* output_file = fopen(OUTPUT_FILE_PATH, "wt"); // 텍스트 쓰기 모드
if (input_file == NULL || output_file == NULL)
{
perror("파일 열기 실패"); // 파일 열기 실패 메시지 출력
return EXIT_FAILURE; // 프로그램 비정상 종료
}
// [1] 파일에서 데이터 읽기
int record_count = read_records(input_file, records);
printf("입력된 상품 데이터 (%d개):\n", record_count);
print_records(records, record_count);
// [2] 상품명 기준 정렬
sort_records(records, record_count);
printf("\n정렬된 데이터:\n");
print_records(records, record_count);
// [3] 동일 상품명끼리 판매량 합산 (그룹화)
int group_count = group_records(records, record_count, grouped);
printf("\n상품별 판매량 집계 결과:\n");
print_records(grouped, group_count);
// [4] 결과를 출력 파일로 저장
write_records(output_file, grouped, group_count);
// [5] 파일 닫기
fclose(input_file);
fclose(output_file);
return EXIT_SUCCESS; // 프로그램 정상 종료
}
C 언어 그룹(GROUP)알고리즘.c
// 그룹(GROUP) 알고리즘
#include <stdio.h>
#include <string.h>
//[!] Input data
struct Record
{
char ProductName[6]; // 상품명
int Quantity; // 판매량
}record[10];
//[!] Output data
struct Output
{
char ProductName[6]; // 상품명
int Quantity; // 판매량
}output[10];
void main(void)
{
//[1] Init
FILE *inData;
FILE *outData;
char buffer[10];
char tempbuff[4];
int count = 0;
int i = 0;
int j = 0;
struct Record temp;
int subTotal = 0; // 그룹소계
int groupCount = 0; // 그룹수
//[2] Input
inData = fopen("C:\\Temp\\abc1229.txt", "rt");
outData = fopen("C:\\Temp\\abc1229_.txt", "wt");
if (inData == NULL || outData == NULL)
{
perror("파일을 열 수 없습니다.");
exit(1);
}
while (!feof(inData))
{
memset(buffer, 0, 10); // 버퍼 초기화
fgets(buffer, 10, inData); // 라인 단위 입력
if (strlen(buffer) > 2) // 예외처리 : 버퍼에 담기 데이터가 있다면...
{
strncpy(record[count].ProductName, buffer + 0, 5); // 상품명
record[count].Quantity = atoi(strncpy(tempbuff, buffer + 5, 3)); // 판매량
count++;
}
}
printf("입력 후 데이터 : \n");
for(i = 0;i < count;i++)
{
printf("%s %d\n", record[i].ProductName, record[i].Quantity);
}
//[2] Process
//[A] Sort
for(i = 0;i < count - 1;i++)
{
for(j = i + 1;j < count;j++)
{
if(strcmp(record[i].ProductName, record[j].ProductName) > 0)
{
temp = record[i];
record[i] = record[j];
record[j] = temp;
}
}
}
printf("정렬 후 데이터 : \n");
for(i = 0;i < count;i++)
{
printf("%s %d\n", record[i].ProductName, record[i].Quantity);
}
//[B] Group
for(i = 0;i < count;i++)
{
subTotal += record[i].Quantity; // 그룹소계
// 상품명이 다르면, 새로운 상품명으로 이동
if(strcmp(record[i].ProductName, record[i+1].ProductName) != 0)
{
strcpy(output[groupCount].ProductName, record[i].ProductName);
output[groupCount].Quantity = subTotal; // 그룹소계
groupCount++; // 그룹수 증가
subTotal = 0; // 그룹소계 초기화
}
}
//[3] Output
printf("처리 후 데이터 : \n");
for(i = 0;i < groupCount;i++)
{
printf("%s %d\n", output[i].ProductName, output[i].Quantity);
fprintf(outData, "%s %d\n", output[i].ProductName, output[i].Quantity);
}
//[4] Dispose
fclose(inData);
fclose(outData);
}
/*
abc1229.txt파일의 내용
--------------------
RADIO 5
TV 6
PHONE 3
RADIO 2
PHONE 2
TV 10
PHONE 11
TV 7
PHONE 4
*/
Comments
Comments are closed