알고리즘(코딩테스트)

string 관련 함수들 (tolower, isalpha, transform)

gbleem 2025. 1. 3. 14:55

문제 풀다가 접하게 된 string 처리 관련 함수를 정리해 보았다.

참고한 자료는

https://modoocode.com/275

 

C++ 레퍼런스 - transform 함수

모두의 코드 C++ 레퍼런스 - transform 함수 작성일 : 2019-04-19 이 글은 21195 번 읽혔습니다. std::transform 은 범위 내 (first 부터 last 전 까지) 원소들 각각에 대해 인자로 전달한 함수를 실행 한 후, 그 결

modoocode.com

https://en.cppreference.com/w/

 

cppreference.com

Null-terminated strings:    byte  −   multibyte  −   wide

en.cppreference.com

그리고 chat gpt이다.

 

1. tolower, toupper

int tolower(int ch);
  • cctype 헤더에 정의되어있고, 함수 시그니처가 위처럼 생겼다.
  • 문자를 10진수로 변환시켜 들어간 후, 대문자인 경우 소문자로 바꿔주는 함수이다.
    • toupper는 말 그대로 대문자를 소문자로 바꿔준다.
    • 만약 알파벳이 아닌 것이나 숫자, 공백등을 넣으면 값이 바뀌지 않고 그대로 출력된다.
  • 예시코드
#include <iostream>
#include <cctype>
using namespace std;

int main()
{
	string str = "ab12@ 2";

	for (int i = 0; i < str.size(); ++i)
	{
		str[i] = toupper(str[i]);
	}

	for (auto s : str)
	{
		cout << s; //AB12@ 2
	}
}

 

출력값

2. isalpha

int isalpha(int ch);
  • islower 함수와 마찬가지로, 같은 형태의 함수이다. 이 함수 또한 cctype 헤더에 정의되어있다.
  • input으로 char 를 받고 출력으로 문자인 경우 0이 아닌 값을, 문자가 아니면 0을 반환한다.
  • 예시코드
#include <iostream>
#include <cctype>
using namespace std;

int main()
{
	string str = "ab12@ 2";

	for (int i = 0; i < str.size(); ++i)
	{
		if (isalpha(str[i]))
		{
			cout << "alpha : " << str[i] << "\n";
		}
		else if (isdigit(str[i]))
		{
			cout << "digit: " << str[i] << "\n";
		}
		//isalnum
	}
}

출력값

3. transform

//1
template<class InputIt, class OutputIt, class UnaryOP>
OuputIt transform (InputIt first1, InputIt last1, OuputIt d_first, UnaryOp unary_op);

//2
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class UnaryOp >
ForwardIt2 transform( ExecutionPolicy&& policy,
	ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 d_first, UnaryOp unary_op );
   
//3
template< class InputIt1, class InputIt2, class OutputIt, class BinaryOp >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, 
 	OutputIt d_first, BinaryOp binary_op );
    
 //4
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3, 
 				class BinaryOp >
ForwardIt3 transform( ExecutionPolicy&& policy,
                      ForwardIt1 first1, ForwardIt1 last1,
                      ForwardIt2 first2,
                      ForwardIt3 d_first, BinaryOp binary_op );
  • 이 함수는 algorithm 헤더에 정의 되어 있다. 위처럼 네가지 방식으로 사용이 가능하다.
  • 이 함수의 기본적인 동작은 주어진 입력 범위인  [first, last) 안에 원소 각각에 인자로 전달한 주어진 함수를 적용하고, 결과를 d_first부터 시작하는 iterator에 저장하는 함수이다.
  • 예제를 통해서 사용법을 자세히 살펴보자
    • 1번은 단항 함수(원소가 한개인 함수)를 사용하며, first1부터 last1 까지 unary_op를 적용한 값을 d_first로 시작하는 iterator에 저장하는 기능을 한다.
    • 3번은 이상 함수(원소가 두개인 함수)를 통해 first1부터 last1까지와 first2 부터 시작되는 원소를 binary_op를 통해 쌍을 지어 함수를 실행하고 d_first에 저장한다.
        • 이때 주의할 것은 first1부터 시작하는 iterator가 first2보다 크다면, end iterator보다 더 탐색했다는 런타임 에러가 발생한다.
    • 2번과 4번은 각각의 방식에 ExecutionPolicy를 추가한 함수이다.
//단항함수 vector에 사용
void foo1()
{
	vector<int> input = { 1,2,3,4,5 };
	vector<int> output(input.size());

	transform(input.begin(), input.end(), output.begin(), [](int x) {return x * x; });

	for (auto i : input)
	{
		cout << i << " "; //1 2 3 4 5
	}
	cout << "\n";
	for (auto o : output)
	{
		cout << o << " "; //1 4 9 16 25
	}
}

//단항함수, string에 사용
void foo2()
{
	string str("Hello");

	transform(str.begin(), str.end(), str.begin(), toupper);

	for (auto s : str)
	{
		cout << s ; //HELLO
	}
}

//이항함수
void foo3()
{
	vector<int> vec1 = { 1,2,3,4,5 };
	vector<int> vec2 = { 10,20,30,40,50 };
	vector<int> res(vec1.size());

	transform(vec1.begin(), vec1.end(), vec2.begin(), res.begin(), [](int x, int y) {return x + y; });

	for (auto r : res)
	{
		cout << r << " "; //11 22 33 44 55
	}
	cout << "\n";
}
  • for_each VS transform
    • 기본적인 동작은 비슷하지만, 반환 결과의 저장 유무가 가장 큰 차이점인 것 같다.
    •  for_each
      • 원소를 수정하지 않는 것이 기본, 그러나 함수에 레퍼런스로 값을 받는다면 수정은 가능해 진다.
      • 리턴값이 없고(함수 객체를 리턴하는 경우도 있다), 원소들을 순차대로 접근하는 것이 보장된다. 
    • transform
      • 원소를 수정하고, 함수의 리턴값으로 해당 원소가 바뀐다.
      • 모든 원소에 접근하는 것은 맞지만, 순서대로 원소들에 접근하는 것을 보장하지 않는다.
void to_lowercase_inplace(char& c) //reference
{
	c = tolower(c);
}
void foo4()
{
	string str("Hello!");
	transform(str.begin(), str.end(), str.begin(), toupper);	
	cout << str << "\n";

	for_each(str.begin(), str.end(), tolower);
	cout << str << "\n";

	for_each(str.begin(), str.end(), to_lowercase_inplace);
	cout << str << "\n";
	
	vector<int> vec = { 1,2,3,4,5 };
	for_each(vec.begin(), vec.end(), [](int n) {n++; });
	
	for (auto v : vec)
	{
		cout << v << " ";
	}
	cout << "\n";
	for_each(vec.begin(), vec.end(), [](int& n) {n++; });

	for (auto v : vec)
	{
		cout << v << " ";
	}
}