티스토리 뷰

저번에 했던 scanf() 래핑하기를 업글해봤습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <locale.h>    //setlocale()
#include <stdio.h>    //wprintf() wscanf() NULL
#include <stdlib.h>    //srand() rand()
#include <uchar.h>    //char16_t
#include <stdint.h> //int32_t
#include <stdbool.h> //bool
#include <stdarg.h>    //va_list, va_start(), va_end(), va_arg()
#include <time.h>    //time()
 
#if defined(_WIN32) || defined(_WIN64)
#include <crtdbg.h>
#endif
 
//Input 함수 안에 쓰여질 _Generic() 타입을 받아서 문자서식자를 반환함
#define FMT_SPEC(T) _Generic((T), int32_t: u"%d%c"float: u"%f%c", char16_t*: u"%s%c")
 
//Input 함수에 인자값으로 쓰기위한 enum 문
enum TYPE_NAME
{
    TYPE_INT32_T,
    TYPE_FLOAT,
    TYPE_CHAR16_T
};
 
bool _wInput(const char16_t* _lpszFormat, ...);    //scanf() 래핑하는 범용성 입력기 int32_t float char16_t 만 지원가능
void ClearStream();                                //스트림 청소합니다
//에라토스테네스의 체를 이용하여
//소수를 찾아내는 프로그램을 만들겠습니다.
int main() {
 
#if defined(_WIN32) || defined(_WIN64)    //메모리 릭 검사
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    //_CrtSEtBreakAlloc();
#endif
 
    //로케일 설정 유니코드 함수들은 이함수에 지역값에따라 영향을 받습니다.
    //""은 현재 컴퓨터에 지정된 언어값이 설정되고
    //"Korean" 이라고하시면 한국이 설정됩니다.
    setlocale(LC_ALL, "");
    
    int32_t iInt[2= { 0 };
    float fFloat[3= { 0.f };
    char16_t szChar[30= u"하이룽";
 
    wprintf(u"입력해주세용.\n");
    _wInput(u"int32_t, float, char16_t"&iInt[0], &fFloat[0], szChar);
 
    wprintf(u"값 :: %d\n", iInt);
    wprintf(u"값 :: %f\n", fFloat);
    wprintf(u"값 :: %s\n", szChar);
 
    wprintf(u"입력해주세용.\n");
    _wInput(u"int32_t, float, char16_t, float, float, int32_t"
        &iInt[0], &fFloat[0], szChar, &fFloat[1], &fFloat[2], &iInt[1]);
 
    wprintf(u"값 :: %d\n", iInt[0]);
    wprintf(u"값 :: %d\n", iInt[1]);
    wprintf(u"값 :: %f\n", fFloat[0]);
    wprintf(u"값 :: %f\n", fFloat[1]);
    wprintf(u"값 :: %f\n", fFloat[2]);
    wprintf(u"값 :: %s\n", szChar);
 
    return 0;
}
cs

메인은 대충 이렇습니다 테스트 예제 몃개도 넣어봤습니다


저번함수와 달라진점은

저번함수는 enum으로 사용자에게서 타힙형을 받았지만



첫번재 인자로 포맷을 문자열로 받습니다
int32_t, float , chart16_t 형만 추가해봤습니다.
함수안에 변수는 메모리가 한도하는선에서 계속 추가가능합니다.

아는 함수에관한 코드입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//첫번째 인자 :: char16_t 문자열 int32_t , float, char16_t 입력
//자료형의 주소값을 넘겨주세요
bool _wInput(const char16_t* _lpszFormat, ...)
{
    // ----------------------- 함수 초기화 시작
    va_list args;                        //인자값을 저장할 args를 선언해준뒤
    va_start(args, _lpszFormat);        //args 값을 초기화해 줍니다.
 
    bool bResult = true;                //리턴값
    const char16_t* lpszFormat = _lpszFormat;    //인자값 받아옵니다.
 
    typedef struct _tagKey                //문자열과 문자열의 길이를 저장할 구조체
    {
        const char16_t* lpszType;
        int32_t cch;
        enum TYPE_NAME eType;
    }KEY, *PKEY;
 
    KEY tKey[] = { {u"int32_t"}, {u"float"}, {u"char16_t"} };    //key 값들을 초기화
    tKey[0].eType = TYPE_INT32_T;
    tKey[1].eType = TYPE_FLOAT;
    tKey[2].eType = TYPE_CHAR16_T;
    int32_t KeyCount = 3;                                        //key의 갯수
 
    for (int32_t i = 0; i < 3++i)    //키값들의 문자열 길이들을 구합니다.
    {
        tKey[i].cch = wcslen(tKey[i].lpszType);    //각각 문자열의 길이구함
        //wprintf(u"%s\n", tKey[i].lpszKey);    //디버깅용                    //NULL 포함
        //wprintf(u"%d\n", tKey[i].cch);
    }
 
    int32_t iMax = _wMax(u"3", tKey[0].cch, tKey[1].cch, tKey[2].cch) + 1;    //Key값중 문자열의 길이 최대값.
    char16_t cBuffer = u'\0';                //개행값 저장할 버퍼
    int32_t cch = wcslen(lpszFormat);        //입력받은 문자열의 길이를 구함
    int32_t n = 1;                            //몃개가 변수가 저장됬나 셀것임
    for (int32_t i = 0; i < cch; ++i)
        if (lpszFormat[i] == u','++n;        //, 갯수만큼 입력됬을것이라 가정함    
 
    char16_t** Buffer = (char16_t**)calloc(n, sizeof(char16_t*));    //2차원 배열을 동적할당으로
    Buffer[0= (char16_t*)calloc(n * iMax, sizeof(char16_t));        //생성중
    for (int32_t i = 1; i < n; ++i)
        Buffer[i] = Buffer[i - 1+ iMax;
    //--------------------------- 함수 초기화 끝
 
    //문자열의 0번부터 차례대로 검색을 시작합니다.
    int32_t count = 0;    //버퍼 카운트
    for (int32_t i = 0; i < cch; ++i)
    {
        if (lpszFormat[i] == u',' || lpszFormat[i] == u' ' || lpszFormat[i] == u'\0')
            continue;    //',' ' ' '\0'콤마면 패스        
        for (int32_t j = 0; j < iMax; ++j)
        {
            Buffer[count][j] = lpszFormat[i]; ++i;
            if (lpszFormat[i] == u',' || lpszFormat[i] == u' ' || lpszFormat[i] == u'\0')
            {    ++count; break;    }
        }
    }
 
    //디버깅용
    //for (int32_t i = 0; i < n; ++i)
    //    wprintf(u"%s\n", Buffer[i]);
 
    //버퍼에 모든것을 담았으니까 이제 버퍼에 담긴것들이 유효한 값인지 확인해야 합니다.
    //버퍼와 키값을 비교합니다
    int32_t CmpCount = 0;
    for (int32_t i = 0; i < n; ++i)
    {
        CmpCount = 0;
        for (int32_t j = 0; j < KeyCount; ++j)
        {
            if (wcscmp(Buffer[i], tKey[j].lpszType) == 0)    //하나라도 똑같다면 카운트올라가고 탈출
            {
                ++CmpCount;
                break;
            }
        }
        if (CmpCount == 0)            //중복값이 0개면 end 로 보냄     
        {                            //리턴값을 false로 변환
            bResult = false;
            goto end;
        }        
    }
 
    //뭔가 산으로가는느낌입니다...
    //이중문 돌려서 키값안에 enum 값으로 마무리를 시작합니다.
    //중복키를 찾으면 그 for문을 완전히 깨야하는데 그냥 냅두겠습니다.
    for (int32_t i = 0; i < n; ++i)
    {
        cBuffer = u'\0';
        for (int32_t j = 0; j < KeyCount; ++j)
        {            
            if (wcscmp(Buffer[i], tKey[j].lpszType) == 0)
            {
                switch (tKey[j].eType)
                {
                case TYPE_INT32_T:
                {
                    int32_t* pInt32_t = va_arg(args, int32_t*);        //args 에서 값을 받아온뒤
                    int32_t i32Temp = 0;                            //임시 변수 생성
                    wscanf(FMT_SPEC(i32Temp), &i32Temp, &cBuffer);    //wscaf()에 주소값 전달
                    if (cBuffer == u'\n')                            //cBuffer 개행이 일때
                        *pInt32_t = i32Temp;                        //값을 전달해줌.
                    else
                        ClearStream();                                //아니면 버퍼청소
                                                
 
                }
                break;
                case TYPE_FLOAT:
                {
                    float* pFloat = va_arg(args, float*);        //args 에서 값을 받아온뒤
                    float fTemp = 0.f;                            //임시 변수 생성
                    wscanf(FMT_SPEC(fTemp), &fTemp, &cBuffer);    //wscaf()에 주소값 전달
                    if (cBuffer == u'\n')                        
                        *pFloat = fTemp;
                    else
                        ClearStream();
                }
                break;
                case TYPE_CHAR16_T:
                {
                    char16_t* pChar = va_arg(args, char16_t*);
                    int32_t cch = 50;
                    char16_t* c16Temp = (char16_t*)calloc(cch, sizeof(char16_t));
                    wscanf(FMT_SPEC(c16Temp), c16Temp, &cBuffer);
                    if (cBuffer == u'\n')
                    {    
                        //인자값을 청소해준후 값을 할당합니다.
                        cch = wcslen(pChar);
                        memset(pChar, u'\0'sizeof(char16_t) * cch);
                        wcscpy(pChar, c16Temp);
                    }
                    else
                        ClearStream();
                    free(c16Temp);
                }
                break;
                }            
            }
        }
    }
 
end:
    //메모리해제
    free(Buffer[0]);
    free(Buffer);
 
    //스택정리
    va_end(args);
 
    //리턴
    return bResult;
}
 
void ClearStream()
{
    int32_t cBuffer = u'\0';
    while ((cBuffer = getchar()) != u'\n' && cBuffer != EOF)
        continue;
}
cs



하다가 점점 산으로가는 느낌이 들었슴다...

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함