Schoolwork/자료구조와 C++프로그래밍

[C++] 3주차 과제3

FATKITTY 2020. 8. 5. 11:17
반응형

첨부파일(HW3.pdf)에 제시된 문제를 C++ 프로그램으로 작성하라.

  • 입력 파일의 제목은 "input.txt"로 통일 (문장부호, 중복 단어를 포함한 예문 사용)
  • 결과물(출력할 내용) : 입력파일 내용, 단어 정렬 결과, 중복 제거 결과, 단어 검색 결과 예
    • 단어 정렬 결과, 중복 제거 결과 등은 (단어 위치, 단어)와 같이 쌍으로 표현하며, 출력 형식(표, 리스트 등)은 자유로이 선택
    • 검색 예는 입력에 포함되어 있는 단어, 없는 단어 각 3개씩 검색하여 결과 보이게 한다. 
    • 프로그램의 종료 없이 한 번의 실행으로 반복적으로 검색할 수 있도록 한다. (.(마침표) 입력시 프로그램 종료)
    • 문장부호는 최소 '"!?,. 6개를 제외시킨다.
    • 문장에 존재하는 단어를 입력할 시에는 단어의 위치(1부터 시작), 없는 경우에는 -1을 출력한다.
    • 코드에 코멘트를 달아서 이해하기 쉽도록 한다.

** 반드시 문제에 주어진 알고리즘을 사용한다. (선택정렬, 순환적 이원 탐색)

  • 선택정렬, 순환적 이원 탐색을 반드시 직접 구현

Code

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>

#define R 1001
using namespace std;

char WordDataSet[R][R]; // 받은 데이터를 담고있는 2차원 배열입니다.

int BinarySearch(const char arr[R][R], char* x, const int left, const int right)  // 순환이진탐색 -> 단어 위치
{
	if (left <= right)
	{
		int middle = (left + right) / 2;
		if (strcmp(x, arr[middle]) == -1) BinarySearch(arr, x, left, middle - 1);
		else if (strcmp(x, arr[middle]) == 1)  BinarySearch(arr, x, middle + 1, right);
		else return middle;  // x == arr[middle]
	}
	else return -1;  // left > right
}

void SelectionSort(const int n)  // 선택정렬 -> 단어 정렬
{
	for (int i = 0; i < n; i++)
	{
		int j = i;
		for (int k = i + 1; k < n; k++) {
			if (strcmp(WordDataSet[k], WordDataSet[j]) == -1) j = k;
		}
		swap(WordDataSet[i], WordDataSet[j]);
	}
}

// void* memmove(void* destination, const void* source, size_t num); 
// 메모리 블록을 옮긴다. source 가 가리키는 곳 부터 num 바이트 만큼을 destination 이 가리키는 곳으로 옮긴다.
void Delete(char* ar, int idx)
{
	memmove(ar + idx, ar + idx + 1, strlen(ar) - idx);
}

int main() 
{
	FILE* f = fopen("input.txt", "r"); // 파일을 읽기 형식으로 받아줍니다. 
	if (f == NULL) printf("None file\n"); // 파일이 존재하지 않을 경우 예외처리입니다.
	
	int i = 0; //  받은 데이터들의 인덱스를 표시하는 변수입니다.

	cout << " ***** 입력파일 내용 ***** " << endl;
	while (!feof(f)) {
		fscanf(f, "%s", WordDataSet[i]); // 텍스트파일에서 문자열을 받습니다.
		int size = strlen(WordDataSet[i]); //  텍스트파일에 있는 문자열의 길이를 구합니다.
		
		// 입력파일에서 문자열 받은 것을 공백 기준으로 잘라서 출력합니다.
		char* ptr = strtok(WordDataSet[i], " ");  // 공백 문자를 기준으로 문자열을 자름, 포인터 반환
		while (ptr != NULL)  // 자른 문자열이 나오지 않을 때까지 반복
		{
			printf("%s ", ptr);  // 자른 문자열 출력

			for (int check = 0; check < size; check++) {  // 원본 내용 출력 후에 특수문자 삭제
				if (WordDataSet[i][check] >= 32 && WordDataSet[i][check] <= 47 || WordDataSet[i][check] >= 58 && WordDataSet[i][check] <= 64
					|| WordDataSet[i][check] >= 91 && WordDataSet[i][check] <= 96 || WordDataSet[i][check] >= 123 && WordDataSet[i][check] <= 126)
				{
					Delete(WordDataSet[i], check);
					check--;
					// Delete하면 check 뒷부분의 나머지 문자열이 한칸씩 앞으로 땡겨오기 때문에 그 빈칸을 채우고, 
					// 원래 delete 전 check+1에 해당했던 부분을 건너뛰게 되므로 check도 다시 한칸 앞으로 땡겨준다.
				}
			}

			i++;  // 인덱스 증가
			ptr = strtok(NULL, " ");  // 다음 문자열을 잘라서 포인터를 반환
		}
	}

	SelectionSort(i);  // 단어 정렬

	cout << "\n\n ***** 단어 정렬 결과 *****" << endl;
	for (int j = 0; j < i; j++) {  // 정렬된 결과를 출력합니다. (단어 위치, 단어)와 같이 쌍으로 표현
		cout << j + 1 << ". " << WordDataSet[j] << endl;
	}

	int count_overlap = 0;  // 중복된 횟수
	for (int check = 0; check < i; check++)
	{
		for (int overlap = check + 1; overlap < i; overlap++)
		{
			if (strcmp(WordDataSet[check], WordDataSet[overlap]) == 0) {  // 서로 같은 단어가 존재할 때,
				*WordDataSet[check] = '\0';  // 앞에꺼 null 처리
				count_overlap++;
			}
		}
	}

	SelectionSort(i);  // 중복 제거 후 생긴 Null이 다 위에 모이도록 다시 정렬

	cout << "\n ***** 중복 제거 결과 *****" << endl;
	for (int j = 0; j < i; j++) {  // 중복 제거 후 정렬된 결과를 출력합니다. (단어 위치, 단어)와 같이 쌍으로 표현
		if (*WordDataSet[j] != '\0') cout << j - count_overlap + 1 << ". " << WordDataSet[j] << endl;
	}

	char UserInput[100];  // 사용자가 검색할 단어
	while (1)  // 프로그램의 종료 없이 한 번의 실행으로 반복적으로 검색할 수 있도록 한다.
	{
		cout << "\n검색할 단어를 입력하세요 : ";
		scanf("%s", &UserInput);

		if (UserInput[0] == '.') {  // .(마침표)입력시 프로그램 종료
			break;
			exit(0);
		}

		int location = BinarySearch(WordDataSet, UserInput, 0, i);  // 이원 탐색한 결과, 검색한 단어의 위치

		if (location >= 0) {
			printf("%d\n", location - count_overlap + 1);  // 중복 제거 결과와 같은 원리로 출력 (null의 갯수 만큼 빼줍니다)
		}
		else {
			printf("%d\n", location);  // 중복되는 원소가 존재하지 않는 경우, -1 출력
		}
	}

	return 0;
}

실행결과

 

참고자료

sorting.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>

#define R 1001
using namespace std;

/*해당 샘플코드는 텍스트 파일에서 문장을 읽어와 공백기준으로 데이터를 보관하는 방법을 설명한 코드입니다.
과제를 할시 cstdlib과 cstring과 같은 헤더파일은 인정되지만 구현해야하는 정렬이나 탐색 함수는 직접 구현하셔야합니다.
또한 과제에서의 문자열 중복처리 예외처리는 과제의 일부분이기때문에 샘플코드를 제공하지 않습니다.*/

char word[R]; // 텍스트파일에서 문자를 받아오는 변수입니다.
char WordDataSet[R][R]; // 받은 데이터를 담고있는 2차원 배열입니다.

int main() {

	FILE *f = fopen("input.txt", "r"); // 파일을 읽기 형식으로 받아줍니다. 

	if (f == NULL) printf("None file\n"); // 파일이 존재하지 않을 경우 예외처리입니다.
	int i = 0; //  받은 데이터들의 인덱스를 표시하는 변수입니다.

	while (!feof(f)) {
		fscanf(f, "%s", WordDataSet[i]); // 텍스트파일에서 문자열을 받습니다.
		int size = strlen(WordDataSet[i]); //  텍스트파일에 있는 문자열의 길이를 구합니다.
		if (WordDataSet[i][size - 1] == '.') WordDataSet[i][size - 1] = NULL; //  마침표가 있을 시 삭제를 해줍니다.
		i++;
	}

	for (int j = 0; j < i; j++) { // 저장된 문자열을 출력합니다.
		printf("%s\n", WordDataSet[j]);
	}

	return 0;
}

 

ASCII-Table

 

점수 10/10

 

 

  ❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)  

반응형

'Schoolwork > 자료구조와 C++프로그래밍' 카테고리의 다른 글

[C++] 9주차 과제6  (0) 2020.08.05
[C++] 7주차 과제5  (0) 2020.08.05
[C++] 5주차 과제4  (0) 2020.08.05
[C++] 2주차 과제2  (0) 2020.08.05
[C++] 1주차 과제1  (0) 2020.08.05