C Programming

dongwoo·2024년 10월 10일

day 1

  1. basic
printf
scanf

\" \'
\n \b \t

/*
	정수     :  %d      decimal
    			%x      hexa decimal
                %o      octal

	실수     :   %lf    long float
    문자     :   %c     character
    문자열   :   %s     string
*/

// lvalue: 변수
// rvalue: 변수, 상수
  1. operator
/* 
	산술연산자: 
      +
      -
      *
      /
      % -> 나머지 연산은 정수 연산에만
*/

day 2

c file 	-> main 함수를 맨 앞쪽으로 두는 습관을 가져라.
		-> main 함수에서 쓰이는 함수는 앞쪽에 정의하라.
        
전역변수 -> 남발하지 말자
		-> 싱글톤 사용하자
  1. operator
/*
    관계연산자 :
            >   >=
            <   <=
            ==  !=
    참:     1, 1.0, 0.1, -1, 2, ...
    거짓:   0, 0.0
*/
/*
    논리연산자 :
            &&  ||	!
*/

Q. 대문자 전체를 while문을 이용하여 출력해보세요.

#1
void get_capital_letter()
{
    int i = 'A';
    while (i <= 'Z')
    {
        printf("%c", i);
        i++;
    }
}


#2
void get_capital_letter()
{
    int i = 0;
    while (i < 26)
    {
        printf("%c", i + 'A');
        i++;
    }
}

day 3

c언어는 반환을 한 개밖에 하지 못함 -> 포인터 사용

/*
	연산자 우선순위

	1. 산술 연산자 ( * , / , % ) -> ( + , - )
	2. 관계 연산자
	3. 논리 연산자
	4. 대입 연산자
*/

Q. 2개의 정수 중에서 큰 값을 찾는 함수를 만드세요.

#1
int max_2(int a, int b)
{
    if (a > b)
        return a;

    return b;
}


#2
int max_2(int a, int b)
{
    if (a > b)
        b = a;

    return b;
}

Q. 4개의 정수 중에서 큰 값을 찾는 함수를 만드세요.

#1
int max_4(int a, int b, int c, int d)
{
    if (a > b)
        b = a;

    if (b > c)
        c = b;

    if (c > d)
        d = c;

    return d;
}


#2
int max_4(int a, int b, int c, int d)
{
    if (d < a)
        d = a;

    if (d < b)
        d = b;

    if (d > c)
        d = c;

    return d;
}


#3
int max_4(int a, int b, int c, int d)
{
    int max = a;

    if (max < b)
        max = b;

    if (max < c)
        max = c;

    if (max < d)
        max = d;

    return max;
}


#4 (reuse)
int max_4(int a, int b, int c, int d)
{
    return max_2(a, max_2(b, max_2(c, d)));
}


#5 (reuse)
int max_4(int a, int b, int c, int d)
{
    return max_2(max_2(a, b), max_2(c, d));
}

Q. 1 부터 n 까지의 합을 구하는 함수를 만드세요.

int getSum(int n)
{
    int sum = 0;
    int i = 1;
    while (i <= n)
    {
        sum += i;
        i++;
    }

    return sum;
}

day 4

c 에서 함수명 관용적으로 snake case 사용 
					-> ex) say_hello()
  1. array
/*
    변수 선언 = 자료형 + 변수명

    -> 자료형 = 변수 선언 - 변수명
*/

// 배열 = 포인터 = 주소

void show_array(int arr[], int size);
void show_array2(int arr[]);

int main()
{
    int ages[3] = {10, 20, 30};

    printf("%d\n", ages);         // 메모리 주소 출력
    printf("%d\n", sizeof(ages)); // 4 byte x 3
    printf("%d\n", sizeof(ages) / 4);
    printf("%d\n", sizeof(ages) / sizeof(int));
    printf("%d\n", sizeof(ages) / sizeof(ages[0]));
	
    int size = sizeof(ages) / sizeof(ages[0]);
    
    show_array(ages, size);
    show_array2(ages);

    return 0;
}

void show_array(int arr[], int size)
{
    int i = 0;
    while (i < size)
    {
        printf("%d ", arr[i]);
        i++;
    }
    printf("\n");
}

void show_array2(int arr[])
{
    /*
        아래의 size는 원하는 결과가 아님.

        c 언어에는 배열의 크기를 구할 수 있는 함수는 없음.
        변수 선언된 곳에서 sizeof '연산자'를 사용하여 매개변수로 전달
    */
    int size = sizeof(arr) / sizeof(arr[0]);

    int i = 0;
    while (i < size)
    {
        printf("%d ", arr[i]);
        i++;
    }
    printf("\n");
}

Q. 0 ~ 99 사이의 양수 10개를 배열에 저장하는 함수를 만드세요.

void make_randoms(int *p, int size)
{
    int i = 0;
    while (i < size)
    {
        p[i] = rand() % 100;
        i++;
    }
}

Q. 1차원 배열에서 홀수만 출력하는 함수를 만드세요.

void show_odd(int *p, int size)
{
    int i = 0;
    while (i < size)
    {
        if (p[i] % 2)
            printf("%d ", p[i]);

        i++;
    }
}
  1. pointer
#include <stdio.h>

// * : 곱셈(*), 곱셈복합(*=), 주석(/* */), 변수 선언(int*), 값 접근(*p)
int main()
{
    
    int a = 7;

    printf("%d\n", a);  // 7
    printf("%x\n", &a); // 61ff18
    printf("%p\n", &a); // 0061FF18

    int *p = &a;
    printf("%p\n", p);  // 0061FF18
    printf("%d\n", *p); // 7

    *p = 99;
    printf("%d\n", a); // 99

    return 0;
}

Q. 2개 변수의 값을 교환하는 함수를 만드세요.

void swap(int *p, int *q)
{
    int tmp = *p;
    *p = *q;
    *q = tmp;
}

day 5

  1. pointer
int main()
{
    int digits[4] = {2, 4, 6, 9};

    int *p = digits;

    printf("%d\n", digits);
    printf("%d\n", p);
    printf("%d\n", p + 1); // 포인터가 가리키는 자료형의 크기만큼 증가

    printf("%d\n", digits[0]);
    printf("%d\n", p[0]);
    printf("%d\n", *p);

    return 0;
}

show_array 함수

#1
void show_array(int *p, int size)
{
    int i = 0;
    while (i < size)
    {
        printf("%d ", p[i]);
        i++;
    }
    printf("\n");
}


#2
void show_array(int *p, int size)
{
    int *end = p + size;
    while (p < end)
    {
        printf("%d ", *p++);
    }
    printf("\n");
}

find_max 함수

#1
int find_max(int *p, int size)
{
    int i = 0, max = p[0];

    while (i < size)
    {
        if (max < p[i])
            max = p[i];

        i++;
    }

    return max;
}


#2
int find_max(int *p, int size)
{
    int max = *p;
    int *end = p + size;
    while (p < end)
    {
        if (max < *p)
            max = *p;

        p++;
    }

    return max;
}
  1. sentinel
// sentinel = '보초' 라는 뜻
// sentinel 로 가장 좋은 것은 0

int main()
{
    // 최대 255자
    // char s[256] = {'h', 'e', 'l', 'l', 'o'};
    char s[256] = "hello";

    /*
        문자열 맨 마지막에는 sentinel 존재
        sentinel = \0 = NULL = ascii 0
    */

    // 보안에 안좋은 코드
    printf("%s\n", s); // hello

    s[1] = '\0';

    printf("%s\n", s); // h

    return 0;
}

show_sentinel 함수

void show_sentinel(int *p)
{
    while (*p)
        printf("%d ", *p++);

    printf("\n");
}
  1. string
#include <stdio.h>
#include <string.h>

int main()
{
    char s[256] = "mountain";
    char buffer[256];

    // 문자열 길이
    printf("length : %d\n", strlen(s)); // length : 8

    // 문자열 복사
    strcpy(buffer, s);
    puts(buffer); // mountain

    // 문자열 덧셈
    strcat(buffer, s);
    puts(buffer); // mountainmountain

    // 문자열 관계
    printf("compare : %d\n", strcmp(s, buffer)); // compare : -1
    printf("compare : %d\n", strcmp(s, s));      // compare : 0
    printf("compare : %d\n", strcmp(buffer, s)); // compare : 1

    // 특정 문자 찾기
    printf("find : %d\n", strchr(s, 'a'));     // find : 6422053 -> 주소
    printf("find : %d\n", *strchr(s, 'a'));    // find : 97 -> 'a' 의 ascii code
    printf("n_th : %d\n", strchr(s, 'a') - s); // n_th : 5 -> 'a'의 인덱스 위치

    // 특정 문자열 찾기
    printf("find : %s\n", strstr(buffer, s));     // find : mountainmountain
    printf("find : %d\n", strstr(buffer, s));     // find : 6421792
    printf("find : %d\n", strstr(buffer, "sea")); // find : 0 -> 실패하면 0(null pointer) 반환


    return 0;
}

my_len 함수

#1
int my_len(const char *s)
{
    int i = 0;
    while (s[i++])
        ;

    return i - 1;
}


#2
int my_len(const char *s)
{
    const char *p = s;

    while (*p++)
        ;

    return p - s - 1;
}

my_copy 함수

#1
char *my_cpy(char *dst, const char *src)
{
    int i = 0;
    while (src[i])
    {
        dst[i] = src[i];
        i++;
    }
    dst[i] = '\0';

    return dst;
}


#2
char *my_cpy(char *dst, const char *src)
{
    char *base = dst;

    while (*src)
    {
        *dst++ = *src++;
    }
    *dst = '\0';

    return base;
}


#3
char *my_cpy(char *dst, const char *src)
{
    char *base = dst;

    while (*dst++ = *src++)
        ;

    return base;
}

day 6

/* 
	반복문에서
    
    continue 	: 해당 블록에서 아래 코드를 실행하지 않고, 다시 블록 실행 
        			   -> 증감 연산자 위에 쓰면 무한루프가 발생할 수 있음
    
    break 		: 반복문 종료
*/            

Q. 2중 for문을 사용하여 다음을 각각 출력하세요.

*
**  
*** 
****
------------
****
*** 
**  
*
------------
****
 ***
  **
   *
------------
   *
  **
 ***
****
풀이방법은 다양하지만 다음과 같이 생각하면 편하다.

//   0123		3210
// 0 *			   *
// 1 **			  **
// 2 ***		 ***
// 3 ****		****

// 3 ****		****
// 2 ***		 ***
// 1 **			  **
// 0 *			   *
void show_star()
{
    for (int i = 0; i <= 3; i++)
    {
        for (int j = 0; j <= 3; j++)
        {
            if (i >= j)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }

    for (int i = 3; i >= 0; i--)
    {
        for (int j = 0; j <= 3; j++)
        {
            if (i >= j)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }

    for (int i = 3; i >= 0; i--)
    {
        for (int j = 3; j >= 0; j--)
        {
            if (i >= j)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }

    for (int i = 0; i <= 3; i++)
    {
        for (int j = 3; j >= 0; j--)
        {
            if (i >= j)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }
}
  1. 2d_array
#include <stdio.h>

void show_2d_array(int a[][5]);
int sum_2d_array(int a[][5]);

int main()
{
    // 배열: 같은 자료형을 가진 값들 끼리 묶은 것
    int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}}; // 3개 배열

    int(*b)[5] = a;
	
    a[0][0] = 99;
    b[2][4] = -1;
    
    printf("%d\n", a);        // 주소 6422240
    printf("%d\n", a[0]);     // 주소 6422240
    printf("%d\n", a[0][0]);  // 99
    printf("%d\n", &a[0][0]); // 주소 6422240
    printf("%d\n", &a[0][1]); // 주소 6422244
    printf("%d\n", &a[1][0]); // 주소 6422260

    show_2d_array(a);
    printf("sum : %d\n", sum_2d_array(a));
    printf("sum : %d\n", sum_2d_array(*&a));
    printf("sum : %d\n", sum_2d_array(&a[0]));

    int n = 3;
    int *p = &n;
    int **q = &p;
    int ***r = &q;

    printf("%d\n", *p);
    printf("%d\n", **q);
    printf("%d\n", ***r);

    return 0;
}

void show_2d_array(int a[][5])
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
}

int sum_2d_array(int a[][5])
{
    int s = 0;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            s += a[i][j];
        }
    }
    return s;
}
  1. file
#include <stdio.h>

void print_file_1();

int main()
{
    print_file_1();
    return 0;
}

// 텍스트: txt, csv, json, c, cpp, py, ...
// binary: exe, hwp, xls, ppt, jpg, ...

void print_file_1()
{
    FILE *fp = fopen("poem.txt", "r");
    // printf("%d\n", fp);
	
    int ch;
    
    // for (int i = 0; i < 1000; i++)
    // {
    //     int ch = fgetc(fp);
    //     putchar(ch);
    // }
    
    // 퀴즈
    // fgetc 함수를 사용해서 파일 전체를 출력하세요.
    
    while (1)
    {
        ch = fgetc(fp);

        if (ch == -1)
            break;

        putchar(ch);
    }


    fclose(fp);
}

day 7

  1. 2d_array
#include <stdio.h>

void show_array(int *p, int size);

int main()
{
    int grid[3][4] = {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11}};

    // 퀴즈
    // 2차원 배열에서 n번째 요소를 출력하는 함수를 만드세요.
    
    show_array(grid[0], 4);
    show_array(grid[1], 4);
    show_array(grid[2], 4);
    show_array(&grid[2][0], 4);

    // 퀴즈
    // 2차원 배열을 출력하는 함수를 만드세요.
    // 2차원 형식을 유지하지 말고, 한 줄로 출력해주세요.
    
    show_array(grid[0], 12);

    return 0;
}

void show_array(int *p, int size)
{
    for (int i = 0; i < size; i++)
    {
        printf("%d ", p[i]);
    }
    printf("\n");
}
  1. file
#include <stdio.h>
#include <string.h>

void print_file_1();
void print_file_2();
void write_file_1();
void write_file_2();
void csv_file();

int main()
{
    // print_file_1();
    // print_file_2();
    // write_file_1();
    // write_file_2();
    csv_file();

    return 0;
}

// 텍스트: txt, csv, json, c, cpp, py, ...
// binary: exe, hwp, xls, ppt, jpg, ...

// 퀴즈
// fgetc 함수를 사용해서 파일 전체를 출력하세요.
void print_file_1()
{
    FILE *fp = fopen("poem.txt", "r");

    int ch;
    while (1)
    {
        ch = fgetc(fp);

        if (ch == -1)
            break;

        putchar(ch);
    }

    fclose(fp);
}

// 퀴즈
// fgets 함수를 사용해서 파일 전체를 출력하세요.
void print_file_2()
{
    FILE *fp = fopen("poem.txt", "r");

    char buf[256];

    // char *p;
    // while (1)
    // {
    //     p = fgets(buf, sizeof(buf), fp);
    //     if (p == NULL)
    //         break;
    //     printf("%s", buf);
    // }
	
     while (fgets(buf, sizeof(buf), fp))
    {
        printf("%s", buf);
    }
    
    fclose(fp);
}

void write_file_1()
{
    FILE *fp = fopen("sample.txt", "w");

    for (int i = 0; i < 26; i++)
        fputc('a' + i, fp);

    fputc('\n', fp);

    fputs("Friday, i am happy!", fp);

    fclose(fp);
}

// 퀴즈
// 사용자가 exit을 입력할 때까지 입력한 모든 문자열을 파일에 저장해 보세요.
void write_file_2()
{
    FILE *fp = fopen("sample.txt", "w");

    char buf[256];

    while (1)
    {
        scanf("%s", buf);

        if (strcmp(buf, "exit") == 0)
            break;

        fputs(buf, fp);
        fputc('\n', fp);
    }

    fclose(fp);
}

void csv_file()
{
    FILE *fp_w = fopen("sample.csv", "w");

    // printf("%d %lf %c %s\n", 3, 4.5, 'A', "ace");

    // fprintf(fp_w, "%d,%lf,%c,%s\n", 3, 4.5, 'A', "ace");
    // fprintf(fp_w, "%d,%lf,%c,%s\n", 1, 2.7, 'B', "bed");

    char buf[256];
    // 모든 자료형을 문자열로 변환할 수 있다.
    sprintf(buf, "%d,%lf,%c,%s\n", 3, 4.5, 'A', "ace");
    fputs(buf, fp_w);
    sprintf(buf, "%d,%lf,%c,%s\n", 1, 2.7, 'B', "bed");
    fputs(buf, fp_w);

    fclose(fp_w);

    FILE *fp_r = fopen("sample.csv", "r");

    int a;
    double b;
    char c;
    char d[256];

    fscanf(fp_r, "%d,%lf,%c,%s", &a, &b, &c, &d);
    printf("%d %lf %c %s\n", a, b, c, d);

    fscanf(fp_r, "%d,%lf,%c,%s", &a, &b, &c, &d);
    printf("%d %lf %c %s\n", a, b, c, d);

    fclose(fp_r);
}
  1. Stack

#include <stdio.h>

// C -> 자료구조 -> C++

// 스택: 곽티슈, 프링글스, 변수 할당, 함수 호출, 무르기

int g_stack[256];
int g_top = 0; // 데이터가 들어가는 위치

void push(int n);
int pop();
int is_empty();

void show_array(int *p, int size);

int main()
{
    push(1);
    push(2);
    push(3);

    // 퀴즈
    // 스택에 들어있는 모든 데이터를 출력하세요.

    while (!is_empty())
    {
        printf("%d\n", pop());
    }

    // 퀴즈
    // 스택을 사용해서 1차원 배열을 거꾸로 뒤집어보세요.
    
    int orders[] = {5, 1, 8, 3, 4, 9, 2, 1};
    int size = sizeof(orders) / sizeof(orders[0]);

    for (int i = 0; i < size; i++)
    {
        push(orders[i]);
    }

    for (int i = 0; i < size; i++)
    {
        orders[i] = pop();
    }

    show_array(orders, size);

    // 퀴즈
    // 스택을 사용하지 말고 1차원 배열을 거꾸로 뒤집어보세요.
    
    for (int i = 0; i < size / 2; i++)
    {
        int tmp = orders[i];
        orders[i] = orders[size - 1 - i];
        orders[size - 1 - i] = tmp;
    }

    show_array(orders, size);

    return 0;
}

void push(int n)
{
    g_stack[g_top++] = n;
}

int pop()
{
    return g_stack[--g_top];
}

int is_empty()
{
    return g_top == 0;
}

void show_array(int *p, int size)
{
    for (int i = 0; i < size; i++)
    {
        printf("%d ", p[i]);
    }
    printf("\n");
}
  1. struct
#include <stdio.h>

// 관례적으로 대문자를 씀
struct POINT
{
    int x, y;
};

struct RECT
{
    struct POINT pt1, pt2;
};

void show_point(struct POINT pt);
struct POINT change_1();
void change_2(struct POINT *p);

int main()
{
    struct POINT pt = {10, 20};

    show_point(pt);

    // 퀴즈
    // scanf 함수를 통해 pt에 좌표를 입력 받아 보세요.

    scanf("%d %d", &pt.x, &pt.y);
    show_point(pt);

    // 퀴즈
    // POINT 구제의 x, y를 88, 99로 변경하는 함수를 만드세요.

    pt = change_1();
    show_point(pt);

    change_2(&pt);
    show_point(pt);

    struct RECT rc = {{1, 2}, {3, 4}};

    // 퀴즈
    // RECT 구조체에 포함된 모든 값을 출력하세요.

    printf("%d %d %d %d\n", rc.pt1.x, rc.pt1.y, rc.pt2.x, rc.pt2.y);
    show_point(rc.pt1);
    show_point(rc.pt2);

    // 퀴즈
    // p를 선언하고 p를 사용해서 RECT의 모든 값을 출력하세요.
    
    struct RECT *p = &rc;
    printf("%d %d %d %d\n", (*p).pt1.x, p->pt1.y, *(&(*p).pt2).x, (&p->pt2)->y);

    return 0;
}

void show_point(struct POINT pt)
{
    printf("%d %d\n", pt.x, pt.y);
}

struct POINT change_1()
{
    struct POINT pt = {88, 99};
    return pt;
}

void change_2(struct POINT *p)
{
    // (*p).x = 88;
    // (*p).y = 99;

    p->x = 88;
    p->y = 99;
}
profile
hello world!

0개의 댓글