문제 개념
주어진 문자열이 유효한 숫자(numeric)인지 판별하는 프로그램을 작성해야 합니다. 단순히 숫자 형태처럼 보이는지만 확인하는 것이 아니라, 소수점과 지수 표기까지 포함해 엄격하게 검증해야 합니다.
입력 − str = "12.5"
출력 − true
입력 − str = "def"
출력 − false
입력 − str = "2e5"
출력 − true
입력 − str = "10e4.4"
출력 − false
접근 방법
문자열이 유효한 숫자인지 확인하려면 코드에서 다음과 같은 경우들을 반드시 처리해야 합니다.
- 문자열 앞뒤에 있는 선행·후행 공백은 무시합니다.
- 문자열 시작 부분의 '+', '-', '.' 기호는 허용합니다.
- 문자열을 구성하는 모든 문자는 {+, -, ., e, [0-9]} 집합에 속해야 합니다.
- 'e' 뒤에는 '.'이 나올 수 없습니다.
- '.' 문자 다음에는 반드시 숫자가 이어져야 합니다.
- 'e' 문자 뒤에는 '+', '-', 또는 숫자 중 하나가 와야 합니다.
동작 원리
먼저 두 포인터를 이용해 문자열 양 끝의 공백을 제거하고, 남은 구간이 비어 있거나 첫 문자가 유효하지 않으면 즉시 실패를 반환합니다. 이후 문자열을 한 글자씩 순회하면서 각 문자가 허용된 집합에 속하는지 검사하고, 소수점('.')과 지수('e')가 등장하는 위치와 그 뒤에 오는 문자의 조합이 올바른지 확인합니다. 모든 검사를 통과하면 해당 문자열은 유효한 숫자입니다. 전체 탐색은 문자열 길이 n에 대해 선형으로 진행되므로 시간 복잡도는 O(n)입니다.
예제 코드
// C++ program to check if input number
// is a valid number
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int valid_number1(string str1){
int i = 0, j = str1.length() - 1;
while (i < str1.length() && str1[i] == ' ')
i++;
while (j >= 0 && str1[j] == ' ')
j--;
if (i > j)
return 0;
if (i == j && !(str1[i] >= '0' && str1[i] <= '9'))
return 0;
if (str1[i] != '.' && str1[i] != '+' && str1[i] != '-' && !(str1[i] >= '0' && str1[i] <= '9'))
return 0;
bool flagDotOrE = false;
for (i; i <= j; i++) {
// If any of the char does not belong to
// {digit, +, -, ., e}
if (str1[i] != 'e' && str1[i] != '.'
&& str1[i] != '+' && str1[i] != '-'
&& !(str1[i] >= '0' && str1[i] <= '9'))
return 0;
if (str1[i] == '.') {
if (flagDotOrE == true)
return 0;
if (i + 1 > str1.length())
return 0;
if (!(str1[i + 1] >= '0' && str1[i + 1] <= '9'))
return 0;
}
else if (str1[i] == 'e') {
flagDotOrE = true;
if (!(str1[i - 1] >= '0' && str1[i - 1] <= '9'))
return 0;
if (i + 1 > str1.length())
return 0;
if (str1[i + 1] != '+' && str1[i + 1] != '-'
&& (str1[i + 1] >= '0' && str1[i] <= '9'))
return 0;
}
}
return 1;
}
// Driver code
int main(){
char str1[] = "0.1e10";
if (valid_number1(str1))
cout << "true";
else
cout << "false";
return 0;
}출력 결과
true
마무리
위 예제에서 입력 문자열 "0.1e10"은 소수점과 지수 표기를 모두 포함하지만 각 규칙을 만족하므로 true가 출력됩니다. 반면 "10e4.4"처럼 지수(e) 뒤에 소수점이 등장하는 문자열은 규칙 위반으로 false를 반환하게 됩니다. 이러한 단계별 검증 방식은 정규표현식 없이도 문자열 숫자 판별 문제를 안정적으로 해결할 수 있는 실용적인 접근 방법입니다.