살아가는 이야기

C/C++에서 행 단위 입력 본문

컴퓨터, 풀어그림

C/C++에서 행 단위 입력

우균 2021. 2. 1. 06:26

표준입력(stdin)에서 행 단위로 읽으려면 fgets를 사용한다. 과거 사용하던 gets는 버퍼 넘침(buffer overflow) 문제로 인해 더 이상 사용하지 않는다. fgets의 인수는 fgets(버퍼, 크기, 스트림) 형식으로 사용하는데, 우리말 순서로는 인수 순서가 잘 이해되지 않지만 영어 순서로는 "get a string into 버퍼 with 크기 from 스트림"으로 읽을 수 있으므로 뜻이 통한다. 헷갈리는 것은 버퍼와 스트림 순서인데, strcpy(버퍼, 소스)의 순서처럼 우측 끝 인수가 소스(source)라고 생각하면 기억하기 쉽다.

#include <stdio.h>

int main()
{
    char line[BUFSIZ];
    int  sz = sizeof line, lineno = 0;
    while (fgets(line, sz, stdin) != NULL) {
        fprintf(stdout, "%4d: %s", ++lineno, line);
    }
    return 0;
}

BUFSIZ는 <stdio.h>에 정의되어 있는데, 시스템에 따라 크기가 다르다. 대개 512, 1024 등 2의 거듭제곱 크기로 정해져 있다.

C++의 <iostream>을 사용하려면 cin.getline(버퍼, 크기)을 사용하면 된다. cin 자체가 콘솔 입력, 즉 표준 입력(stdin)을 나타내므로 별도의 stdin 인수가 필요 없다.

#include <iostream>
#include <cstdio>
#include <string>

using namespace std;

int main()
{
    char line[BUFSIZ];
    int  lineno = 0;
    while (cin.getline(line, BUFSIZ)) {
        fprintf(stdout, "%4d: %s\n", ++lineno, line);
    }
}

C++의 <string> 라이브러리에는 전역 함수로 getline이 존재한다. 사용 형식은 getline(스트림, 문자열)이다. string 라이브러리에 있는 것이므로 cin의 메소드로 만들지 않은 듯하다. string의 길이는 별도로 관리되므로 특별히 버퍼 크기를 인수로 전달하지 않아도 된다.

#include <iostream>
#include <cstdio>
#include <string>

using namespace std;

int main()
{
    int    lineno = 0;
    string line;
    while (getline(cin, line)) {
        fprintf(stdout, "%4d: %s\n", ++lineno, line.c_str());
    }
}

fprintf에서 %s 형식으로 출력하려면 string 메소드 c_str()을 이용하여 char* 데이터를 생성해 주어야 한다.

조금 더 C++ 스타일로 작성해 보자. 이 때에는 출력 조정자(output manipulator)를 사용해야 한다. 출력 너비를 4로 지정하려면 출력 조정자 setw(4)를 사용한다. setw는 <iomanip>에 선언되어 있다.

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

int main()
{
    int    lineno = 0;
    string line;
    while (getline(cin, line)) {
        cout << setw(4) << ++lineno << ": " << line << endl;
    }
}

C++ 스타일이라는 점은 좋지만 조금 번거롭다.

줄 단위 입력을 적으려다 어느덧 줄 단위 출력으로 얘기가 바뀌었다. 역시 입력과 출력은 따로 생각하기 어렵다.

Comments