remove(), string::erase 함수

출처 : https://www.cplusplus.com/



1. function template std::remove

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);


  • 이 함수는 #include < algorithm > 헤더에 있는 remove이다. 파일명을 확인해서 파일을 제거하는 remove 함수는 cstdio 헤더파일에 포함되어 있다.

  • 구성은 단순하다. 첫번째와 두번째 파라미터로 삭제할 범위의 이터레이터를 넣으면 된다. 이터레이터의 특징은 범위가 [first, last) 즉 first 이상 last 미만이라는 점이다.

  • 세번째 파라미터는 이터레이터를 돌며 삭제할 값이다.

  • 반환값으로 제거되지 않은 마지막 원소의 이터레이터(쉽게 여기선 위치라고 생각하자)를 반환한다고 되어 있다.



예제

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
	string str1;

	getline(cin, str1);

	remove(str1.begin(), str1.end(), ' ');

	for (string::iterator it = str1.begin(); it != str1.end(); ++it)
		cout << *it;

	cout << endl;

	return 0;
}


결과 remove함수 예시


  • 위 코드에서는 입력받은 str1에서 스페이스 ‘ ‘를 제거하는 코드이다.
  • 키보드를 통해 for ever young을 입력했다.(빨간색 check는 스페이스를 표현한 것이다)
  • 결과값이 이상하다. for ever young에서 space를 제거하면 foreveryoung이 나올 줄 알았는데 foreveryoungng라고 뒤에 ng가 더 있음을 알 수 있다.
  • 일반적으로 STL의 컨테이너들이 가지고 있는 remove 함수와 다르게 이 remove 함수는 작동방식이 다르다. 함수 호출시 3번째 인자로 넘어온 값(여기선 스페이스)와 같은 값을 찾고 찾은 값(여기선 스페이스)의 다음 요소(여기선 문자)부터 마지막 요소까지 모두 한칸 앞으로 카피하는 방식으로 작동하기 때문이다.
  • 즉 for ever young에서 r 다음에 있는 스페이스를 발견하고 그 뒤에 있는 e부터 young의 g까지 전부 한칸씩 앞으로 복사하다 보니 마지막에 있던 ng도 출력된다.



2. std::string::erase

sequence (1)
 string& erase (size_t pos = 0, size_t len = npos);

character (2)
iterator erase (const_iterator p);

range (3)
iterator erase (const_iterator first, const_iterator last);
  • 이 erase 함수는 string 클래스에 있는 public 멤버함수이다.
  • erase하는 방법은 총 3가지가 있다.


// string::erase
#include <iostream>
#include <string>

int main ()
{
  std::string str ("This is an example sentence.");
  std::cout << str << '\n';
                                           // "This is an example sentence."
  str.erase (10,8);                        //            ^^^^^^^^
  std::cout << str << '\n';
                                           // "This is an sentence."
  str.erase (str.begin()+9);               //           ^
  std::cout << str << '\n';
                                           // "This is a sentence."
  str.erase (str.begin()+5, str.end()-9);  //       ^^^^^
  std::cout << str << '\n';
                                           // "This sentence."
  return 0;
}
  • 첫번째 방법은, 기준점(pos)을 넣고 기준점으로부터 몇개의 문자들을 지울지 적는 것이다. string 컨테이너도 시퀀스 컨테이너이며 배열 기반 컨테이너 범주에 속한다. 따라서 배열의 index가 0부터 시작하듯이 string을 이용한 문자열도 맨 앞이 0부터 시작한다. 위 코드에서 str.erase (10,8); 를 통해 기준점이 10(맨 앞이 0이므로 사실상 11번째)인 문자부터 8개를 지운다고 되어 있다. T가 기준점이 0인 곳이고 example의 e앞의 스페이스가 10인 곳이다. 기준점으로부터 카운트 할 때 스페이스도 포함해야 한다. 스페이스 + example이 10, 11, 12, 13, 14, 15, 16, 17이 총 8개이므로 example이 erase된다.

  • 두번째 방법은, 이터레이터를 사용해서 특정 지점을 지정하는 것이다. 위 코드에서 str.erase (str.begin()+9); 를 사용해 맨 처음에서 9번째에 있는 문자를 지정했다.

  • 세번째 방법으로 이터레이터를 사용해서 범위를 지정하는 방법이다.



3. remove()와 std::string::erase 같이 쓰기

예제

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
	string str1;

	getline(cin, str1);

	str1.erase(remove(str1.begin(), str1.end(), ' '), str1.end());

	for (string::iterator it = str1.begin(); it != str1.end(); ++it)
		cout << *it;

	cout << endl;

	return 0;
}

결과 remove함수예시2

  • 1번에서 단순 remove() 함수를 이용해서 스페이스를 제거했을시 foreveryoungng이란 문제가 발생했다. 하지만 remove와 erase 함수를 활용하면 이런 문제점을 해결 할 수 있다.
  • remove() 함수는 제거하지 않은(움직이지 않은) 마지막 원소의 이터레이터(위치)를 반환한다.

  • 위의 for ever young 예시에서

for ever young

foreveryoungng

youngng에서 두 번째 n의 위치를 이터레이터로 반환한다. erase 함수는 두 번째 n부터 str1.end()까지 글자를 삭제하므로 따라서 ng가 삭제되고 출력은 원했던 foreveryoung으로 나오게 된다.

4. anagram 함수 만들때 2

bool IsAnagram(string str1, string str2)
{
  transform(str1.begin(), str1.end(), str1.begin(), toupper);

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

  str1.erase(remove(str1.begin(), str1.end(), ' '), str1.end());

  str2.erase(remove(str2.begin(), str2.end(), ' '), str2.end());
}

–> 이런 식으로 anagram을 판별하는 함수를 만들 수 있다. transform을 활용해서 전부 문자열을 전부 대문자로 바꾼후에 erase와 remove 함수를 활용하여 문자열 사이에 스페이스를 제거하는 방식이다. 그후에 std::sort 함수를 이용하여 문자열을 크기 순(아스키 코드상 값 순)으로 바꾼 후에 비교하면 두 문자열이 anagram인지 아닌지 알 수 있다.