[C++기초] 4. 문자열과 파일입출력

Index

  1. stdstring 클래스
  2. strstring이 좋은가?
  3. 파일입출력(I/O)
  4. 파일 읽기 한 문자, 한 줄, 한 단어
  5. 파일 읽기 Best Practice
  6. 파일 쓰기, 바이너리 파일 읽기, 파일 안에서의 탐색

stdstring 클래스

string을 사용하지 않을 경우

char line[256];
cin.getline(line, 256);

std::string 클래스

대입(Assignment)과 덧붙이기(Appending);

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 firstName[20] = "POPE";
char lastName[20] = "KIM";
char fullName[40];

snprintf(fullName, 40, "%s %s", firstName, lastName);

C++의 경우

string firstName[20] = "POPE";
string lastName[20] = "KIM";
string fullName[40];

fullName = firstName + " " + lastName;

비교(Relational)연산자

C의 경우

if (strcmp(firstName1, firstName2) == 0)
{
 //...
}

if (strcmp(firstName1, firstName2) > 0)
{
 //...
}

C++의 경우

if(firstNam1 == firstName2)
{
 //...
}

//사전 상의 순서를 비교
if(firstName1 > firstName2)
{
 //...
}

size(), length(), c_str()

string 속의 한 문자에 접근하기

strstring이 좋은가?

<sstring>

C헤더를 써도 될까?

그래서 string이 더 낫다는 건가?

장점

단점

결론

여전히 sprintf와 함께 char[]를 매우 많이 사용한다.

파일입출력(I/O)

ifstream

ofstream

fstream

파일 열기

C의 경우

FILE* fp;

//읽기 전용으로 파일 오픈
fp = fopen("helloworld.txt","r");

//쓰기 전용으로 파일 오픈(파일이 없으면 생성)
fp = fopen("helloworld.txt","w+");

//일기와 쓰기 범용으로 파일 오픈
fp = fopen("helloworld.txt","r+");

C++의 경우

//읽기 전용으로 파일을 오픈
ifstream fin;
fin.open("helloworld.txt");

//쓰기 전용으로 파일을 오픈(파일이 없으면 생성)
ofstream fout;
fout.open("helloworld.txt");

//읽기와 쓰기 범용으로 파일을 오픈
fstream fs;
fs.open("helloworld.txt");

open()

파일 열기 모드의 예

C C++
“r” ios_base::in
“w” ios_base::out
ios_base::out|ios_base::trunc
“a” ios_base::out|ios_base::app
“r+” ios_base::in|ios_base::out
“w+” ios_base::in|ios_base::out|ios_base::trunc

파일 닫기

C의 경우

FILE *fp;
//...
fclose(fp);

C++의 경우

ifstream fin;
//...
fin.close();

스트림상태 확인하기

C의 경우

FILE *fp;
fp = fopen("helloWorld.txt","r+");

if(fp != NULL)
{
//...
}

C++의 경우

fstream fs;
fs.open("HelloWorld.txt");

if(fs.is_open())
{
//...
}

파일 읽기 한 문자, 한 줄, 한 단어

파일에서 문자 하나씩 읽기

C의 경우

FILE* fp;
fp= fopen("HelloWorld.txt","r");

char character;
do
{
	charactor = getc(fp);
	printf("%c", character);
} while(character != EOF);
fclose(fp);

C++의 경우

ifstream fin;
fin.open("HelloWorld.txt");

char character;
while(true)
{
	fin.get (character);
	if(fin.faile()) break;
	cout<<character;
}
fin.close();

get(), getline(), »

파일에서 한 줄씩 읽기

ifsteam fin;
fin.open("Hello World.txt");
string line;
while(!fin.eof())
{
        getline(fin,line);
        cout<<line<<endl;
}
fin.close();

파일에서 한 단어씩 읽기

ifstream fin;
fin.open("Hello World.txt");

string name;
float balance;
while(!fin.eof())
{
        fin >> name >> balance;
        cout << name << ":$" << balance << endl;
}

fin.close();

잘못된 파일 입력을 처리하는 방법

파일 읽기 Best Practice

EOF처리는 까다롭다

베스트 프랙티스

훌륭한 테스트 케이스

  1. 유효한 입력 뒤에 EOF

    0 1 2 3 4 5 6 7
    1 0 0 \n 2 0 0 EOF
  2. 유효한 입력과 뉴라인\n뒤에 EOF

    0 1 2 3 4 5 6 7 8
    1 0 0 \n 2 0 0 \n EOF
  3. 유효하지 않은 입력 뒤에 EOF

    0 1 2 3 4 5 6 7
    1 0 0 \n C + + EOF
  4. 유효하지 않은 입력과 뉴라인\n뒤에 EOF

    0 1 2 3 4 5 6 7 8
    1 0 0 \n C + + \n EOF
  5. 공백:탭도 포함할 것인가

    0 1 2 3 4 5 6 7 8
    1 0 0   C + + \t
  6. 키보드 입력과 리다이렉선(redirection)을 둘 다 확인할 서)

    • 100 200 300
    • cmd>numbers.exe<numbinput.txt

파일 쓰기, 바이너리 파일 읽기, 파일 안에서의 탐색

파일에 쓰기

C의 경우

FILE* fp;
fp = fopen("HelloWorld", "w");

char line[512];
if (fgets(line, 512, stdin) != NULL)
{
	fprintf(fp, "%s\n", line);
}
fclose(fp);

C++의 경우

ofstream fout;
fout.open("HelloWorld.txt");

string line;
getline(cin,line);
if(!cin.fail())
{
	fout<<line<<endl;
}
fin.close();

put(), «

바이너리 파일 읽기

C의 경우

FILE *fp;
fp = fopen("studentRecord.dat","rb");

if(fp != NULL)
{
	//record는 char[20]변수 2개와 int변수 1개를 가짐
	Record record;
	fread(&record, sizeof(Record),1,fp);
}
fclose(fp);

C++의 경우

ifstream fin("studentRecords.dat",ios_base::in | ios_base::binary);
if(fin.is_open())
{
	Record record;
	fin.read((char*)&record,sizeof(Record));
}
fin.close();

ifstream::read()

바이너리 파일에 쓰기

C의 경우

FILE *fp;
fp = fopen("studentRecords.dat", "w");
if(fp != NULL)
{
	char buffer[20] = "Pope Kim";
	fwrite(buffer, 20, 1, fp);
}
fclose(fp);

C++의 경우

ofstream fout("studentRecords.dat", ios_base::out | ios_base::binary);
if(fout.is_open())
{
	char buffer[20] = "Pope Kim";
	fout.write(buffer, 20);
}
fout.close();

ofstream::write()

파일 안에서의 탐색

C의 경우

FILE* fp;
fp = fopen("studentRecord.dat", "w");
if(fp != NULL)
{
	if (fseek(fp.20,SEEK_SET) == 0)
	{
		// 21번째 위치에서부터 덮어쓰기
	}
}
fclose(fp);

C++의 경우

fstream fs("helloWorld.dat", ios_base::in | ios_base::out | ios_base::binary);
if (fs.is_open())
{
	fs.seekp(20, ios_base::beg);
	if (!fs.fail())
	{
		// 21번째 위치에서부터 덮어쓰기
	}
}
fs.close();

탐색 유형

파일 쓰기 위치 읽기 및 변경

  1. tellp() 쓰기 포인터의 위치를 구함

    ios::pos_type pos = fout.tellp();

  2. tellg() 읽기 포인터의 위치를 구함

    ios::pos_type pose = fin.tellg();

  3. seekp() 쓰기 포인터의 위치를 변경함

    절대적

    fout.seekp(0); // 처음 위치로 이동
    

    상대적

    // 현재 위치로부터 20바이트 뒤로 이동
    fout.seekp(20, ios_base::cur);
    
  4. seekg() 읽기 포인터의 위치를 변경함

    절대적

    fin.seekg(0); // 처음 위치로 이동
    

    상대적

    // 파일의 끝에서부터 10 바이트 앞으로 이동
    fin.seekg(-15, ios_base::end);
    

기타 정보

  cin >> number;
  getline(cin, line); // cin에서 공백을 꺼내 감

해결법

cin >> number;
cin >> ws; //공백을 버림
getline(cin,line);