문자열 string
본 내용에 앞서 지난 chpt2 에서 다룬 getline 에 대해 잠깐 살펴보고자 한다.
char line[256];
cin.getline(line, 256);
위 코드에서는 현재 두 가지 문제점을 가지고 있다
- 아무것도 읽지 못했을 때의 동작
- 문장 길이가 256 을 넘겼을 때의 동작(주어진 버퍼의 크기보다 문장길이가 클 때)
또한 코드 표준 시각에서 바라봤을 때도 그리 좋은 코드는 아니다
현재 위 코드에선 '256' 이라는 어떠한 기준 값을 직접적으로 숫자로 작성한 것을 '매직넘버'라고 부른다
매직넘버의 단점
- 256 이 왜 256 으로 설정했는지는 기존 지식을 인지한 사람만 이해할 수 있음
- 같은 숫자가 여러 곳에 있을 때 수정이 어렵고 실수하기 쉬움
- 256 이란 숫자가 다른 의미로도 사용했을 경우 헷갈릴 수 있음
- 정책 변경 시(PC 의 최대값이 바뀐다거나) 모든 코드에서 직접 하나하나 수정해야 됨
그래서 아래와 같은 방식을 추구함
#define LINE_LENGTH 256;
char line[LINE_LENGTH];
getline(line, LINE_LENGTH);
다시 본론으로 돌아와서 getline 의 단점을 보완하고자 C++ 에서는 std::string 클래스를 지원하고 있다.
#include <string>
std::string firstName;
std::cin >> firstName;
std::string 클래스를 이용한 문자열은 길이가 증가할 수 있다.
아래의 여러 예시들을 통해 C 와 비교하면서 알아보자
대입(assignment) 과 덧붙이기(appeding)
// C
char firstName[20] = "POPE";
char fullName[20];
// 대입 - 안전하지 않음
strcpy(fullName, firstName);
// 덧붙이기 - 안전하지 않음
strcat(fullName, " KIM");
-----------------------------------------------------------
// C++
string firstName = "POPE";
string fullName = "John Doe";
// 대입
fullName = firstName;
// 덧붙이기
fullName += " KIM";
문자열 합치기(concatenation)
// C
char fistaName[20] = "POPE";
char lastName[20] = "KIM";
char fullName[40];
snprintf(fullname, 40, %s %s, firstName, lastName);
---------------------------------------------------------------------------------
// C++
string firstName = "POPE";
string lastName = "KIM";
string fullName;
fullName = firstname + " " + lastName;
비교(relational)연산자
// C
if (strcmp(firstName1, firstName2) == 0)
{
}
if (strcmp(firstName1, firstName2) > 0)
{
}
-------------------------------------------------------------------
// C++
if (firstName1 == firstName2)
{
}
if (firstName1 > firstName2)
{
}
size(), length(), c_str()
size(), length()
문자열 길이를 반환
cout << firstName.size() << endl;
cout << firstname.length() << endl;
c_str()
const char* 반환
해당 string 이 가지고 있는 문자 배열의 시작 주소를 가라키는 포인터를 반환
C++ 은 C 와 같이 동작할 수 있게 구조되었으며 C 는 string 클래스가 배열로된 string 을 사용하기 때문에 그에 맞춰 동작될 수 있도록 만들어진 기능
또한 운영체제 함수 호출시에도 대부분 C 기반이라 char * 를 요구하기 때문이기도 하다
string line;
cin >> line;
cost char* cLine = line.c_str();
string 내부 문자 바꾸기
C 와 같은 방식
string firstName = "POKE";
char letter = firstName[1];
// 문자 변환
firstName[2] = 'P';
-----------------------------------------
[2] <- 이 부분은 함수로써 반환값을 통해 해당 문자를 접근하며, 참조를 통해 반환한다.
std::string 내부 구현 (간소화)
char& operator[](std::size_t pos); // 비-const 버전
const char& operator[](std::size_t pos) const; // const 버전
비 const 객체에서 []를 호출하면 참조(char&) 를 반환
const 객체에서 호출하면 읽기 전용 참조(const char&) 반환
at() 방식
char letter = firstname.at(1);
firstname.at(2) = 'P';
문장 한 줄 읽기
string mailHeader;
getline(cin, mailHeader); // '\n' 만날 때까지 cin 에서 문자들을 꺼내서 mailHeader 에 저장
getline(cin, mailHeader, '@'); // '@' 문자 만날 때까지 cin 에서 문자들을 꺼내서 mailHeader 에 저장
구분자(기본: '\n') 를 만나거나 EOF 를 만나면 종료한다.
sstream
자주 사용되지는 않지만 일다 조금만 살펴보자
std::istringstream
- cin 과 비슷, 키보드 대신 string 으로부터 읽어옴
- sscanf() 와 비슷
std::ostringstream
- cout 과 비슷, 콘솔 대신 string 에 출력
- sprintf() 와 비슷
참고 : cout, cin 도 스트림
C++ 에서 C 헤더 사용 방법
C | C++ |
<string.h> | <cstring> |
<stdio.h> | <cstdio> |
<ctype.h> | <cctype> |
기존 C 에서 '.h' 를 빼고, C 함수임을 알리기 위해 해당 해더 앞에 'c' 를 추가
string 활용 예문
문자열 뒤집어 덧붙이기
#include <iostream>
#inlcude <string>
#inlcude "MirrorString.h"
using namespace std;
namespace samples
{
void MirrorStringExample()
{
string line = "hello world!";
cout << "string to mirro: " << line << endl;
for (int i = (int)line.size() - 1;. i >= 0; --i)
{
line += line[i];
}
cout << "Mirrored String" << line << endl;
}
}
int main()
{
samples::MirrorStringExample();
return 0;
}
'C++ > FOCU_C++' 카테고리의 다른 글
C++ chpt6. (1) | 2025.05.16 |
---|---|
C++ chpt5. (0) | 2025.05.04 |
C++ chtp3. (0) | 2025.05.03 |
C++ chpt2. (0) | 2025.04.29 |
C++ chpt1. (0) | 2025.04.28 |