기존 C표준 라이브러리 함수와 차이가 있다면, 원래 strtoul, strtol 함수는 명시적으로 base 인자를 받는데 이를 받지 않고 자동으로 base를 감지하도록 하였다. 이는 원래 함수에서 base 인자가 0인 경우와 같은 동작을 한다.
또한 원래 strtoul, strtol 함수는 2진수 접두사 "0b"를 처리하지 않는데 이를 처리하도록 하였다.
그리고 원래 strtof 함수 과학적 지수 표기(e 또는 E)를 지원하나 간단한 구현 및 처리를 위해 이를 지원하지 않는 버전으로 했다.
#include <stdio.h>
// 공백 문자 확인
int my_isspace(char c) {
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f');
}
// 숫자 확인
int my_isdigit(char c) {
return (c >= '0' && c <= '9');
}
// 문자열을 unsigned long으로 변환 (부호 처리 제거)
unsigned long my_strtoul(const char* nptr, char** endptr)
{
const char* s = nptr;
unsigned long acc = 0;
int base = 10;
int c;
// 공백 스킵
while (my_isspace((unsigned char)*s))
s++;
// 진수 감지
if (*s == '0') {
s++;
if (*s == 'x' || *s == 'X') {
base = 16;
s++;
}
else if (*s == 'b' || *s == 'B') {
base = 2;
s++;
}
else {
// 앞에 0만 있는 경우 8진수로 처리
base = 8;
}
}
// 숫자 변환
while ((c = *s)) {
int digit;
if (c >= '0' && c <= '9') {
digit = c - '0';
}
else if (c >= 'a' && c <= 'z') {
digit = c - 'a' + 10;
}
else if (c >= 'A' && c <= 'Z') {
digit = c - 'A' + 10;
}
else {
break;
}
if (digit >= base)
break;
acc = acc * base + digit;
s++;
}
// 변환이 끝난 위치 저장
if (endptr)
*endptr = (char*)s;
return acc;
}
// 문자열을 long으로 반환
long my_strtol(const char* nptr, char** endptr)
{
const char* s = nptr;
unsigned long acc = 0;
int base = 10;
int c;
int neg = 0;
// 공백 스킵
while (my_isspace((unsigned char)*s))
s++;
// 부호 처리
if (*s == '-') {
neg = 1;
s++;
}
else if (*s == '+') {
s++;
}
// 진수 감지
if (*s == '0') {
s++;
if (*s == 'x' || *s == 'X') {
base = 16;
s++;
}
else if (*s == 'b' || *s == 'B') {
base = 2;
s++;
}
else {
base = 8;
}
}
// 숫자 변환
while ((c = *s)) {
int digit;
if (c >= '0' && c <= '9') {
digit = c - '0';
}
else if (c >= 'a' && c <= 'z') {
digit = c - 'a' + 10;
}
else if (c >= 'A' && c <= 'Z') {
digit = c - 'A' + 10;
}
else {
break;
}
if (digit >= base)
break;
acc = acc * base + digit;
s++;
}
if (endptr)
*endptr = (char*)s;
long result = (long)acc;
if (neg)
result = -result;
return result;
}
// 문자열을 float로 변환
float my_strtof(const char* nptr, char** endptr)
{
const char* s = nptr;
float result = 0.0f;
int sign = 1;
while (my_isspace((unsigned char)*s))
s++;
if (*s == '-') {
sign = -1;
s++;
}
else if (*s == '+') {
s++;
}
// 정수부 처리
while (my_isdigit((unsigned char)*s)) {
result = result * 10.0f + (*s - '0');
s++;
}
// 소수점 이하 처리
if (*s == '.') {
s++;
float frac = 0.0f;
float divisor = 10.0f;
while (my_isdigit((unsigned char)*s)) {
frac += (*s - '0') / divisor;
divisor *= 10.0f;
s++;
}
result += frac;
}
if (endptr)
*endptr = (char*)s;
return sign * result;
}
int main() {
char* endptr;
printf("Testing my_strtoul:\n");
printf("Input: '123' => %lu\n", my_strtoul("123", &endptr));
printf("Input: '0x1A3F' => %lu\n", my_strtoul("0x1A3F", &endptr));
printf("Input: '0755' => %lu\n", my_strtoul("0755", &endptr));
printf("Input: '0b1010' => %lu\n", my_strtoul("0b1010", &endptr));
printf("Input: 'invalid' => %lu\n\n", my_strtoul("invalid", &endptr));
printf("Testing my_strtol:\n");
printf("Input: '123' => %ld\n", my_strtol("123", &endptr));
printf("Input: '-123' => %ld\n", my_strtol("-123", &endptr));
printf("Input: '+456' => %ld\n", my_strtol("+456", &endptr));
printf("Input: '0xFF' => %ld\n", my_strtol("0xFF", &endptr));
printf("Input: '0755' => %ld\n", my_strtol("0755", &endptr));
printf("Input: '0b1010' => %ld\n", my_strtol("0b1010", &endptr));
printf("Input: 'invalid' => %ld\n\n", my_strtol("invalid", &endptr));
printf("Testing my_strtof:\n");
printf("Input: '123.456' => %.3f\n", my_strtof("123.456", &endptr));
printf("Input: '-0.789' => %.3f\n", my_strtof("-0.789", &endptr));
printf("Input: '+3.14159' => %.5f\n", my_strtof("+3.14159", &endptr));
printf("Input: '0.0' => %.1f\n", my_strtof("0.0", &endptr));
printf("Input: 'invalid' => %.1f\n", my_strtof("invalid", &endptr));
return 0;
}
'프로그래밍 > C' 카테고리의 다른 글
C ] X-Macro (0) | 2025.01.30 |
---|---|
C ] TUI ARINC429 비행 고도/속도 송신 앱 (Text-based User Interface) (0) | 2025.01.07 |
C] 콘솔 프로그램 플리커 현상 개선하기 (더블 버퍼링 & 오프스크린 버퍼) (0) | 2025.01.05 |
inet_addr, inet_aton, inet_pton, inet_ntoa, inet_ntop (0) | 2024.12.17 |
winmm API 사용하여 WAV 파일 재생하기 (0) | 2024.07.04 |