이 게시글은
서울대학교 데이터사이언스대학원
조요한 교수님의
데이터사이언스 응용을 위한 컴퓨팅 강의를
학습을 위해 재구성하였습니다.
저번시간은 c++의 입출력 시스템인
std::cin과 std::cout에 대해서 배웠었다
이번 시간에는
c++의 File I/O Streams에 대해 배워보자
c++의 File I/O Stream는
ifstream, ofstream을 사용한다
ifstream이 Input file system
ofstream이 output file system이다
헤더에는 #include <fstream>을 정의해줘야
사용할 수 있고
standard I/O Stream과 비슷한 방식으로
사용된다고한다
File Read
std::ifstream file(PATH)로 파일 변수를 선언해준다
이렇게 선언하면 읽어올 파일의 변수명은 file이 된다
파일이 제대로 열렸는지 확인하기위해
if(file.is_open())으로 확인해주고
제대로 열리지 않았을 때 cerr 메세지를 띄우게한다
std::getline 메소드를 통해서
파일의 각 라인을 읽어온다
위에 string 변수인 line을 정의해주고
while문 안에 getline(file, line)을 해주면
file에 있는 라인이 없을 때까지
while문을 돌면서 line이라는 string변수에 저장된다
마지막으로는 file.close()를 통해
파일을 닫아줘야한다
반드시 getline으로 읽어와야하는 것은 아니다
위 ppt의 예시를 통해
파일을 어떻게 받아오는지 이해해보자
앞 시간에 배웠듯이 input buffer로는
whitespace, tab이 있으면
그 앞까지만 읽어올 수 있다
그럼 예시에서 data.txt파일을
while(file >> number)와 같이
input buffer를 통해 가져오게 된다면 어떻게될까
우선 젤 처음 텍스트를 읽어올 것이기 때문에
while문을 1회 돌 때 number에는
1이 저장되고 출력된 뒤
whitespace 때문에 중단된다
그 다음 while문이 있기 때문에
다시 2번 돌게되고
number에는 1과 whitespace 다음 글자인 2가
저장되고 출력된다
그 다음 다시 whitespace로 멈췄다가
다시 while문을 통해서 3번째 반복하고
마지막으로는 3을 출력하고 whlie문을 탈출하게된다
따라서 위 ppt처럼 output이 출력되는 것이다
std의 cin이나 cout처럼
본인 자신의 object를 계속해서 반환하면서
sequencial하게 이용이 가능하다
File Write
쓸 파일을
std::ofstream file(PATH)와 같이 정의해준다
그럼 쓸 파일의 변수명은 file이 된다
ifstream 때와 동일하게
file.open으로 에러여부 확인해준다음
<< 를 통해서 file에 쓰고싶은 내용을 넣어준다
쓸 내용을 다 넣었다면
file.close()로 닫아주면
지정해둔 경로에 file이 써진 것을 확인할 수 있을 것이다
string
c언어에서는 string이 없어서
char array로 사용해야하지만
c++은 string이라는 데이터타입이 존재한다
string을 구성하는 요소로는
data, size, capacity가 있다
data는 실제로 텍스트를 저장하고
있는 곳의 포인터 값으로
heap에 array로 저장되어있다
heap에 몇 개의 공간이 할당되었는지가
size 정보 (저장된 텍스트 데이터가 몇 칸인지)이고
최대 몇 개의 데이터를 담을 수 있는지를
나타내는 capacity가 있다
capacity는 어떻게 설정되냐는 질문이 있었는데
c++이 모든 컴퓨터나 환경에서 동일하지가 않다고 한다.
window에서 사용하는 c++이나
mac에서 사용하는 c++이나 모두 다르고
standard library도 기본적으로
지원하는 기능 정도만 정의해놓지
그 기능들이 어떻게 구현되는지는 각 환경이나 컴퓨터에따라
달라질 수 있다고한다
따라서 capacity같은 경우에도 c++ 라이브러리를
어디서 어떻게 구현하고 배포하느냐에따라
달라질 수 있기 때문에
정확하게 말할 수는 없다고한다
string을 초기화하는 방법에는
크게 세 가지가 있다
std::string str1;
이렇게 하면 빈 string이 선언되고
std::string str2 = "String2";
라고하면 String2라는 string이 선언된다
std::string str3("String3");
이렇게 선언해도 결과는 위와 마찬가지
string concatenation은 간단한데
+로 붙여주면 된다
+= 로도 붙여줄 수 있고
append 메소드를 이용할 수도 있다
string에서 비교하는 메소드이다
string에서의 대소관계는
알파벳, 가나다순이다
따라서 ==, <, >와 같이
크기를 비교하는 연산자들로
string끼리 비교할 수 있고
compare 메소드들로도 가능하다
string에서 substring을 찾는 법이다
find()를 이용하면 찾고자하는 substring이
전체 string에서 몇 번째 위치에 있는지 반환해준다
"Data Science"에서
"Science"는 5번째 인덱스부터
존재하기때문에
find를 하면 5가 반환된다
만약 substring이 존재하지 않는다면
string::npos 값을 반환하는데
string::npos값이란
size_t가 나타낼 수 있는 최대로 큰 값을 말한다
size_t는 unsigned integer 값으로
대충 string이 가질 수 있는 사이즈 정보를 담는
데이터 타입이라고 한다
아무튼
따라서 string에 substring이 존재하는지 아닌지는
if (pos != string::npos)와 같은 방식으로 확인한다
find한 값이 string::npos의 값과 같으면
substring이 없는거고
같지 않으면 substring이 특정 인덱스에
존재한다는 의미이다
substr(5, 3)은
5번째 index부터 3개를 가져오라는 뜻이다
따라서 "Data Science"에서
substr(5, 3)을 하면
"Sci"가 나오게 된다
replace(0, 4, "Bio")는
0번째 index부터 4개를 가져와서
"Bio"와 바꿔라
라는 의미이다
따라서 "Data Science"에서
replace(0, 4, "Bio")를 해주면
"Data" 대신에 "Bio"가 들어가게 된다
그래서 전체를 출력하면
"Bio Science"가 출력될 것이다
string에서 다른 데이터타입으로
변경하는 것도 가능하다
std::stoi를 이용하면
string에서 int로 변경하는 것이고
std::stod는
string에서 double로 변경하는 것이다
반대로 int나 double을 string으로 바꾸고싶다면
std::to_string 메소드를 이용할 수 있다
string에서의 메모리 구조이다
밑 코드를 잘 이해해보자
맨 처음 myString에는 "Hello World!"라는
string을 저장했다
그러고 myString의
size, capacity, 첫번째 글자의 주솟값을 출력해보니
13, 22, 그리고 어떤 주솟값이 나왔다
그 다음으로는 myString 뒤에 "!"를 추가했다
추가한 뒤 똑같이
size, capacity, 첫번째 주솟값을 출력하니
size는 "!"가 추가됐으므로 14로 늘어나고
capacity와 첫번째 주솟값은 그대로인 것을
확인할 수 있다
마지막으로는
"A large string"이라는 꽤 긴 문자를
myString에 추가했다
그 다음 size, capacity, 첫번째 주솟값을 출력하니
size는 긴 문자까지 추가된 29로 늘어났고
capacity가 기존에는 22였지만
myString의 size가 capacity를 넘겼으므로
capacity도 47로 늘어난 것을 확인할 수 있다
그리고 첫번째 문자의 주솟값이
기존의 myString과 달라진 것을 확인할 수 있다
이 메모리 주소가 왜 바뀌었냐하면
기존의 capacity로는
새로 추가된 myString을 담을 수 없으니
새로운 더 긴 array를 할당해서
capacity를 늘린 것이다
따라서 이를 통해
string을 다룰 때
기존 capacity보다
더 큰 사이즈를 저장하게되면
reallocation이 발생하게 된다는 것을
확인할 수 있다
stringstream은 string을 stream처럼
사용할 수 있게 해준다
위에 #include <sstream> 을 선언해서 사용 가능하다
위 ppt 예시처럼
std::stringstream parser("42,3.14,Hello World");로
stringstream을 선언하면
parser에는 뒤 문자가 stream으로 담긴다
그 다음 parser에 있는 stream을
각각
intValue
ignoreChar
doubleValue
ignoreChar
strValue
에 담으려고 한다
ignoreChar은 저장하려는 용도라기보단
,를 따로 빼려는 용도이다
parser >> intValue에서
intValue는 데이터타입이 int이기때문에
42만 저장이된다
이후 ignoreChar에는
바로 뒤 char 값인 콤마(,)가 저장이된다
이후 doubleValue에는 double값인
3.14까지 저장이 된다
그다음 ignoreChar에는 동일하게
콤마(,)가 저장이 된다
그리고 이후 strValue에 Hello World를
저장해주려하는데
Hello World안에 띄어쓰기가 있기때문에
단순한 input buffer를 이용해서 담아주면
Hello 까지만 저장이된다
그래서 getline을 통해서
strValue안에 Hello World를 가져와서 담아준다
반대로 stringstream ss를 정의한 후
100, 3.14, "Hello"를 넣어주면
ss에는 1003.14Hello가 담기게된다
하지만 이렇게 쓰는것이 권장되는 방법은 아니라고하는데
현재 ss를 read하는지 write하는지
이를 state를 가져와서 관리하는데
이게 계속해서 변경되면 작동이 복잡해지기때문이라고 한다
따라서 작동원리를 정확하게 알고있는게
아닌 이상 이런방식으로 자유롭게 쓰는 것은
권장되지 않는다고 한다
'강의 > computer science' 카테고리의 다른 글
[ComputerScience] c++와 list (0) | 2024.09.23 |
---|---|
[ComputerScience] c++의 vector (1) | 2024.09.23 |
[ComputerScience] c++의 I/O Streams (cin, cout) (1) | 2024.09.20 |
[ComputerScience] C++과 Namespace (1) | 2024.09.20 |
[ComputerScience] 알고리즘의 시간복잡도와 탐색, 정렬 (Binary Search, 깊이우선탐색, 넓이우선탐색, Selection Sort, QuickSort, Merge Sort) (3) | 2024.09.19 |