Eat Study Love

먹고 공부하고 사랑하라

SW 만학도/C++ & Algorithm

2. C++ Standard Library (2)

eatplaylove 2024. 3. 22. 14:48

https://eglife.tistory.com/34

 

1. C++ Standard Library (1)

아 ~ 이게 무슨 영어, 중국어 배우는 것도 아니고 코딩하나 하는데도 프로그래밍 언어가 너무 많다;; 이거 누가 통일 좀 안 시키나ㅠㅠ 그래도 써먹을데가 분명히 있다고 하니까 이놈의 C++ 공부

eglife.tistory.com

 

 

지난 시간에 이어서 C++ STD Library 추가학습 시우시작..

 

File I / O Streams

 

- Data 작업을 하려면 일단 기본적으로 file I / O 는 할 수 있어야 한다.

 

- C++에선 input file stream --> ifstream , output file stream --> ofstream class를 사용한다.

 

- 얘네는 전부 C++ STD Library의 <fstream> 헤더파일의 일부이다.

 

 

File I / O Streams - Reading

 

file을 읽기 위해 Open하는 방법, 끝에는 꼭 close 해주는 습관을 가지자

 

#include <iostream>
#include <fstream>
#include <string>

int main(void)
{
    std::ifstream file("test_folder\\test.txt");
    // std::ifstream file("test_folder/test.txt");
    // file path는 위와 같이 두 가지 방식으로 처리 가능

    if (!file.is_open())
    {
        std::cerr << "fail" << std::endl;
        return 0;
    }   //파일이 열렸는지 체크

    std::string line;
    while(std::getline(file,line))
    {
        std::cout << line << std::endl;
    }

    file.close();
    return 0;
}

 

- getline function을 쓰지 않으면 ifstream은 character를 input buffer로부터 읽을 때 white space를 만나면 읽기를 멈춘다.

(cin과 비슷)

 

- 사실상 ifstream은 istram class를 inherit 한 것이다.

 

1. getline 사용 X

// num_data :
// 123
// 4 5
// 67 8

#include <iostream>
#include <fstream>

int main()
{
    std::ifstream file("num_data.txt");
    int num;
    
    while(file >> num)
    {
        std::cout << num << std::endl;
    }
    file.close();
    return 0;
}
// 123
// 4
// 5
// 67
// 8

 

2. getline 사용 O --> getline은 int말고 string type variable로 써야한다.

// num_data :
// 123
// 4 5
// 67 8

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream file("num_data.txt");
    int num;
    std::string str;
    // while(file >> num)
    while(std::getline(file,str))
    {
        std::cout << str << std::endl;
    }
    file.close();
    return 0;
}
// 123
// 4 5
// 67 8

 

 

File I / O Streams - Writing

 

Writing을 위해 파일을 읽는 방법

 

// data.txt

// a b c
// d e
// f
#include <iostream>
#include <fstream>

int main()
{
    std::ofstream file123("data.txt");
    if(!file123.is_open())
    {
        std::cout << "ERROR" << std::endl;
        return 1;
    }
    file123 << "ADD THIS COMMENT!!" << std::endl;

    file123.close();
    return 0;
}

// data.txt
// ADD THIS COMMENT!!

// 기존 내용 날라가고 덮어쓰기가 되어버리네..;;

 

 

- Write을 해보니 파일에 있던 기존 txt 파일은 다 날라가고 추가한 문구만 들어간다.

 

- 기존 문구 살리면서 추가 코멘트만 넣는 방법에 대해 고안..

 

// data.txt
// original txt is here!

#include <iostream>
#include <fstream>
#include <string>
int main()
{   
    std::string str1;
    std::string str2;


    std::ifstream file123("data.txt");
    while(std::getline(file123,str1))
    {
        str2 = str2 + str1;
    }

    file123.close();

    std::ofstream file("data.txt");
    if(!file.is_open())
    {
        std::cout << "ERROR" << std::endl;
        return 1;
    }
    file << str2 << std::endl;
    file << "Add this text" << std::endl;

    file.close();
    return 0;
}

// data.txt

// original txt is here!
// Add this text

 

 

- 파일을 Read할 때, String을 하나 더 만들어서 기존 내용을 저장해놓고, Write할 때 이놈을 더해서 기존 DATA 유지

(백업 개념)

 

- 근데 file을 한 번에 read, write 목적으로 열고 닫을 때 file 이름을 동일하게 설정하면 error가 뜨네.. 그래서 그냥 variable 이름을 달리 해줌. 뭐 어려운 건 아니니까

 

 

String

 

- C에선 String은 Character array를 뜻했다.

- C++ STD Library는 string class를 지원하고, 이는 순차적으로 연결된 dynamic memory를 사용하는 array의 형태이다.

 

- String이 내포하고 있는 정보는 아래와 같다.

 

 1) 기본적으로 text data를 포함하고 있는 주소 pointer의 data

 

 2) 현재 text data의 size

 

 3) Char array가 최대로 가질 수 있는 character 길이 : Capacity

 

- String은 header로 #include <string>이 필요하고, std::string WHATEVER <-- 형식으로 선언한다.

std::string str; //empty
std::string str1 = "hi";
std::string str1("hi");

 

String Concatenation

 

- '+' operator 를 이용해 String 간 결합이 가능하다.

 

// 간편하구만!
#include <iostream>
#include <string>
int main()
{
    std::string one = "I";
    std::string two = "Love";

    std::string three = one + " " + two;

    std::cout << three << std::endl;
    return 0;
}
//I Love

 

 

- String에는 그리고 append+= 도 사용할 수 있다.

 

- 이 두가지 Case 모두 String이 자동으로 Update 된다.

 

#include <iostream>
#include <string>
int main()
{
    std::string one = "I";
    std::string two = "Love";

    one += " Play";
    two.append(" You");

    std::cout << one <<std::endl<<two<<std::endl;
    return 0;
}
// I Play
// Love You

// += , append 모두 string이 자동으로 update 된다.

 

String Comparison

 

- String도 " == , != , < , > Operator로 비교가 가능하다. ( Lexicographical order로! : 사전식 순서로!)

 

- 또는 Compare Method를 쓰는 법도 있다.

 

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string one = "ACE";
    string two = "FIRE";

    if(one == two)
    { cout << "'SAME'" <<endl;}
    else if(one < two)
    { cout << "'TWO BIG'"<<endl;}
    else
    { cout << "'ONE BIG'"<<endl;}
    //'TWO BIG'

    cout << one.compare(two) << endl;// one > two? --> -1
    cout << one.compare(one) << endl;//0
    cout << two.compare(one) << endl;// two > one?--> 1

    return 0;
}

 

- if / else if / else 조건문을 쓸 때 compare operation 사용 가능!

 

 

Strings Finding Substrings

 

 

- Find를 통해 string 내에 substring의 위치가 어떻게 되는 지 알 수 있다.

 

- size_tunsigned integer type이다. 보통 size 또는 count를 표현할 때 쓴다.

 

- string::npos 는 string class에 속하는 상수이며 size_t가 가질 수 있는 가장 큰 값을 의미한다.

 (find () 가 substring을 찾는데 실패하면 string::npos를 반환한다.)

 

int main()
{
    std::string str = "hello boy are you a girl?";
    size_t pos = str.find("are");
    if(pos != std::string::npos){
        std::cout << "find : "<< pos <<std::endl;
    }
    // find : 10


    size_t pos2 = str.find("ZZZ");
    if(pos2 != std::string::npos){
        std::cout<< "find : " <<pos2<<std::endl;
    }
    else{
        std::cout << "ERROR" <<std::endl;
    }
    // ERROR

    return 0;
}

 

 

- 궁금해서 해봤는데, 그냥 아래처럼 실행해도 위치 찾을 수 있다.

 

    std::string str = "hello boy are you a girl?";
    int a = str.find("boy");
    std::cout << a << std::endl;
    //6

 

 

- substr(position , length) 는 string에서 starting position(position) 기준 length만큼 substring을 반환한다.

 

#include <iostream>
#include <string>
#include "string"
int main(void)
{
    std::string str = "DEATH NOTE";
    std::cout << str.substr(1,3) << std::endl;

    return 0;
    //EAT
}

 

 

Strings Replacing Substrings

 

- replace( start , lengrh , replacement ) 는 string에서 start 기준 length만큼을 replacement로 바꿔준다.

 

#include <iostream>
#include <string>
#include "string"
using namespace std;
int main(void)
{

    string str = "GOOD MORNING";
    string replace = str.replace(5,3,"DAY");
    cout << str << endl;
    cout << replace << endl;
    string replace2 = str.replace(5,3,"DAY~~~!"); 
    cout << replace2 << endl;
    cout << str << endl;
    cout << replace << endl;
    // GOOD DAYNING
    // GOOD DAYNING
    // GOOD DAY~~~!NING
    // GOOD DAY~~~!NING
    // GOOD DAYNING
    return 0;
}

 

- Replace를 하는 순간 기존 string도 자동으로 replace Update가 진행된다.

 

Strgins - Conversion

 

- std::stoi , std::stod는 string을 integer나 double type으로 바꿔준다.(String 내용이 숫자여야 할 것이다.)

 

- 반대로 std::to_string은 숫자를 string으로 바꿔준다.

 

#include <iostream>
#include <string>
#include "string"
// using namespace std;
int main(void)
{
    std::string num = "92";
    int intnum = std::stoi(num);
    double doublenum = std::stod(num);

    std::cout << intnum+1<<std::endl;
    std::cout << doublenum+1<<std::endl;
    //93
    //93

    int var = 123;
    std::string strvar = std::to_string(var);
    std::cout << strvar << std::endl;
    //123

    return 0;
}

 

- 숫자가 아닌 String 형태를 숫자로 바꾸려고 한다면..

 

    std::string num = "AA";
    int intnum = std::stoi(num);
    double doublenum = std::stod(num);
    std::cout << intnum <<std::endl;
    std::cout << doublenum <<std::endl;

// 에러를 마주하게 된다
/*terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi*/

 

 

String - Memory

 

 

 

 

- ARRAY의 CAPA보다 큰 Szie data가 들어오면 array 주소가 reallocated 된다.

 

- ARRAY의 CAPA보다 큰 Szie data가 들어오면 array의 CAPA가 더 큰 사이즈로 재지정된다.

 

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str = "Hi, I'm Marcus";
    cout << "1st size: "<<str.size()<<endl;
    cout << "1st capa: "<<str.capacity()<<endl;
    cout << "1st address: "<<(void*)str.c_str()<<endl;

// 1st size: 14
// 1st capa: 15
// 1st address: 0x61fdf0

    //쪼만한 length append

    str.append("~!!");
    cout << "2nd size: "<<str.size()<<endl;
    cout << "2nd capa: "<<str.capacity()<<endl;
    cout << "2nd address: "<<(void*)str.c_str()<<endl;

// 2nd size: 15
// 2nd capa: 15
// 2nd address: 0x61fdf0

    //큰 length append
    str.append("Nice to meet you ma luvey!");
    cout << "1st size: "<<str.size()<<endl;
    cout << "1st capa: "<<str.capacity()<<endl;
    cout << "1st address: "<<(void*)str.c_str()<<endl;

// 1st size: 41
// 1st capa: 41 --> CAPA 변경!
// 1st address: 0xf66b40 --> 주소 자체가 변경!

    return 1;
}

 

 

Stringstreams

 

- 한 stringstream에 대해 read / write를 동시에 하는 걸 방지한다. --> 무슨 말인지..? 암튼 이런 것도 있다.

 

#include <iostream>
#include <sstream>

int main()
{
    std::stringstream test;
    
    test<<123.456;
    test<<"ABC";
    test<<999;

    std::cout << test.str() << std::endl;
    //123.456ABC999
    return 0;
}

 

뭐,, 이해하긴 쉬운데 외울 게 여전히 많아 보이는 C++의 세계!

 

계속 전진해보즈앙!

 

 

'SW 만학도 > C++ & Algorithm' 카테고리의 다른 글

6. Out_of_class Definition & Operator Overloading  (0) 2024.04.10
5. Classes  (0) 2024.04.09
4. Functions and Memory Management  (1) 2024.03.29
3. C++ Standard Library (3)  (1) 2024.03.24
1. C++ Standard Library (1)  (0) 2024.03.21