본문 바로가기

프로그래밍/C70

C언어 ] 맵 자료구조 구현 map 생성시 사이즈를 직접 결정할 수 있도록 해보았다. 근데 링버퍼처럼 범용적으로 쓸 거 같진 않아서 사실 고정길이배열로 mapManger 구조체안에 둬도 될 것 같다. map.h #include "main.h" #define MAP_MAX_KEY_LEN20 // 맵 자료구조 typedef struct { char key[MAP_MAX_KEY_LEN+1]; uint32_t value; } map_t; // 맵 자료구조 관리 구조체 typedef struct { map_t* maps; uint32_t currentSize; uint32_t maxSize; } mapManager_t; void map_create(mapManager_t* mapManager, map_t* maps, uint32_t maxS.. 2023. 5. 7.
C ] float to hex / hex to float Converter 2023.04.09 - [프로그래밍/C# (WinForms)] - C#, WinForms ] float to hex / hex to float Converter C#, WinForms ] float to hex / hex to float Converter 필요에 의해서 만들었다. 내가 예전에 소개한 float to hex converter 사이트랑 달리 시스템 아키텍쳐에 따라 메모리에 저장된 대로 보여준다. 디자이너 부분을 먼저 살펴보면 Form은 사용자가 크기를 eteo.tistory.com 위 글에서 WinForms로 만든 float to hex / hex to float Converter를 C언어로 간단히 구현해 본 것. 예외처리나 옵션 없이 리틀엔디안으로 변환하는 기능만 넣었다. #include .. 2023. 4. 9.
C ] 시간복잡도가 O(1)인 2의 거듭제곱 판별 int isPowerOfTwo(int n) { return (n && ((n & (n - 1)) == 0)); } 2의 거듭제곱은 가장 왼쪽에 있는 1을 제외하고 뒷부분이 전부 0이라는 걸 고려할 때 위와 같은 코드로 판별할 수 있다. 그리고 어떤 정수를 2의 거듭제곱 수로 나눈 나머지 연산을 해야할 때 성능향상을 위한 최적화 기법으로 %연산이 아니라 &연산을 쓰기도 한다. 위와 같은 논리이다. #define SOME_NUMBER_POWER_OF_TWO8 int getRemainder(int n) { return n & (SOME_NUMBER_POWER_OF_TWO - 1); } 2023. 3. 31.
C ] atoi 함수 구현 #include int myatoi(char* str) { int sign = 1; int sum = 0; while (*str == ' ') { str++; } if (*str == '-') { sign = -1; str++; } while (*str) { int num = *str - '0'; // 0x30 if (num >= 0 && num 2023. 3. 25.
C ] isalpha, isupper, islower, isdigit, isxdigit, isalnum, isspace, ispunct, isprint, isgraph, iscntrl, isascii, 함수 구현 int my_isalpha(int c) { return (c >= 'A' && c = 'a' && c = 'A' && C = 'a' && C = '0' && c = 'A' && c = 'a' && c = 0 && c = 32 && c = 0 && c 2023. 3. 25.
C ] vprintf, vsprintf, vsnprintf 차이 int vprintf(const char * __restrict _format, va_list _ap); int vsprintf(char * __restrict _string, const char * __restrict _format, va_list _ap); int vsnprintf(char * __restrict _string, size_t _n, const char * __restrict _format, va_list _ap); 셋 다 마지막 매개변수로 가변인수 목록이 담긴 포인터를 받는다는 공통점이 있지만 vprintf는 콘솔로 출력하고 vsprintf와 vsnprintf는 버퍼로 출력한다는 차이점이 있다. vsprintf와 vsnprintf의 차이점은 vsnprintf는 버퍼의 크기를 지정해서 .. 2023. 2. 17.
컴파일러 워닝 "was set but never used" 해결법 변수를 선언하거나 함수를 정의하고 사용하지 않으면 컴파일러가 "was set but never used" 경고를 낼 때가 있다. 다음과 같이 캐스팅하면 된다. void never_call() { (void)abc; } 2023. 1. 31.
#ifdef 와 #if defined() 의 차이 #ifdef 와 #if defined() 는 항목이 하나일 땐 동일하다. #ifdef A #if defined(A) 차이점은 #if defined() 만 아래처럼 여러 항목을 비교할 수 있다고, #ifdef 는 이런 표현이 불가능하다. #if defined(A) && (defined(B) || defined(C)) 출처 : https://zoosso.tistory.com/1201 2023. 1. 31.
C ] sscanf() 사용법 %d : 공백으로 구분된 문자열을 정수로 읽어들인다. %s : 공백으로 구분된 문자열을 문자열로 읽어들인다. %*s : 공백으로 구분된 문자열을 읽어들이지 않고 건너뛴다. #include #include int main(void) { char *str = "ABC 123"; int num = 0; sscanf(str, "%*s %d", &num); printf("%d\n", num); } %[A] : 현재 위치에서 문자 A가 있는 경우 A를 문자열로 읽어들인다. %*[A] : 현재 위치에서 문자 A를 읽어들이지 않고 건너뛴다. %[^B] : 현재 위치에서 문자 B 직전까지 문자열로 읽어들인다. %*[^B] : 현재 위치에서 문자 B 직전까지를 읽어들이지 않고 건너 뛴다. (포인터는 B 위치) #inclu.. 2023. 1. 15.
C ] strtol, strtoul : 정수 문자열을 진수 선택하여 long/unsigned long 값으로 변환 (2진수, 8진수, 10진수, 16진수) strtol strtol 함수는 정수로 구성된 문자열 str을 세번째 파라미터인 진수체계로 판단하여 long 형식 값으로 반환한다. 더이상 계산할 수 없는 문자를 발견하면 두번째 파라미터인 endptr에 해당 위치를 저장한다. #include long strtol (const char* str, char** endptr, int base); - 파라미터str : long 형식 값을 구할 문자열endptr : 계산을 끝낸 위치를 저장할 문자열 포인터base : 진수- 리턴 값 : 계산된 long 형식 값 #include #include int main(void){ char src[100]="123 ff 16 1001 -10"; char *pos=NULL; long value1=0,value.. 2023. 1. 15.
C ] strtok, strtok_r : 구분 문자로 문자열 쪼개기 strtok 함수는 문자열을 구분문자(delimiter) 단위로 쪼개는데 사용되는데 이렇게 쪼개진 문자열을 토큰(token)이라고 한다. str에 쪼개고자 하는 문자열을 전달하면 str의 가장 첫번째 문자가 토큰의 시작이 되고 delim에 포함된 문자들 중 하나를 만나는 곳이 토큰의 마지막이 되며, 원래 delimiter가 있었던 토큰의 마지막을 null-terminted 하고 토큰의 시작 주소를 리턴한다. strtok 함수는 내부에 static 변수로 str 문자열에서 작업을 끝낸 다음 위치를 기억하고 있기 때문에, 이 다음에 str인자로 NULL을 전달하며 호출하면 이전에 찾았던 토큰 바로 다음 문자부터 시작해서 분리작업을 진행한다. 그러다 맨처음에 전달된 str 문자열의 NULL 문자에 도달하게 되.. 2023. 1. 15.
윈도우 소켓 ] 소켓 프로그래밍 용어 및 함수 정리 출처 : 윤성우의 열혈 TCP/IP 소켓 프로그래밍 소켓 생성시 필요한 매개변수 첫번째, 두번째 인자로 전달된 정보를 통해 소켓의 프로토콜이 사실상 결정되기 때문에 세번째 인자로 0을 전달해도 된다. 프로토콜 체계 소켓의 타입 1. SOCK_STREAM 중간에 데이터가 소멸되지 않고 목적지로 전송된다. 전송 순서대로 데이터가 수신된다. 전송되는 데이터의 경계가 존재하지 않는다 여러번의 write 함수호출을 통해 전송된 데이터를 한번의 read 함수 호출을 통해 전부 수신할 수 있고, 반대로 한번의 write 함수호출을 통해 전송된 데이터를 여러번의 read 함수 호출을 통해 수신할 수 있다. write/read 함수 호출 횟수가 큰 의미를 갖지 못한다. 수신된 데이터는 소켓에 존재하는 버퍼에 저장되고, .. 2023. 1. 1.
윈도우 소켓 ] TCP 에코 서버, 클라이언트 및 동작원리 TCP 서버의 함수 호출 순서 TCP 서버에서 listen 함수호출을 통해 연결요청 대기상태에 들어가면 클라이언트가 connect() 함수호출을 통해서 연결요청을 할 수 있다. int listen(SOCKET s, int backlog); s : 연결요청 대기상태에 두고자 하는 소켓 전달. 이 함수 인자로 전달된 소켓이 서버 소켓(리스닝 소켓)이 된다. backlog : 연결요청 대기 큐의 크기정보 전달, ex. 5가 전달되면 클라이언트의 연결요청을 5개까지 대기시킬 수 있다. 적절한 값은 실험적 결과에 의존해 결정하면 되고 일반적으로 웹서버와 같이 잦은 연결요청을 받는 서버의 경우 15 이상을 전달한다. listen 함수 호출이후 클라이언트의 연결요청이 들어왔다면, 들어온 순서대로 연결요청을 수락하고 .. 2023. 1. 1.
윈도우 소켓 ] UDP 서버, 클라이언트 📝 UDP 소켓과 TCP 소켓의 차이점 TCP 소켓 (연결지향형 SOCK_STREAM) 중간에 데이터가 소멸되지 않는다. 전송 순서대로 데이터가 수신된다. 데이터의 경계가 존재하지 않는다. 소켓 대 소켓의 연결은 반드시 1 대1의 구조이다. UDP 소켓 (비 연결지향형 SOCK_DGRAM) Flow Control 이 없다. 그러므로 SEQ, ACK 같은 메시지 전달을 하지 않는다. 연결의 설정과 해제의 과정이 존재하지 않는다. 데이터 분실 및 파손의 위험이 존재한다. 데이터 전송이 빠름 한번에 전송할 수 있는 데이터의 크기가 제한된다. 서버소켓과 클라이언트의 소켓 구분이 없이 하나의 소켓으로 둘 이상의 노드와 데이터 송수신이 가능하다. UDP 송수신 함수 #include int sendto(SOCKET .. 2022. 12. 27.
윈도우 소켓 ] Winsock 라이브러리 링크하기 Winsock이란? Windows Sockets API(WSA)로 인터넷 네트워크 및 소켓과 관련된 함수들을 제공해준다. Winsock은 버전1과 버전2가 있으며 Winsock1에 여러 기능이 좀 더 추가된 것이 Winsock2이다. 윈도우에서 소켓 프로그래밍을 하기 위해선 헤더를 포함하고 라이브러리를 링크시켜야한다. 라이브러리를 링크하는 3가지 방법이 있다. 셋 중 하나를 택하면 된다. 1. 프로젝트 우클릭 - 속성 - 링커 - 입력 - 추가종속성에 ws2_32.lib 를 추가한다. 2. 소스코드 위에 다음과 같은 전처리기 지시문을 작성한다. #pragma comment(lib,"ws2_32") 3. 링크할 라이브러리의 경로를 찾아가 직접 ws2_32.lib 파일을 프로젝트에 추가한다. (프로젝트 우클.. 2022. 12. 16.
C/C++ ] tick / 시간 측정하기 C 인 경우 time.h 를 포함하고 C++인 경우 ctime을 포함한다. #include #include 시간 측정은 두 헤더에 모두 포함된 clock()함수를 사용하면 된다. clock_t clock(void); 반환형은 clock_t 타입인데 따라가보면 그냥 long 타입이다. typedef long clock_t; 그리고 반환하는 내용으로 프로그램 실행 시작부터 경과된 시간을 ms 단위의 정수형으로 반환한다. 사용방법 #include #include int main() { long startTime = (long)clock(); while (1) { long currentTime = (long)clock(); if (currentTime - startTime >= 1000UL) { printf(".. 2022. 12. 14.
C ] 가변인자 매크로를 활용한 디버그 로그 남기기, Predefined macros 함수의 가변인자 함수가 있듯이 매크로에도 가변인자 매크로가 있다. #define printlog(fmt, ...) printf(fmt, __VA_ARGS__) printlog(fmt, ...) 의 "..."이 "__VA_ARGS__"로 확장된다. 그리고 아래에서 __VA_ARGS__ 앞에 붙은 ##은 인수가 전혀없는 경우에 오류를 내지 않기 위해 gcc에서 도입한 표기법이다. 앞에 ##을 붙이지 않으면 인수가 전혀 없는 경우에 printf("",) 이런식으로 컴마가 붙은채로 확장되어 오류를 낼 것이다. 이런 가변인자 매크로는 디버그용 로그를 남길 때 유용하게 사용된다. C언어에 미리 정의된 매크로들을 사용하여 오류가난 파일명, 라인넘버, 함수명을 알 수 있다. #include #include #defin.. 2022. 12. 11.
전처리기 ] # 문자열화 연산자 # 연산자 : 문자열 치환 # 연산자는 함수형 매크로에서 매개변수를 문자열로 변환하는데 사용된다. 또한 매크로가 문자열과 나란히 쓰이면 하나의 문자열로 간주된다. 따라서 다음과 같은 결과가 나온다. #include #define STR(x) #x int main() { printf("%s\n", STR(01234)"56789"); return 0; } 문제가 발생하는 경우는 아래와 같은 경우다. #include #define NAME HongGilDong #define STR(x) #x int main() { puts(STR(NAME)); return 0; } HongGilDong이 출력되길 의도했지만 NAME이 출력되었다. 이에 대한 해결 방법은 다음과 같다. #define STR_(x) #x #def.. 2022. 12. 9.
C ] 빅엔디안 리틀엔디안 변환함수 구현 + 매크로 함수 작성시 주의점 htons(), htonl(), ntohs(), ntohl() 함수를 쓰지 않고 직접 구현하기 #include #define uint16_t unsigned short #define uint32_t unsigned int #define SWAP_UINT16(x) ((uint16_t)((((x) & 0xff00) >> 8) | (((x) & 0x00ff) > 24) | (((x) & 0x00ff0000) >> 8) | (((x) & 0x0000ff00) 8) & 0x00ff) + (((x) & 0x00ff) 2022. 10. 22.
C ] memset 함수 구현 void *my_memset(void *s, int c, int len) { unsigned char *p = (unsigned char *)s; while (len > 0) { *p = c; p++; len--; } return (s); } #include void *my_memset(void *s, int c, int len) { unsigned char *p = (unsigned char *)s; while (len > 0) { *p = c; p++; len--; } return (s); } int main() { char str[13] = "hello world!"; for (int i = 0; str[i] != '\0'; i++) { printf("%c", str[i]); } printf("\n.. 2022. 10. 9.
C, Linux ] pthread 사용해 보기 #include #include #include #include #include void *thread1_func (void *vargp) { unsigned short cnt=0; printf("Thread 1 function starts...\n"); while(1) { sleep(1); printf("thread1_func is running ===>(%d)\n", cnt++); } } void *thread2_func (void *vargp) { unsigned short cnt=0; printf("Thread 2 function starts...\n"); while(1) { sleep(3); printf("thread2_func is running =======> (%d)\n", cnt++); .. 2022. 8. 25.
C ] 명령 프롬프트 구현 (함수포인터 사용) #include #include /* for strcmp() strlen*/ //#include /* for usleep() */ #include #include // argv MAX #define MAX_CMD_NUM 10 // string MAX #define BUF_LEN 128 int cmd_continue = 0; typedef int cmd_func(int argc, char* argv[]); struct Command_List { char* cmd; cmd_func* func; char* help_str; }; int cmd_test1(int argc, char* argv[]) { if (argv[1] == NULL) { printf("test 1 command received. \n"); .. 2022. 8. 25.
C ] 전처리기 (Preprocessor) 전처리기(preprocessor)는 프로그램을 컴파일할 때 컴파일 직전에 실행되는 것으로, 전처리기가 실행되면 각 코드 파일에서 #으로 시작하는 지시자(directives)를 찾는다. #include 지정된 파일을 그 위치에 복사, 파일을 포함시키기 위해 사용한다. Current directory 에서 먼저 찾고 그 다음 표준 라이브러리에서 찾음 // 표준 라이브러리 #include // 사용자가 정의한 파일 #include "filename" #define 심볼릭 상수나 매크로를 생성할 때 사용. 컴파일 시 텍스트로 대체됨. 매크로 사용의 장점은 코딩 오버헤드를 줄여줌. #define PI 3.141592 #define CIRCLE_AREA( x ) ( (PI) * ( x ) * ( x ) ) #def.. 2022. 8. 24.
C, Linux ] ls 명령어 구현 리눅스의 ls 명령어 구현하기 #include #include // 디렉터리 관련 DIR, struct dirent, opendir(), readdir(), closedir() 등이 정의된 헤더 포함 #include // Unix 에 쓰이는 표준 심볼들과 상수, 함수들이 정의된 헤더 포함 #include int main(int argc, char* argv[]) { // cwd에 1024 byte 동적할당 char * cwd = (char *)malloc(sizeof(char) * 1024); // DIR 과 dirent 구조체 포인터를 만들고 일단 NULL 대입 DIR * dir = NULL; struct dirent * entry = NULL; // 추가 인자 없이 실행된 경우 if(argc==1){.. 2022. 8. 17.
C, Linux ] main 함수의 매개변수 사용해서 파일 입출력 하기 main 함수에 전달되는 파라미터를 활용해 코드를 짤 때는 아래와 같이 출력해 디버깅 해보면 편하다. for(int i=0; i< argc; i++){ printf("%s\n",argv[i]); } 1. main 함수의 argument 로 파일이름과 파일에 저장할 문자열을 입력받아 파일을 생성하는 프로그램 #include #include #include int main(int argc, char *argv[]){ /* for(int i=0; i< argc; i++){ printf("%s\n",argv[i]); } */ if (argc < 3) { printf("Usage: fileio.exe "); return 0; } FILE *fp; fp = fopen(argv[1], "w"); if(fp==NULL.. 2022. 8. 17.
C ] 가변인자 함수 만들기, 가변인자 출력함수 만들기 printf() 함수의 경우 내가 원하는 만큼 인자를 넘길 수있다. 예를 들면 printf("%d", a);// 인자 2개 printf("%d %d", a, b);// 인자 3개 이게 가능한 이유는 printf()가 매개변수의 개수가 정해지지 않은 가변인자 함수이기 때문이다. 가변인자 함수로 인자의 개수와 상관없이 정수형 인자를 여러개 받아서 인자 모두를 더한 값을 반환하는 함수를 만들어보도록 하겠다. #include // stdarg.h 포함. va_list, va_start, va_arg, va_end가 정의된 헤더 파일 #include int sum(int num_args, ...) { // 가변 인자의 개수를 받음, ...로 가변 인자 설정 va_list ap;// 가변 인자 목록 포인터 va_s.. 2022. 8. 12.
[ Visual Studio ] CRT 라이브러리로 메모리 누수 탐지하기 Visual Studio에서 CRT 라이브러리를 사용해 메모리 누수 탐지하는 방법 1. 소스 상단에 아래 지시문을 포함한다. #define _CRTDBG_MAP_ALLOC #include #include 2. 종료지점 직전에 아래 코드를 추가한다. _CrtDumpMemoryLeaks(); 3. F5를 눌러 디버그 모드로 실행 후 종료한다. 테스트를 위해 어떤 함수안의 free를 주석처리하고 디버그 모드로 실행한 뒤 그 함수를 호출하고 종료해보았다. 아래와 같이 메모리 누수가 감지되었다고 뜬다. 나는 테스트해본거라 어느위치에서 누수가 된건지 알고있지만 모르겠다면 4. 메인함수 안쪽 상단에 아래 코드를 넣고 매개변수로는 위에서 본 번호인 111을 넣은 뒤 디버그 모드로 다시 실행한다. _CrtSetBreak.. 2022. 5. 2.
[ C언어 ] realloc은 얼마나 자주 메모리 주소를 옮길까? realloc함수에 대한 설명을 찾아보면 다음과 같은 과정으로 작동한다고 한다. 1. 동적할당된 메모리 크기를 변경해 재할당함 (기존 주소일수도 있고, 새로운 주소일 수도 있음) 2. (새로운 주소에 할당한 경우) 기존 주소에 있던 값을 새로운 주소에 복사하고 원래 주소는 할당해제함 얼마나 많이 메모리 주소를 옮겨갈까 궁금해서 아래 코드로 테스트를 해보았다. #define _CRTDBG_MAP_ALLOC #include #include #include #include int main(void) { int arraysize = 10; int i = 0; char* test = (char*)malloc(sizeof(char) * arraysize); int plus = 10; float chk = 0; fo.. 2022. 5. 2.
[ C언어 ] scanf의 리턴값 놀랍게도 scanf에는 리턴값이 있다. 함수가 읽어들여 저장에 성공한 데이터 개수가 반환값이다. 예를들어 위의 경우에는 정수 2개를 b, c 변수에 저장하는데 성공했으므로 리턴값이 2이다. 정수를 입력해야하는데 문자를 입력한 경우 변수 b, c에 저장하는것 둘 다 실패했으므로 리턴값이 0 변수 b에 저장하는 것만 성공했으므로 리턴값이 1 그런데 순서를 바꿔서 a 1 을 입력하면 scanf의 리턴값이 0이다. 이는 변수 b에 저장되지 못한 문자들(개행문자 포함)이 입력버퍼에 남아 그 다음 입력을 방해하니 변수 c에 저장하는 것 또한 실패한 것이다. 이에대한 해결방법 링크 : https://eteo.tistory.com/33 scanf, scanf_s "%d"로 정수 입력 받으려다 문자(열)이 잘못 들어왔을.. 2022. 4. 27.
[ C언어 ] scanf 공백 ( 띄어쓰기 ) 포함 원하는 길이 만큼만 문자열 입력 받는 방법. 공백을 포함해서 입력받는 동시에, 배열의 길이를 넘는 입력이 들어오더라도 오류가 나지 않고 지정된 길이 만큼만 변수에 저장되는 받는 방법을 소개한다. 첫번째 방법 1. "%숫자[^\n]" #include int main(void) { char str[20]; printf("도서 이름을 입력하세요 :"); scanf_s("%20[^\n]", str, sizeof(str)); //fgets(str, 19, stdin); printf("입력하신 도서이름은 %s 입니다.\n", str); return 0; } 예를들어 char 배열의 크기가 20인 경우, null문자가 들어갈 공간을 생각해서 그보다 작은 숫자를 지정해주면 아무리 입력이 많이들어와도 딱 그 길이 만큼만 배열에 저장된다. 한글의 경우 2바이트를 차.. 2022. 4. 27.