코딩 테스트

[코딩테스트 17일차] BAEKJOON 1052번, 10809번

sunlight-dby 2025. 5. 12. 23:15

[BAEKJOON 1052번 : 단어의 개수]

[문제]


[고찰]

해당 문제는 공백이 연속해서 나오지 않기 때문에 공백을 기준으로 단어를 구분하여, 그 개수를 파악하여 풀면 됩니다.

 

중요한 포인트는 string 객체를 cin으로 읽어오면, 예제 입력 1과 같은 경우에 string 객체는 공백으로 구분되어 "The"만 값이 저장됩니다.

따라서, string 객체를 개행 문자 전까지 입력을 받아 저장하기 위해서는 "getline"을 통해 입력받아야 합니다.

 

문자열 중간에 오는 공백을 단어의 뒤에 오는 공백으로만 한정 짓고 싶어서, 입력 받은 문자열을 for 문으로 순회하면서 if문으로 해당 조건을 확인해주었습니다.

최종적으로 조건을 확인한 후, 문자열이 끝날 때 공백으로 끝이나지 않을 가능성이 있기 때문에 마지막 글자가 공백이 아니라면 일부러 1을 더 해주어, 마치 공백으로 끝이 난 것처럼 구현하였습니다.

#include <iostream>
#include <string>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	string str;
	char space = ' ';

	int answer = 0;

	getline(cin, str);
	
	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] != space && str[i + 1] == space)
			++answer;
		
	}
	if (str[str.length() - 1] != space)
		++answer;


	cout << answer;

	return 0;
}

[개념]

제가 푼 아이디어만으로도 괜찮지만, 다른 분들의 풀이를 보면서 두 가지 방법을 더 알게 되었습니다.

 

[첫 번째 방법]

첫 번째 방법은 다른 환경이 아닌 백준 환경에서만 가능한 풀이입니다.

 

그 방법은 string 타입의 객체 str을 while 문 안에서 계속해서 입력을 받고, 입력을 받을 때 answer에 1을 더해주는 방식입니다.

str에는 공백을 기준으로 단어마다 저장이 되면서 1이 더해지고, 최종적으로는 str에는 마지막으로 입력한 단어만 남게 됩니다.

 

visual studio의 환경에서는 해당 방법은 while 문에서 끝없이 반복하기 때문에, EOF character(ctrl + z)를 넣어줘야 끝낼 수 있습니다. 하지만 백준에서는 입력을 넣을 때 파일로 주기 때문에 EOF가 자연스럽게 붙어 있어서 while 문의 입력을 끝낼 수 있습니다.

 

[두 번째 방법]

두 번째 방법은 stringstream을 활용하는 방법입니다.

읽어온 문자열을 stringstream으로 생성한 뒤, while문을 통해 stringstream에서 공백을 기준으로 단어를 하나씩 읽어오면서 answer을 1씩 더해주면 됩니다.


stringstream

stringstream은 C++ 의 입출력 스트림(iostream) 계층 구조의 일부로, 메모리 상의 std::string 객체입니다.

  • 헤더파일
    • <sstream>
  • std::istringstream
    • input string stream의 약자로, 입력 스트림으로만 작동합니다.
    • 입력 문자열에서 데이터를 읽어오는 데 사용합니다.
    • 자연스럽게 공백이나 개행문자를 제거하고 원하는 데이터 형태의 문자열만 읽을 수 있다는 장점이 있습니다.
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    std::string data_str = "Name: Alice Age: 30 Score: 95.5";
    std::istringstream iss(data_str);

    std::string label1, name, label2;
    int age;
    std::string label3;
    double score;

    // >> 연산자를 사용하여 문자열에서 데이터를 타입에 맞게 읽어옵니다.
    iss >> label1 >> name >> label2 >> age >> label3 >> score;

    std::cout << label1 << " " << name << std::endl;
    std::cout << label2 << " " << age << std::endl;
    std::cout << label3 << " " << score << std::endl;

    return 0;
}

// 출력 결과
// Name: Alice
// Age: 30
// Score: 95.5
  • std::ostringstream
    • output string stream의 약자로, 출력 스트림으로만 작동합니다.
    • 데이터를 문자열로 출력하는데 사용됩니다.
    • ostringstream 객체를 사용해 여러 자료형을 문자열로 합쳐줍니다.
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip> // setprecision 등을 위해 포함

int main()
{
    int id = 101;
    std::string status = "Active";
    double balance = 12345.678;

    std::ostringstream oss;

    // << 연산자를 사용하여 다양한 데이터를 스트림에 씀
    oss << "User ID: " << id
        << ", Status: " << status
        << ", Balance: " << std::fixed << std::setprecision(2) << balance;
        // setprecision 등으로 출력 형식을 제어할 수 있음

    std::string user_info = oss.str();

    std::cout << user_info << std::endl;

    return 0;
}

// 출력 결과
// User ID: 101, Status: Active, Balance: 12345.68
  • std::stringstream
    • 입 • 출력 스트림을 모두 다룰 수 있는 객체입니다.
    • istringstream, ostringstream 기능을 모두 포함하고 있습니다.

[정리]

stringstream에 대해 확실히 알아두어, 나중에 공백 관련 문자열 문제가 나오더라도 잘 풀 수 있게 준비해둬야겠습니다.


[Solution : BAEKJOON 환경 이용]

#include <iostream>
#include <string>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	string str;

	int answer = 0;

	while (cin >> str)
	{
		++answer;
	}

	cout << answer;

	return 0;
}

 

[Solution : stringstream 활용]

#include <iostream>
#include <string>
#include <sstream> 

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	string str;
	getline(std::cin, str);

	stringstream ss(str);
	string word;         
	int answer = 0;      

	while (ss >> word)
	{
		answer++;
	}

	std::cout << answer;

	return 0;
}

[BAEKJOON 10809번 : 알파벳 찾기]

[문제]


[고찰]

해당 문제는 기존에 풀었던 문제 중 인덱스와 관련된 문제들과 아주 유사합니다.

다만, 아스키코드를 활용한다는 측면에서 조금 다릅니다.

 

BAEKJOON 5597번 : 과제 안 내신 분..?

 

[코딩테스트 15일차] BAEKJOON 5073번, 5597번

[BAEKJOON 5073번 : 삼각형과 세 변][문제] [고찰] 해당 문제에 대해 저는 아래의 코드로 답변을 냈습니다.답변은 정답이긴 했지만, 제출하고 나니 if문을 중첩하여 사용할 필요가 없었다는 것을 깨달

sunlight-dby.tistory.com

BAEKJOON 3052번 : 나머지

 

 

[코딩테스트 16일차] BAEKJOON 3052번 : 나머지

[BAEKJOON 3052번 : 나머지][문제] [고찰] 해당 문제는 10개의 수를 42로 나눈 나머지의 값들 중, 서로 다른 값이 몇 개인지를 파악하면 되는 문제입니다.저는 문제대로 접근을 했고, 해당 답변으로 문

sunlight-dby.tistory.com

 

저도 어렵지 않게 풀 수 있었지만, 배열의 모든 값을 −1로 초기화해야 한다는 부분에서 좀 애먹었습니다.

그래서 배열의 초기화와 더불어 벡터를 사용할 때는 어떻게 초기화할 수 있는지를 정리하였습니다.


[개념]

[std::fill]

  • 헤더 파일
    • <algorithm>
  • 함수 원형
    • template <class ForwardIterator, class T>
      void fill (ForwardIterator first, ForwardIterator last, const T& val);
    • ForwardIterator
      • 반복자의 카테고리 중 하나입니다. std::fill은 최소한 순항 반복자(Forward Iterator)를 요구합니다.
        배열의 포인터나 std::vector, std::list 등 대부분의 표준 컨테이너가 제공하는 반복자는 ForwardIterator의 요구사항을 만족합니다.
    • first : 채우기 시작할 범위의 시작을 가리키는 반복자(또는 포인터)입니다. 이 위치에 있는 요소부터 값이 변경됩니다.
    • last : 채우기 끝의 바로 다음 위치를 가리키는 반복자(또는 포인터)입니다. 이 위치에 있는 요소는 변경되지 않습니다.
    • val : 범위 내의 모든 요소에 할당할 값입니다. const T& 형태로 전달되어 값의 복사를 피할 수 있습니다.
  • 예시
int my_array[5];
std::fill(my_array, my_array + 5, -1);
// my_array : -1 -1 -1 -1 -1

vector<int> my_vector(5);
std::fill(my_vector.begin(), my_vector.end(), 5);
// my_vector : 5 5 5 5 5

 

[벡터의 선언 및 초기화]

벡터는 선언과 동시에 초기화하면서 모든 요소를 특정 값으로 채울 수 있습니다.

std::vector의 생성자 중 하나가 이 기능을 제공합니다.

 

해당 생성자 오버로드 중 하나는 다음과 같은 형태입니다.

explicit vector(size_type count, const T& value, const Allocator& alloc = Allocator());
  • size_type count : 벡터의 초기 크기입니다.
  • const T& value : 생성될 모든 요소에 할당될 값입니다.
  • Allocator : 메모리 할당자를 지정하는 부분으로, 일반적으로 기본값을 사용하기 때문에 큰 신경을 쓰지 않아도 됩니다.

[예시]

vector<int> answer(26, -1);

 

※ Allocator (할당자)

Allocator는 컨테이너가 필요로 하는 메모리를 시스템으로부터 얻어오고(allocation), 더 이상 필요 없을 때 시스템에 반환하며(deallocation), 할당된 메모리 공간에 객체를 생성하고 소멸시키는 역할을 담당합니다.


[정리]

사소한 부분도 모두 알아놔야 더 쾌적한 프로그래밍이 될 것이라 명심하고 더욱 더 정진해야겠습니다.


[Solution]

#include <iostream>
#include <string>

using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    string s;
    int answer[26];
    std::fill(answer, answer + 26, -1);
    
    cin >> s;
    
    for (int i = 0; i < s.length(); ++i)
    {
        if (answer[s[i] - 97] == -1)
            answer[s[i] - 97] = i;
    }
    
    for (int i = 0; i < 26; ++i)
        cout << answer[i] << " ";
        
    return 0;
}