반응형
문자열 → 수 변환 3종 비교: atoi vs stoi vs from_chars
| 항목 | atoi | stoi | from_chars |
| 헤더 | <cstdlib> | <string> | <charconv> |
| 입력 형태 | const char* (널종료) | std::string | 범위 (first, last) 포인터 |
| 진법 | 10 고정 | 2–36 지정 가능 | 정수: 2–36 지정 가능 / 부동소수: chars_format |
| 실패 처리 | 0 반환(모호) | invalid_argument, out_of_range 예외 | std::errc 코드 반환(예외 없음) |
| 범위 초과 | 정의 불명확 | out_of_range 예외 | ec = result_out_of_range |
| 변환 끝 위치 | 없음 | pos로 제공 | result.ptr 로 제공 |
| 공백 스킵 | 일부 구현 의존 | 선행 공백 스킵함 | 스킵 안 함 (직접 다뤄야 함) |
| 로케일 영향 | 가능 | 가능 | 영향 없음 |
| 힙 할당 | 없음 | 있을 수 있음 | 없음 |
| 표준/보급 | C | C++11 | 정수: C++17, 부동소수: C++17(광범위 구현은 C++20부터)** |
요지: 고성능·미세 제어 → from_chars
안전/간편 → stoi
레거시 C 코드 호환 최소 기능 → atoi
std::from_chars 기본 형태
정수
#include <charconv> // from_chars
#include <system_error> // std::errc
std::from_chars_result r = std::from_chars(first, last, out_int, base);
// r.ptr: 파싱이 끝난 위치
// r.ec : std::errc{}(성공), invalid_argument, result_out_of_range
기본 특징
- 선행 공백 미스킵(그대로 실패로 간주) → 필요하면 직접 isspace로 건너뛰기
- +/- 부호 허용(정수)
- 접두사(예: 0x)를 자동 인식하지 않음 → base=16이라도 "0xFF"는 실패. "FF"만 유효
- 로케일 무시, 예외/할당 없음 → 매우 빠르고 예측 가능
부동소수
std::from_chars_result r =
std::from_chars(first, last, out_double, std::chars_format::general);
// format: general / fixed / scientific / hex / (비트 OR 가능)
- general: 일반 표기/지수 표기 모두 허용 (123.4, 1.23e2)
- fixed: 고정소수점만
- scientific: 지수 표기만
- hex: C99 스타일 16진 부동소수(0x1.fp+2 등)
부동소수 오버로드는 표준상 C++17에 포함되지만, 실제 구현은 C++20부터 널리 안정적입니다.
실전 예제
1) 정수: 공백/접두사 직접 처리
#include <charconv>
#include <string>
#include <cctype>
#include <iostream>
using namespace std;
int main() {
string s = " 1010xyz";
const char* p = s.data();
const char* end = p + s.size();
// from_chars는 공백을 안 건너뛰므로 직접 처리
while (p < end && isspace((unsigned char)*p)) ++p;
int val = 0;
auto r = from_chars(p, end, val, 2); // 2진수
if (r.ec == errc{}) {
cout << "val=" << val << ", next='" << string(r.ptr, end) << "'\n";
// 출력: val=10, next="xyz"
} else if (r.ec == errc::invalid_argument) {
cout << "no digits\n";
} else if (r.ec == errc::result_out_of_range) {
cout << "overflow\n";
}
}
2) 부동소수: 형식 제한
#include <charconv>
#include <string>
#include <iostream>
using namespace std;
int main() {
string s = "3.14159e0 tail";
double x;
auto r = from_chars(s.data(), s.data() + s.size(), x, chars_format::general);
if (r.ec == errc{}) {
cout << x << " | rest: '" << string(r.ptr, s.data()+s.size()) << "'\n";
}
}
3) 부분 문자열 범위 파싱(널 종료 불필요)
string line = "id=42;next";
auto begin = line.data() + 3; // '4' 위치
auto stop = line.data() + 5; // '2' 다음 세미콜론 직전
int id;
auto r = from_chars(begin, stop, id, 10); // "42"만 대상으로 파싱
상황에 따라 써야하는 함수
- 최고 성능/세밀 제어/예외 금지/로케일 독립: from_chars
- 파서, 대용량 로그/파일 처리, 성능 민감 코드
- 간편 + 안전(예외로 실패 구분): stoi
- 사용자 입력 검증, 간단한 유틸, 진법 옵션 필요
- 레거시/초간단: atoi
- C 코드 유지보수, 실패 구분 불가 리스크 감수
공통 함정 & 팁
- 공백: from_chars는 공백을 절대 안 건너뜀 → 직접 전처리
- 접두사: from_chars 정수는 0x, 0b 등을 인지하지 않음
- 범위: 오버플로는 result_out_of_range; 부분 파싱 시 result.ptr을 반드시 사용
- 부동소수: 플랫폼 구현 상태 확인(C++20부터 보급), chars_format으로 허용 형식 명시
- 로케일: 통일된 해석이 필요하면 from_chars가 확실 (, 소수점 등 로케일 영향 無)
반응형
'프로그래밍 언어 > C++' 카테고리의 다른 글
| C++ ostringstream string 버퍼를 이용한 출력 (0) | 2025.10.01 |
|---|---|
| C++ to_string 숫자 -> 문자열 변환 함수 (0) | 2025.10.01 |
| C++ 문자열 -> 정수 변환 stoi vs atoi (0) | 2025.09.30 |
| C++ stoi 사용법 정리 (0) | 2025.09.30 |
| C++ 숫자 / 알파벳 / 공백 / 특수문자 판별 함수 정리 (isalpha, isdigit, isalnum, isspace, ispunct) (0) | 2025.09.30 |
댓글