const char* :  C-style 문자열을 나타내는 포인터

여기서 C-styel 문자열이란, 말그대로 C 언어에서 사용하는 문자열 표현 방식으로, Null 종료 문자열(Null-terminated string)을 사용하여 문자열을 표현합니다.

Null 종료 문자열은 문자열의 끝에 항상 널 문자('\0')가 포함된 문자열을 의미합니다.

예를 들어, "Hello"라는 문자열은 다음과 같이 C-style 문자열로 표현할 수 있습니다.

 

char str[] = {'H', 'e', 'l', 'l', 'o', '\0'};

 

 

이렇게 문자열을 표현할 경우 문자열의 끝을 알기 위해 널 문자('\0')을 사용합니다.
이를 이용해 문자열의 길이를 계산하거나, 문자열을 다루는 다양한 함수를 사용할 수 있습니다.

다음은 C-style 문자열에서 자주 사용되는 함수들입니다 (c++에서 사용할 경우, <cstring> 헤더 include 필요)

 

1.  strlen() : 문자열 길이 계산

 

const char* str = "Hello, world!";
int length = strlen(str); // 13

 *공백, 특수문자(, !) 등도 포함. null 은 미포함.

2. strcpy() : 문자열 복사

 

char src[] = "Hello";
char dest[10];
strcpy(dest, src);
// dest는 "Hello"로 설정됩니다.

 

3.  strcat() : 문자열 연결

 

char str1[20] = "Hello";
char str2[20] = "World";
strcat(str1, str2);
// str1은 "HelloWorld"로 설정됩니다.

 

4. strcmp() : 두 문자열 비교

 

char str1[] = "Hello";
char str2[] = "World";
int result = strcmp(str1, str2); // 음수 값이 반환됩니다.

 

5. strchr() : 문자열에서 특정 문자 검색

 

const char* str = "Hello, world!";
char ch = 'o';
const char* ptr = strchr(str, ch); // "o, world!"

 

6. strstr() : 특정 문자열 검색

 

const char* str = "Hello, world!";
const char* sub_str = "world";
const char* ptr = strstr(str, sub_str); // "world!"

 

C-style 문자열은 char 배열 형태로 표현됩니다.

 

#include <stdio.h>
#include <string.h>

int main() {
    char str1[20] = "Hello";
    char str2[] = ", world!";
    strcat(str1, str2);
    printf("%s\n", str1);

    char str3[20];
    strncpy(str3, str1 + 7, 5);
    printf("%s\n", str3);

    int result = strcmp(str1, str2);
    printf("%d\n", result);

    char* ptr = strstr(str1, "world");
    if (ptr != NULL) {
        strncpy(ptr, "Earth", 5);
    }
    printf("%s\n", str1);

    return 0;
}

 

위 예제에서는 strcat(), strncpy(), strcmp(), strstr() 등의 함수를 사용하여 C-style 문자열을 배열로 표현하고 조작합니다.
strcat(str1, str2) : str1 끝에 str2를 이어 붙입니다.
strncpy(str3, str1 + 7, 5) : str1의 8번째 문자부터 5개의 문자를 str3에 복사합니다.
strcmp(str1, str2) : str1과 str2를 비교합니다.
strstr(str1, "world") : str1에서 "world" 문자열을 찾습니다.
strncpy(ptr, "Earth", 5) : ptr에서 시작하는 위치에 "Earth" 문자열의 5개 문자를 복사합니다.
그러면 str1에는 "Hello, world!"가 저장되어 있을 것입니다.
strcat() 함수를 사용하여 ", world!" 문자열을 이어 붙여 "Hello, world!"를 완성합니다.
그 다음 strncpy() 함수를 사용하여 str1에서 8번째 문자부터 5개의 문자를 str3에 복사하고,
strcmp() 함수를 사용하여 str1과 str2를 비교합니다.
마지막으로 strstr() 함수를 사용하여 str1에서 "world" 문자열을 찾고, strncpy() 함수를 사용하여 "Earth" 문자열로 대체합니다.

 

출력결과

 

Hello, world!
world
72
Hello, Earth!

 

이 때, 문자열의 크기를 지정하지 않아도 되며, 필요에 따라 문자열의 길이를 동적으로 할당할 수 있습니다.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char* str = NULL;
    size_t len = 0;
    ssize_t read;

    printf("Enter a string: ");
    read = getline(&str, &len, stdin);

    if (read == -1) {
        printf("Error reading input\n");
        return 1;
    }

    printf("Input string: %s\n", str);

    char* str2 = (char*)malloc(strlen(str) + 1);
    strcpy(str2, str);
    printf("Copied string: %s\n", str2);

    free(str);
    free(str2);

    return 0;
}
위 예제에서는 getline() 함수를 사용하여 키보드로부터 입력을 받습니다.
입력된 문자열의 길이에 따라 필요한 만큼 메모리를 동적으로 할당합니다.
그 다음, strcpy() 함수를 사용하여 할당된 메모리에 문자열을 복사합니다.
getline() 함수는 입력된 문자열의 길이와 할당된 메모리의 크기를 반환합니다.
malloc() 함수를 사용하여 문자열의 길이에 따라 필요한 만큼 메모리를 동적으로 할당합니다.
할당된 메모리에 strcpy() 함수를 사용하여 문자열을 복사합니다.
마지막으로 free() 함수를 사용하여 할당된 메모리를 해제합니다.

출력결과

 

Enter a string: Hello, world!
Input string: Hello, world!
Copied string: Hello, world!

 

C-style 문자열은 C++에서도 사용할 수 있습니다

(다만, C++에서는 문자열을 다루기 위해 string 클래스를 사용하는 것이 더 안전하고 편리합니다)

 

*(참고) getline

getline() 함수는 C++의 표준 라이브러리인 <iostream> 헤더 파일에 선언된 함수로,

파일 스트림 또는 입력 스트림에서 한 줄씩 문자열을 읽어올 때 사용됩니다.

getline() 함수는 기본적으로 세 개의 매개변수를 받습니다.

 

getline(std::istream& input_stream, std::string& str, char delimiter='\n');

 

  • input_stream: 입력 스트림 또는 파일 스트림 객체입니다. std::cin, std::ifstream 등이 될 수 있습니다.
  • str: 읽어온 문자열이 저장될 std::string 객체입니다.
  • delimiter: 읽어올 문자열의 끝을 표시하는 구분자입니다. 기본값은 개행 문자('\n')입니다.

getline() 함수는 입력 스트림에서 delimiter 문자를 만나거나 스트림의 끝에 도달할 때까지 문자열을 읽어 str 객체에 저장합니다.
이 때, delimiter 문자는 입력 스트림에서 제거되지 않고 버퍼에 남게 됩니다.

getline() 함수를 사용하면 키보드나 파일 등에서 한 줄씩 문자열을 읽어와 처리할 수 있습니다. getline() 함수를 이용하면, 사용자가 입력한 문자열을 std::string 객체에 저장할 수 있으며, 입력 스트림을 더 이상 읽지 않을 때까지 문자열을 계속해서 읽어올 수 있습니다.

 



 string :  문자열을 다루기 위해 사용하는 c++  표준 라이브러리 클래스

 

string은 문자열을 동적으로 할당하여 저장하고, 문자열의 길이 정보도 함께 저장합니다.

문자열을 수정하거나 추가하는 작업이 자유롭기 때문에 보다 편리하게 문자열을 다룰 수 있습니다.

또한, string 클래스는 C++ 표준 라이브러리의 일부로 제공되기 때문에 라이브러리에서 제공하는 다양한 기능을 사용할 수 있습니다.

 

std::string 클래스의 내부 구현은 크게 두 가지로 나눌 수 있습니다.

첫 번째는 문자열 데이터를 저장하기 위한 메모리 관리를 위한 부분이며,

두 번째는 문자열을 조작하기 위한 멤버 함수들을 구현하는 부분입니다.

 

첫 번째 부분에서는 문자열 데이터를 저장하기 위한 메모리를 할당하고, 필요에 따라 재할당합니다.

문자열 데이터는 동적으로 할당된 메모리 공간에 저장됩니다.

std::string 클래스는 문자열 데이터의 길이와 할당된 메모리 공간의 크기를 구별하며, 이를 통해 문자열 데이터를 조작할 때 메모리를 효율적으로 사용합니다.

두 번째 부분에서는 문자열을 조작하기 위한 멤버 함수들이 구현됩니다.

이러한 멤버 함수들은 문자열 데이터에 직접 접근하지 않고, 문자열 데이터에 대한 포인터와 길이 정보를 사용합니다.

이를 통해 문자열을 조작하는 과정에서 문자열 데이터의 내부 구조가 변경되더라도 멤버 함수들이 제대로 동작할 수 있습니다.

 

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, world!";

    // 문자열 데이터에 접근하는 방법
    const char* data = str.data(); // C-style 문자열로 변환된 데이터 포인터 반환
    std::cout << "Data: " << data << std::endl;

    // 문자열 데이터의 길이를 구하는 방법
    size_t length = str.length();
    std::cout << "Length: " << length << std::endl;

    // 문자열 데이터를 조작하는 방법
    str += " Welcome to the world!";
    std::cout << "Modified string: " << str << std::endl;

    return 0;
}
이 예제 코드에서는 std::string 클래스의 객체를 생성하고, 이를 통해 문자열 데이터를 다루는 방법을 보여줍니다.
먼저, 문자열 데이터에 접근하는 방법은 data라는 std::strring 클래스 멤버함수를 통해 할 수 있습니다.
data() 멤버 함수를 통해 내부 문자열 데이터의 C-style 문자열 형태로 변환된 데이터 포인터를 반환합니다.
이 포인터를 이용하면 std::string 클래스가 제공하지 않는 C-style 문자열 함수를 사용할 수 있습니다.

문자열 데이터의 길이를 구하는 방법 또한 std::string 클래스 멤버함수인 length() 통해 구할 수 있습니다.

 

단, 이 함수는 문자열 데이터가 저장된 메모리의 크기와는 다릅니다.

std::string 클래스는 문자열 데이터의 길이와 할당된 메모리 공간의 크기를 구별하여 문자열을 효율적으로 처리합니다.

std::string 클래스의 멤버 함수인 length()는 문자열의 길이를 반환합니다.
이 길이는 문자열 데이터에 포함된 실제 문자 개수를 의미합니다.
하지만 문자열 데이터가 메모리에 저장되는 방식 때문에, 문자열 길이와 실제 메모리 크기는 일치하지 않을 수 있습니다.
std::string 클래스는 동적으로 문자열 데이터를 할당하고 관리합니다.
이 때, 문자열 데이터는 null 종료 문자('\0')로 끝나야 합니다. 따라서 문자열 데이터를 저장하는 메모리 공간의 크기는 문자열 길이보다 1 큽니다. 예를 들어, "hello" 문자열의 경우 길이는 5이지만, 이 문자열을 저장하는 메모리 공간의 크기는 6입니다.
또한, std::string 클래스는 문자열 데이터를 저장하기 위해 동적으로 메모리를 할당합니다.
이 때, 할당되는 메모리의 크기는 문자열 데이터의 길이와는 관련이 없을 수 있습니다.
예를 들어, "hello" 문자열을 저장하기 위해 할당된 메모리 공간이 8바이트인 경우가 있습니다.
이는 메모리 할당의 내부 알고리즘에 따라 달라질 수 있습니다.
따라서, std::string 클래스의 length() 멤버 함수로 얻는 문자열 길이와 실제 문자열 데이터가 저장된 메모리 크기는 일치하지 않을 수 있습니다.
하지만, std::string 클래스는 문자열 데이터의 길이와 메모리 크기를 투명하게 관리하기 때문에, 사용자는 이러한 내부 구현 상세를 신경쓰지 않고 문자열을 처리할 수 있습니다

 

다양한 멤버 함수를 제공하여 문자열 데이터를 조작할 수 있는데, 이 예제에서는 += 연산자를 사용하여 문자열 데이터를 뒤에 추가하는 것을 구현했습니다. 물론 이 외에도 append(), replace(), insert() 등 다양한 멤버 함수를 사용할 수 있습니다.

 

이러한 방식으로 std::string 클래스는 문자열 데이터를 동적으로 할당하고, 문자열을 조작하는 다양한 멤버 함수들을 제공합니다.

내부적으로는 문자열 데이터를 저장하기 위한 메모리 관리와 문자열 조작 함수들의 구현 등이 이루어지며, 이를 통해 문자열 데이터를 효율적으로 처리할 수 있습니다.

 

아래는 string 멤버함수를 활용하여 문자열 데이터를 처리하는 예제입니다.

(문자열을 분리하여 벡터에 저장하고, 저장된 문자열을 역순으로 출력하는 기능 구현)

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::string str = "apple,banana,cherry,date,elderberry";

    // 문자열을 구분자로 분리하여 벡터에 저장하는 방법
    std::vector<std::string> vec;
    size_t start = 0, end = 0;
    while ((end = str.find(',', start)) != std::string::npos) {
        vec.push_back(str.substr(start, end - start));
        start = end + 1;
    }
    vec.push_back(str.substr(start));

    // 저장된 문자열을 역순으로 출력하는 방법
    for (auto iter = vec.rbegin(); iter != vec.rend(); ++iter) {
        std::cout << *iter << std::endl;
    }

    return 0;
}
std::string 클래스의 멤버 함수인 find()과 substr()을 활용하여 문자열을 분리하고, 이를 std::vector 컨테이너에 저장합니다.
이후 저장된 문자열을 역순으로 출력합니다.
1) 문자열을 구분자(' , ')로 분리하여 벡터에 저장
문자열에서 , 문자가 있는 위치를 찾아내는 방법은 find() 멤버 함수를 활용합니다.
이 함수는 문자열에서 주어진 문자 또는 문자열을 찾아, 해당 위치를 반환합니다.
find() 함수의 두 번째 인자는 검색을 시작할 위치를 지정하는 인자입니다.
따라서 start 변수에 이전에 찾은 , 문자의 위치를 저장하고, 이를 시작 위치로 지정하여 , 문자를 찾아냅니다.
이렇게 찾은 문자열은 substr() 멤버 함수를 활용하여 추출합니다.
이 함수는 문자열에서 주어진 위치부터 지정한 길이만큼의 문자열을 반환합니다.
2) 저장된 문자열을 역순으로 출력하는 방법
이 예제에서는 std::vector 컨테이너의 멤버 함수인 rbegin()과 rend()를 활용하여 반복자(iterator)를 역순으로 순회합니다.
이렇게 역순으로 순회하면서 저장된 문자열을 출력합니다.
이러한 방식으로 std::string 클래스의 멤버 함수와 std::vector 컨테이너를 활용하여 문자열을 분리하고, 저장된 문자열을 처리하는 다양한 기능을 구현할 수 있습니다.

 

std::string 클래스의 내부 구현에서는 또한 문자열 데이터의 내부 인코딩에 대한 처리도 이루어집니다.

std::string 클래스는 기본적으로 ASCII나 UTF-8 인코딩을 사용하지만, 다른 인코딩을 사용하는 경우에도 멤버 함수를 통해 문자열 데이터를 적절하게 변환할 수 있습니다.

즉, std::string 클래스는 문자열 데이터를 동적으로 할당하고, 문자열을 조작하는 다양한 멤버 함수들을 제공하는 라이브러리 클래스입니다. 내부적으로는 문자열 데이터를 저장하기 위한 메모리 관리와 문자열 조작 함수들의 구현 등이 이루어지며, 이를 통해 문자열 데이터를 효율적으로 처리할 수 있습니다.

+ Recent posts