📕Programming/📝C/C++

[C / C++] 문자열

주으기 2023. 9. 14. 11:18
728x90
반응형

문자열(string)이란 일련의 연속된 문자(character)들의 집합이다.

 

C++에서는 이러한 문자열을 C언어 스타일의 문자열, string 클래스를 이용한 문자열 이렇게 두 가지 방법으로 생성할 수 있다.

 

--------------------------------------------------------------------------------------------------------------------------------

 

1. 널(NULL) 문자

C++에서 문자열 변수는 문자열의 끝을 프로그램에 따로 알려주어야 한다.

 

그래야만 프로그램이 실제 문자열에 속한 값과 그 외에 쓰레깃값으로 구분할 수 있다.

따라서 문자열이 끝나면, 문자열의 끝을 의미하는 문자를 하나 더 삽입해 준다.

 

이러한 문자를 널(NULL) 문자라고 하며, \0으로 표시하고 아스키코드값은 0이다.

 

널 문자의 유무로 문자형 데이터 배열과 문자열을 서로 구분할 수 있다.

 

--------------------------------------------------------------------------------------------------------------------------------

 

2. C언어 스타일 문자열

문자형 자료형인 char을 배열 형식으로 여러 개 묶으면 그게 곧 문자열 변수가 된다.

int main()
{
	const int SIZE = 20;	// 실제 입력은 19자 (\0이 한 칸 차지)
	char name[SIZE];
	char gender[SIZE];

	cout << "이름을 입력하세요! : ";
	cin >> name;
	cout << "성별을 입력하세요! : ";
	cin >> gender;

	cout << "이름 : " << name << " | 성별 : " << gender << endl;

	return 0;
}
/*실행 결과
이름을 입력하세요! : 홍길동
성별을 입력하세요! : 남자
이름 : 홍길동 | 성별 : 남자
*/

C++에서 문자형 배열로 문자열을 입력받기 위해서는 문자열이 저장될 문자형 배열을 미리 생성해놔야 한다.

 

하지만 여기에는 다음과 같은 두 가지 문제가 있는데,

1. 문자열에 띄어쓰기가 들어가면 안 된다.

2. 20byte 이상의 문자열을 입력하면 프로그램이 강제 종료된다.

 

C++에서 cin 객체는 띄어쓰기를 포함한 탭 문자, 캐리지 리턴 문자 등을 모두 문자열의 끝으로 인식한다.

 

따라서 띄어쓰기를 포함한 문자열을 전부 입력받고, 데이터 크기에 상관없이 입력받으려면 cin 객체의 get() 메소드와 ignore() 메소드를 사용해야 한다.

 

int main()
{
	const int SIZE = 20;
	char name[SIZE];
	char gender[SIZE];

	cout << "이름을 입력하세요! : ";
	cin.get(name, SIZE).ignore(SIZE, '\n');
	cout << "성별을 입력하세요! : ";
	cin.get(gender, SIZE).ignore(SIZE, '\n');

	cout << "이름 : " << name << " | 성별 : " << gender << endl;

	return 0;
}
/*실행 결과
이름을 입력하세요! : abcd efgh ijkl mnop qrst uvwx
성별을 입력하세요! : qweasddfgcvb  qw eeqqqaz
이름 : abcd efgh ijkl mnop | 성별 : qweasddfgcvb  qw ee
*/

위의 예제는 get() 메소드를 사용하여 띄어쓰기를 포함한 이름이나 성별을 입력할 수 있다.

 

또한, ignore() 메소드를 사용하여 20byte 이상의 이름이나 성별을 입력해도 정확히 SIZE에 맞는 byte 까지만 입력받고 있다.

 

C언어 스타일의 문자열 입력에서는 입력할 문자형 배열의 길이를 알고 있어야만 한다는 단점이 있다.

 

--------------------------------------------------------------------------------------------------------------------------------

 

3. string 클래스

string 라이브러리를 통해 string 클래스를 이용하면 C언어 스타일의 문자형 배열을 통해 사용하는 문제점들을 쉽게 극복할 수 있다.

 

string 클래스를 사용하기 위해서는 우선 string 헤더 파일을 포함시켜야 하며, std 네임스페이스가 필요하다.

 

string 클래스를 사용할 경우 문자열을 일반 타입처럼 사용할 수 있게 해 주어 일반 변수처럼 사용이 가능하다.

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string str1 = "Hello World!";
	string str2;
	str2 = str1;

	cout << str2 << endl;
	cout << str2[0] << ", " << str2[1] << str2[2] << endl;

	return 0;
}
/*실행 결과
Hello World!
H, el
*/

일반 변수처럼 선언과 동시에 초기화가 가능하며, 변수끼리의 대입도 가능하다.

[]을 이용해 문자형 배열처럼 한 문자씩 접근도 가능하고, 마지막에 NULL문자가 포함되어 있다.

 

string str1 = "Hello ";
string str2 = "World!";

string str3 = str1 + str2;
    
cout << str3 << endl;

/*실행 결과
Hello World!
*/

문자열끼리의 + 연산과 += 연산도 가능하다.

 

int main()
{
	string name, gender;

	cout << "이름을 입력하세요! : ";
	getline(cin, name);
	cout << "성별을 입력하세요! : ";
	getline(cin, gender);

	cout << "이름은 : " << name << " | 성별은 : " << gender << endl;

	return 0;
}
/*실행 결과
이름을 입력하세요! : 홍길 동
성별을 입력하세요! : 남 자
이름은 : 홍길 동 | 성별은 : 남 자
*/

cin 객체의 공백을 문자열의 끝으로 인식하는 문제는 문자열을 한 행씩 읽을 수 있는 getline() 함수를 통해 입력받으면 된다.

 

--------------------------------------------------------------------------------------------------------------------------------

 

4. string 메소드

string 메소드는 string 클래스에 정의된 문자열과 관련된 작업을 할 때 사용한다.

 

1) length(), size()

string str = "Hello";

cout << str.length() << endl;	// 5
cout << str.size() << endl;	// 5

length와 size 모두 같은 같을 반환 하지만 다른 의미를 가진다.

length의 경우 문자열의 길이를 반환하고 size의 경우 객체가 메모리에서 사용하는 크기를 반환한다.

또한, length의 경우 널 문자까지의 길이가 아닌 실제 문자열의 길이만 반환한다.

 

2) append()

문자열의 끝에 새로운 문자열을 추가하는 메소드이다. 사용방법은 다음과 같다.

1) 문자열.append("새로운 문자열");
2) 문자열.append("새로운 문자열", 시작번호, 개수);
string str1 = "Hello";
string str2 = str1;

cout << str1.append(" World!") << endl;
cout << str2.append(" World!", 1, 3) << endl;

// Hello World!
// HelloWor

문자열의 끝에 추가하려는 문자열이 추가되며, 두 번째의 경우 추가하려는 문자열의 1번 인덱스부터 3개의 문자가 입력된다.

 

3) find()

find()는 원하는 문자열의 시작 위치를 반환하는 메소드이다. 사용방법은 다음과 같다.

1) 문자열.find(찾을 문자열);
2) 문자열.find(찾을 문자);
3) 문자열.find(찾을 문자열, 시작 위치);

 

find()는 해당 문자열에서 찾을 문자열을 찾지 못하면, string::size_type의 string::npos라는 상수를 반환한다.

string str1 = "Hello";

cout << str1.find("lo") << endl;
cout << str1.find("l") << endl;
cout << str1.find('o', 3) << endl;

if (str1.find('k') == string::npos)
	cout << "해당 문자열을 찾지 못했습니다!" << endl;
else
	cout << "해당 문자열을 찾았습니다!" << endl;
    
// 3
// 2
// 4
// 해당 문자열을 찾지 못했습니다.

2번째의 경우를 보면 l이 2개가 존재하는데, 처음 만난 l의 위치를 반환한다. 즉 같은 문자열이 여러 개 있으면 그중 제일 앞에 인덱스를 반환한다.

3번째 경우는 시작 위치 인덱스부터 검색하여 해당 문자열을 찾게 된다.

 

4) compare()

compare() 메소드는 두 문자열 간의 내용을 비교하는 메소드이다. 사용방법은 다음과 같다.

기준 문자열.compare(비교할 문자열)

 

만약 두 문자열이 일치한다면 0을 반환한다.

기준 문자열이 비교할 문자열보다 사전 편찬 순으로 앞일 경우 기준. compare(비교) < 0,    뒤일 경우 기준 compare(비교) > 0 이 된다.

string str1 = "Ha";
string str2 = "Hb";

if (str1.compare(str2) == 0)
	cout << "두 문자열 일치" << endl;
else if (str1.compare(str2) < 0)
	cout << str1 << "가 사전편찬 순서 앞" << endl;
else
	cout << str2 << "가 사전편찬 순서 앞" << endl;
   
// Ha가 사전편찬 순서 앞

 

5) replace()

replace() 메소드는 특정 문자열을 다른 문자열로 대체하는 메소드이다. 사용방법은 다음과 같다.

문자열.replace(변경할 문자열 시작 위치, 새로운 문자열 길이, 새로운 문자열);
string str1 = "Hello World!";
string a = "World!";
string b = "Programming!";
int index = 0;

index = str1.find(a);
cout << str1.replace(index, a.length(), b) << endl;

// Hello Programming!

변경할 문자열의 시작 위치를 find() 메소드를 통해 찾는 것이 좋다.

 

6) capacity(), max_size()

capacity() 메소드는 해당 문자열이 재할당받지 않고 저장할 수 있는 최대 문자열의 길이를 반환한다.

max_size() 메소드는 해당 문자열이 최대한 할당받으면 가질 수 있는 최대 문자열의 길이를 반환한다.

string str = "Hello World!";

cout << str.length() << endl;
cout << str.capacity() << endl;
cout << str.max_size() << endl;

// 12
// 15
// 9223372036854775807

 

 

 

 

 

728x90
반응형