[C언어, C++언어, JAVA언어 라이브러리 및 함수 메서드 링크 ]
[C/C++]
string은 문자열을 담는 클래스잖아요?
하지만 헤더를 '#include<cstring>'이나 '#include<string.h>'로 놓고 문자열을 출력해보면 빨간 줄!! 불가능하다고 뜨는 걸 본적이 있어요.
그런데 이 헤더선언문을 #include<string>으로 바꿔주면 빨간 줄이 뜨고 컴파일이 잘 됩니다. 도대체 무슨 차이가 있는 걸까요~?
cstring vs string.h
The 'cstring' header provides functions for dealing with C-style strings - null-terminated arrays of characters. This includes functions like 'strlen' and 'strcpy'. it's the C++ version of the classic 'string.h' header from C.
C는 입출력함수로 #inlcude<stdio.h>를 놓고, C++은 #include<iostream>을 놓고 시작하죠?
이렇듯 C에는 '.h'로 끝나는 라이브러리가 대부분이예요. 똑같은 클래스를 C++형태로 바꿀 때, 암묵적으로 보통 뒤의 '.h'를 지우고 대신 앞에 'c'를 붙여줍니다.
← 그래서 라이브러리를 확인해보면 cstring외에도 앞에 c가 붙는 c++라이브러리가 많다는 것을 알 수 있어요. 간단하게는 cstring = string.h라고 생각하셔도 무방합니다.
문자열 길이를 리턴해주는 'strlen'함수나 문자열 복사해주는 'strcpy' 등의 함수를 사용할 수 있습니다.
그럼, cstring과 string 클래스 라이브러리의 차이는 뭘까요?
1. 원리 - 문자열을 어떻게 저장하는가?
C에서 문자열 저장할 때, 우리는 배열을 쓰는걸 알고 있어요.
#include <iostream>
using namespace std;
int main()
{
char string_Arr[] = "hello in array";
const char* stringPt = "hello with pointer";
cout << string_Arr << "\n";
cout << stringPt;
return 0;
}
C에서는 이렇게 문자열을 출력하죠!
즉 C에서는 문자열을 배열에 저장하고, 지막에 문자열 끝이라는 신호를 주기 위해 '\0' 널문자가 삽입되기 때문에 배열 사이즈가 실제 문자열 사이즈보다 1커요. 이건 다 배웠던 거니깜~~ 간략히만 짚고 넘어왔어요. 이 게 C스타~일, 널로 종료되는 배열 기반의 문자열을 가지고 유용한 함수를 구현한게 cstring 라이브러리입니다.
2. cstring의 문제
근데 이게 사용하다보니까 불편한게 너무 많은 거예요. 일단 C배열은 자신의 크기를 알 수 없어요. 문자열 쓸때마다 사이즈를 알려면 매번 strlen함수를 사용해줘야합니다. 뭔가 어딘가에 할당해주려면 문자열 하나마다 매~~~번 strlen하고 strcpy하고 C를 조금 해보신 사람들은 많이 겪어봤을 거예요. (잘 모르는 사람이면 앞으로 주구장창 겪을 ..)
class NameCard
{
char* name;
char* Comp;
char* phone;
int position;
public:
NameCard(char* initname, char* initComp, char* initphone, int initpostion)
{
int leng = strlen(initname) + 1;
name = new char[leng];
strcpy(name, leng, initname);
leng = strlen(initComp) + 1;
Comp = new char[leng];
strcpy(Comp, leng, initComp);
leng = strlen(initphone) + 1;
phone = new char[leng];
strcpy(phone, leng, initphone);
position = initpostion;
}
~NameCard()
{
delete[] name;
delete[] Comp;
delete[] phone;
}
}
하나의 예시를 가져왔어요. '명함'을 정의한건데 명함에는 이름(name), 회사(comp), 전번(phone), position(직급)등이 적혀있어요.
그런데 저 안에 보시면 문자열 저장할 이런 변수들 어떤 처리 때문에 strlen함수와 strcpy가 게속 쓰이는 걸 볼 수 있죠? (코드 해석을 못하더라도 아 좀 번거롭구나 정도 이해하면 됩니다)
또 cstring은 직관성이 떨어진다는 문제를 갖습니다. 문자를 비교할 때, strcmp라는 함수를 호출해서 쓰고, 문자열을 붙일 때 strcat이라는 함수를 호출해서 쓰죠? 즉 우리는 매번 함수이름을 정확히 알고 있어야하고, 매개변수로 뭘 전달해줄지 문법을 알고 있어야해요. "hello" + "my name" 이런식으로 직관적으로 쓸 수 있음 얼마나 좋겠어요~ 이것들을 정리해준게 std::string 즉 string라이브러리입니다.
맨날 널 생각해서 한 사이즈 크게 만드는것도 (코드 보면 strlen()다음에 +1이 있는 것은 널때문이예요)
이 배열크기가 실제로 달라(boundary condition) 반복문이든, 계산할 때 신경써줘야하는거에서 사람들이 실수를 종종 하는데 이처럼 하나 차이 때문에 나는 버그를 off-by-one bugs 라고 불러요.
코드 가독성도 떨어지고 계산할 때마다 그 놈의 배열 크기 때문에 신경써야 하는게 한두게도 아니고 그 외에 불편한 문제점들이 많아요. ~~!
3. C++의 std::string과 발전된 특징
이런 cstring의 불편했던 점들을 개선하기 위해, 이런 밑단 문자열들을 관리하기 위해 새로 만든 포장박스!(class)가 std::string입니다. 좀 편하게 쓸 수 있게 문자열을 새로 정의해서 내부적으로 불편한 것들을 자동으로 처리해주는거죠.
The string header provides the std::string class and related functions and operators.
std::string을 사용하는 것이 string라이브러리입니다. 연산자(아까 위에서 예시로 들었던 +같은거)랑 메서드를 제공해줘요.
The headers have similar names, but they're not really related beyond that. They cover separate tasks.
헤더는 이름이 매우 비슷한데, 'cstring'이랑 'string'이니까 헷갈릴만하죠?ㅎㅎ 근데 커버하는 게 완전 달라요.
달라진 몇가지 특징만 뽑아볼까요?
1. Flexible storage capacity,
사이즈를 드디어 자유자래로 늘였다 줄였다 편하게 할 수 있어요. 매번 선언하고 크기 재할당 일일이 설정 안해줘도 된다는거죠.
2. No need to worry about manual memory management or resizing strings
이제는 메모리 매번 신경쓸 필요도 없고 문자열 재할당 할 필요도 없어요
3. Boundary issues are handled for me, with or without a null character.
이말은 널때문에 발생했던 boundary issue가 이제 발생하지 않는다는 거 (알아서 해주니까)
4. Intuitive assignment using = operator rather than strcpy
strcpy함수 쓸 필요 없이 '='만으로 자동으로 복사해줍니다. 깊은 복사든 얕은 복사든 이제 신경 안써도 돼요. strcpy 매개변수로 뭐가 들거아야하는지 신경쓸 필요 없습니다!
5. Intuitive comparison using the ==operator rather than strcmp
마찬가지 문자열 비교할 때 strcmp함수를 썻어야 했잖아요? 간단하게 '=='가 해결해줍니다. 숫자비교할 때처럼 직관적으로 사용할 수 있어요. (문자열 붙이는데 +사용도 동일!)
#include <iostream>
#include <string>
using namespace std;
int main()
{
string st = "hello1!";
string st2("hello2");
string filledst(20, 'A');
if (st < st2)
{
cout <<"st1 comes first lexicographically";
}
return 0;
}
string은 클래스이기 때문에 초기화를 name("~~")이런 형식으로 해줄 수 있습니다.
많은 기능들이 오버로딩되어 있어요
즉 !! 이왕 문자열 쓸거면 string 라이브러리를 써서 편하게 사용하자! 더 많은 기능은 string 포스팅을 따로 빼서 알아볼게요~
'별걸다하는 IT > 프로그래밍언어' 카테고리의 다른 글
C언어 문자열 istream::getline()과 C++ string의 getline()! 한 줄 읽는 함수가 두 개? (10) | 2019.02.27 |
---|---|
[C,C++ 강좌]C언어의 꽃 포인터 총정리(*, &), 포인터 사용 예시, 포인터 연산자 (7) | 2019.02.23 |
[Java 자바 입출력] BufferedReader/BufferedWriter (17) | 2019.02.19 |
[C/C++/C#]프로그램 구조(structure)-전처리기, 전역, 메인, 함수구간 (2) | 2019.02.17 |
함수(function)란? 함수의 종류, 함수 역할 및 기능, 메인(Main)함수 (6) | 2019.02.16 |
최신 댓글