티스토리 뷰
저번에 했던 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 |
하다가 점점 산으로가는 느낌이 들었슴다...
'C > Console' 카테고리의 다른 글
1000 자리까지 계산되는 계산기 (1) | 2018.11.20 |
---|---|
에라토스테네스의 체로 소수 구하기 (0) | 2018.11.16 |
C <stdarg.h>를 이용해서 가변인자의 최대값 구하기 (0) | 2018.11.16 |
N 진수를 입력받아서 N진수로 변환하기 (0) | 2018.11.14 |
문자를 정수로 변환하는 함수를 만들어 봅시다 (0) | 2018.11.14 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- scanf()
- Generic()
- Visual Studio 2017
- .editorconfig
- gettext
- #C
- scss slider
- stdarg.h
- flying bee
- 오류
- 도매인 가격비교
- C++
- css slider
- slider
- HTML
- C11
- JS
- C
- responsive slider
- 도메인 가격비교
- fyling fly
- SCSS @for
- CSS 슬라이더
- xgettext
- wxWidgets
- CSS
- #비주얼스튜디오
- _Generic()
- 1000 자리 계산기
- dropdown list
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함