Study/C언어

[C언어] 코딩도장 공부 (Unit 41~60)

dDong2 2022. 9. 23. 12:45

Unit 41. 문자열 길이

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text[30];

    scanf("%s", &text);

    int text_length = strlen(text);

    printf("%d", text_length);

    return 0;
}

문자열 길이를 30이하여서 배열로 30 받음!

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text1[30], text2[30];

    scanf("%s %s", &text1, &text2);

    printf("%d", strcmp(text1, text2));

    return 0;
}

위의 문제와는 다르게 %d로 받는 인자에 함수 사용해서 바로 출력

 

 

Unit 42. 문자열 복붙

char *s1 = "Hello"; "";와 같은 문자열 포인터에 할당된 문자열 리터럴은

읽기 전용인데, 그 이유는 실행 파일의 읽기 전용 데이터 섹션에 배치하기 때문이다.

Windows PE: .rdata 각 운영체제별 읽기 전용 데이터 섹션에 따라가서다.

(malloc으로 동적 메모리 할당 후 strcpy가 가능)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[31];
    char s2[31];

    scanf("%s", &s1);
    strcpy(s2, s1);

    printf("%s\n", s1);
    printf("%s\n", s2);

    return 0;
}

strcpy -> 문자열 복사 / strcat -> 문자열 붙이기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char s1[40];

    scanf("%s", &s1);
    strcat(s1, "th");

    printf("%s\n", s1);

    return 0;
}

 

 

Unit 43. 문자열 만들기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    int number;
    char name[31], result[40];

    scanf("%d %s", &number, &name);

    if (number == 1)
        sprintf(result, "%dst %s", number, name);
    else if (number == 2)
        sprintf(result, "%dnd %s", number, name);
    else if (number == 3)
        sprintf(result, "%drd %s", number, name);
    else
        sprintf(result, "%dth %s", number, name);
    
    printf("%s\n", result);

    return 0;
}

다른 방법도 있겠지만, 앞서 배운 내용이 sprintf 출력이여서

sprintf 함수를 이용해 result에 출력할 내용을 적어준다.

 

 

Unit 44. 문자열 검색

문자열 검색 함수는 대소문자를 구분하게 된다. (strstr)

참고로 검색할 때 문자보다는 단어로 검색하는 경우가 많아서

프로그램을 만들 때도 문자열 찾기 함수를 더 자주 쓴다고 한다. (strstr)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text[1000];

    scanf("%[^\n]s", &text);

    int length = 0;
    char* ptr = strchr(text, ' ');

    while (ptr != NULL)
    {
        length++;
        ptr = strchr(ptr + 1, ' ');
    }
    
    printf("%d", length);

    return 0;
}

공백을 검색할 때마다 증감연산자로 length를 증가시켰다.

 

 

Unit 45. 문자열 자르기

문자열 자르는 함수는 strtok인데 tok이 token의 약자이다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text[60];

    scanf("%s", &text);

    char* tok = strtok(text, ".");

    while (tok != NULL)
    {
        printf("%s\n", tok);
        tok = strtok(NULL, ".");
    }

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text[1001];

    scanf("%[^\n]s", &text);

    int length = 0;
    char* tok = strtok(text, " .,");

	while (tok != NULL)
	{
		if (tok != NULL && strcmp(tok, "the") == 0)
			length++;
		tok = strtok(NULL, " .,");
	}

	printf("%d", length);

    return 0;
}

이게 조금 어려웠는데, the 단어를 색출하려면 우선 공백, 점, 콤마를 빼준다.

그 다음에 NULL로 비어있는 값을 제외한 단어 중 the와 일치하는(0) 값을

조건문으로 걸어주고 맨 마지막까지(NULL이 아닐때까지) 비교해서

증감연산자를 더해준다.

 

 

Unit 46. 문자열 숫자 변환

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char s1[31];
    int num1;
    int num2;
    float num3;
    char* end;

    scanf("%[^\n]", s1);

    num1 = strtol(s1, &end, 16);
    num2 = strtol(end, &end, 10);
    num3 = strtof(end, NULL);
    
    printf("0x%x\n", num1);
    printf("%d\n", num2);
    printf("%f\n", num3);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    char s1[10];
    char s2[20];
    int num1;
    float num2;

    scanf("%d %f", &num1, &num2);

    num1 = sprintf(s1, "%d", num1);
    num2 = sprintf(s2, "%f", num2);
    
    printf("%s\n", s1);
    printf("%s\n", s2);

    return 0;
}

strtol 함수로 16진수와 10진수로 변환,

strtof 함수로 실수 변환,

sprintf 함수로 배열에 정수와 실수를 문자열로 변환한다.

 

 

Unit 47. 회문 판별과 N-gram

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main() 
{

    char text[31];

    scanf("%[^\n]s", text);

    int length;
    length = strlen(text);

    int palindrome = 1;

    for (int i = 0, j = length - 1; i < j; i++, j--) 
    {
        while (text[i] == ' ')
            i++;
        while (text[j] == ' ')
            j--;
        if (text[i] != text[j]) 
        {
            palindrome = 0;
            break;
        }
    }

    printf("%d", palindrome);

    return 0;
}

난이도가 조금 있었던 문제였다. (그래서 해답에서 힌트를 얻었다)

회문 판별을 할 변수를 정수로 주고,

i에 대한 인덱스가 공백이면 ++ 연산자를,

j에 대한 인덱스가 공백이면 -- 연산자를 대입한다.

두 인덱스 값이 같지 않으면 0을 주고 탈출한다.

예제가 nure es run 이기 때문에 회문을 돌고 1을 출력하게 된다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main()
{
    char text[11];
    int ngram, len;

    scanf("%d %s", &ngram, text);

    len = strlen(text);

    if (len < ngram)
        printf("wrong");
    else
    {
        for (int i = 0; i < len - (ngram - 1); i++)
        {
            for (int j = 0; j < ngram; j++)
            {
                printf("%c", text[i+j]);
            }
            printf("\n");
        }
    }
}

 

 

Unit 48. 구조체

구조체도 변수로 선언해서 사용한다.

약간 사용하는 느낌이 리액트 공부할때랑 파이썬에서 상속받아온

프로퍼티? 그런거를 불러오는 느낌이다.

구조체에서 선언한 것을 구조체 변수.구조체 멤버 이런식으로

사용하기 때문이다.

근데 여기서 사용하기 편하게 typedef를 사용하고,

구조체 이름따로 별칭따로 정해서 사용하면 별칭만 입력해주면된다.

C언어 관습중에 구조체 이름 앞에는 태그(_)를 붙히는데,

최근에는 구조체 이름과 별칭을 같게 하는 경우도 많다고 한다.

#include <stdio.h>

struct Dashboard {
    int speed;
    char fuel;
    float mileage;
    int engineTemp;
    int rpm;
};

int main()
{
    struct Dashboard d1;

    d1.speed = 80;
    d1.fuel = 'F';
    d1.mileage = 5821.442871;
    d1.engineTemp = 200;
    d1.rpm = 1830;
    
    printf("Speed: %dkm/h\n", d1.speed);
    printf("Fuel: %c\n", d1.fuel);
    printf("Mileage: %fkm\n", d1.mileage);
    printf("Engine temp: %d℃\n", d1.engineTemp);
    printf("RPM: %d\n", d1.rpm);

    return 0;
}
#include <stdio.h>

typedef struct _Dashboard {
    int speed;
    char fuel;
    float mileage;
    int engineTemp;
    int rpm;
} Dashboard;

int main()
{
    Dashboard d1;

    d1.speed = 80;
    d1.fuel = 'F';
    d1.mileage = 5821.442871f;
    d1.engineTemp = 200;
    d1.rpm = 1830;

    printf("Speed: %dkm/h\n", d1.speed);
    printf("Fuel: %c\n", d1.fuel);
    printf("Mileage: %fkm\n", d1.mileage);
    printf("Engine temp: %d℃\n", d1.engineTemp);
    printf("RPM: %d\n", d1.rpm);

    return 0;
}

 

 

Unit 49. 구조체와 포인터

구조체의 멤버를 역참조 하던지,

구조체 포인터의 멤버를 역참조 하던지

앞에 * 기호를 붙혀서 역참조를 하면 된다.

멤버에 접근할 때는 화살표를 사용한다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Person {
    char name[20];
    int age;
    char address[100];
};

typedef struct {
    char name[20];
    int number;
    int displacement;
} Car;

int main()
{
    struct Person* p1 = malloc(sizeof(struct Person));

    Car* c1 = malloc(sizeof(Car));

    strcpy(p1->name, "고길동");
    p1->age = 40;
    strcpy(p1->address, "서울시 서초구 반포동");

    strcpy(c1->name, "스텔라");
    c1->number = 3421;
    c1->displacement = 2000;

    printf("이름: %s\n", p1->name);
    printf("나이: %d\n", p1->age);
    printf("주소: %s\n", p1->address);

    printf("자동차 이름: %s\n", c1->name);
    printf("자동차 번호: %d\n", c1->number);
    printf("배기량: %dcc\n", c1->displacement);

    free(p1);
    free(c1);

    return 0;
}
#include <stdio.h>

struct Point3D {
    float x;
    float y;
    float z;
};

int main()
{
    struct Point3D p1 = { 10.0f, 20.0f, 30.0f };
    struct Point3D* ptr;

    ptr = &p1;
    
    printf("%f %f %f\n", ptr->x, ptr->y, ptr->z);

    return 0;
}

 

 

Unit 50. 두 점 사이의 거리

피타고라스의 정리를 사용하는 두 점 사이의 거리에는

math.h 헤더파일에서 sqrt 함수를 사용하여 제곱근을 구한다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

struct Point2D {
    int x;
    int y;
};

int main()
{
    struct Point2D p1;
    struct Point2D p2;
    double distance;

    scanf("%d %d %d %d", &p1.x, &p1.y, &p2.x, &p2.y);

    distance = sqrt(pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2));
    
    printf("%f\n", distance);

    return 0;
}

 

 

Unit 51. 구조체 멤버 정렬

구조체에서 멤버의 오프셋을 구할 때는 

offsetof 매크로를 사용한다.

offsetof는 stddef.h 헤더 파일에 정의되어있다.

구조체 정렬 크기를 조절하기 위해서는

#pragma pack(push, 정렬크기)
#pragma pack(pop)

GCC 4.0 이상에서 해당 내용을 구조체 시작과 끝에

적어주면 된다.

#include <stdio.h>

struct EncryptionHeader {
    char flags;
    int text1;
    char text3;
    char text4;
    char text5;
};

int main()
{
    struct EncryptionHeader header;

    printf("%d\n", sizeof(header));

    return 0;
}
#include <stdio.h>

struct Packet {
    char t1;
    char t2;
    char t3;
};

int main()
{
    struct Packet pkt;

    printf("%d\n", sizeof(pkt));

    return 0;
}

 

 

Unit 52. 구조체와 메모리

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Person {
    char name[20];
    int age;
    char address[100];
};

int main()
{
    struct Person p1;

    strcpy(p1.name, "홍길동");
    p1.age = 30;
    strcpy(p1.address, "서울시 용산구 한남동");

    memset(&p1, NULL, sizeof(struct Person));

    printf("이름: %s\n", p1.name);
    printf("나이: %d\n", p1.age);
    printf("주소: %s\n", p1.address);

    return 0;
}

memset 함수 내 인자 값들만 채워주면 된다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Person {
    char name[20];
    int age;
    char address[100];
};

int main()
{
    struct Person* p1 = malloc(sizeof(struct Person));
    struct Person p2;

    strcpy(p1->name, "고길동");
    p1->age = 40;
    strcpy(p1->address, "서울시 서초구 반포동");

    memcpy(&p2, p1, sizeof(struct Person));

    printf("이름: %s\n", p2.name);
    printf("나이: %d\n", p2.age);
    printf("주소: %s\n", p2.address);

    free(p1);

    return 0;

}

p1 멤버의 인적정보를 복제하는 문제로 memcpy 인자로 넣어준다.

 

 

Unit 53. 구조체와 배열

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

struct Point2D {
    int x;
    int y;
};

int main()
{
    struct Point2D p[4];
    double length = 0.0f;

    scanf("%d %d %d %d %d %d %d %d",
        &p[0].x, &p[0].y, &p[1].x, &p[1].y, &p[2].x, &p[2].y, &p[3].x, &p[3].y
    );

    for (int i = 0; i < sizeof(p) / sizeof(struct Point2D*); i++)
    {
        if (i == 3)
            break;
        length += sqrt(pow((p[i + 1].x - p[i].x), 2) + pow((p[i + 1].y - p[i].y), 2));
    }
    
    printf("%f\n", length);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

struct Person {
    char name[30];
    int age;
};

int main()
{
    struct Person* p[5];

    for (int i = 0; i < sizeof(p) / sizeof(struct Person*); i++)
    {
        p[i] = malloc(sizeof(struct Person));
        scanf("%s %d", &p[i]->name, &p[i]->age);
    }

    int many_age = 0;

    for (int i = 0; i < sizeof(p) / sizeof(struct Person*); i++)
    {
        if (p[many_age]->age < p[i]->age)
            many_age = i;
    }

    printf("%s", p[many_age]->name);

    for (int i = 0; i < sizeof(p) / sizeof(struct Person*); i++)
    {
        free(p[i]);
    }

    return 0;
}

 

 

Unit 54. 공용체

구조체는 멤버들이 독립적인 공간을 사용하는 반면에,

공용체는 모든 멤버가 공간을 공유해서 사용한다고 보면 된다.

또한, 공용체는 가장 큰 자료형의 공간을 공유한다고 보면 된다.

이런 공용체를 사용하기 위해서는 아까 구조체의 struct 구조처럼

union을 사용하여 만들어주면 된다.

이러한 공용체도 변수를 입력해줘야 사용이 가능하다.

#include <stdio.h>

union Data
{
    int num1;
    char c1;
};

int main()
{
    union Data d1;

    d1.num1 = 0x1111;

    printf("0x%x %d\n", d1.c1, sizeof(d1));

    return 0;
}

문제에 주어진 멤버 이름을 확인해본다.

#include <stdio.h>
#include <stdlib.h>

union Data {
    short num1;
    int num2;
};

int main()
{
    union Data* d1 = malloc(sizeof(union Data));

    d1->num2 = 0x11111111;

    printf("0x%x 0x%x\n", d1->num1, d1->num2);

    free(d1);

    return 0;
}

 

 

Unit 55. 구조체와 공용체

이제 여러가지 응용된 버전들이 등장하기 시작했다.

여기 과정에서 나오는 예제에서는 벡터를 예로 들고 있는데,

구조체 이름과 함께 선언한 구조체 안에

익명 공용체를 선언하고 익명 구조체를 선언해서

x, y, z 좌표를 나타낸다.

그 다음 구조체의 변수로 각각의 좌표에 접근하게 된다.

이 때 특이한점은 한 배열에 저장해주고 각 배열에 접근하는 것이다.

이렇게하여 인덱스로 접근해주는 것이다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Stats {
    float health;
    float healthRegen;
    unsigned int mana;
    float manaRegen;
    float range;
    float attackDamage;
    float armor;
    float attackSpeed;
    float magicResist;
    unsigned int movementSpeed;
};

struct Champion {
    char name[20];
    struct Stats stats;
    float abilityPower;
};

int main()
{
    struct Champion swain;

    strcpy(swain.name, "Swain");
    swain.stats.health = 463.000000;
    
    swain.stats.healthRegen = 1.48f;
    swain.stats.mana = 290;
    swain.stats.manaRegen = 1.49f;
    swain.stats.range = 500;
    swain.stats.attackDamage = 52.0f;
    swain.stats.attackSpeed = 0.625f;
    swain.stats.armor = 20.0f;
    swain.stats.magicResist = 30;
    swain.stats.movementSpeed = 335;
    swain.abilityPower = 0;

    printf("%s %f\n", swain.name, swain.stats.health);

    return 0;
}

스웨인이면 롤의 스웨인 같은데.. 친숙해서 좋았다,,

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Stats {
    float health;
    float healthRegen;
    unsigned int mana;
    float manaRegen;
    float range;
    float attackDamage;
    float armor;
    float attackSpeed;
    float magicResist;
    unsigned int movementSpeed;
};

struct Champion {
    char name[20];
    struct Stats* stats;
    float abilityPower;
};

int main()
{
    struct Champion* swain = malloc(sizeof(struct Champion));

    swain->stats = malloc(sizeof(struct Stats));

    strcpy(swain->name, "Swain");
    swain->stats->health = 463.000000;

        swain->stats->healthRegen = 1.48f;
    swain->stats->mana = 290;
    swain->stats->manaRegen = 1.49f;
    swain->stats->range = 500;
    swain->stats->attackDamage = 52.0f;
    swain->stats->attackSpeed = 0.625f;
    swain->stats->armor = 20.0f;
    swain->stats->magicResist = 30;
    swain->stats->movementSpeed = 335;
    swain->abilityPower = 0;

    printf("%s %f\n", swain->name, swain->stats->health);

    free(swain->stats);
    free(swain);

    return 0;
}
#include <stdio.h>

struct DeviceOption
{
    union {
        short option;
        struct {
            unsigned char boot;
            unsigned char interrupt;
        };
    };
};

int main()
{
    struct DeviceOption opt;

    opt.boot = 0x22;
    opt.interrupt = 0x11;

    printf("0x%x\n", opt.option);

    return 0;
}

 

 

Unit 56. 구조체 비트 필드

비트 필드는 구조체를 선언할 때 콜론 (:)을 적어주고,

바로 뒤에 선언하고 세미콜론으로 닫으면 된다.

#include <stdio.h>

struct Flags
{
    // 15 -> 1이 4개
    // 127 -> 1이 7개
    // 7 -> 1이 3개
    unsigned int a : 4;
    unsigned int b : 7;
    unsigned int c : 3;
};

int main()
{
    struct Flags f1;

    f1.a = 0xffffffff;
    f1.b = 0xffffffff;
    f1.c = 0xffffffff;

    printf("%u %u %u\n", f1.a, f1.b, f1.c);

    return 0;
}
#include <stdio.h>

struct Flags {
    union {
        struct {
            unsigned short a : 3;
            unsigned short b : 4;
            unsigned short c : 7;
            unsigned short d : 2;
        };
        unsigned short e;
    };
};

int main()
{
    struct Flags f1 = { 0, };

    f1.a = 4;
    f1.b = 8;
    f1.c = 64;
    f1.d = 3;

    printf("%u\n", f1.e);

    return 0;
}

 

 

Unit 57. 열거형

열거형은 구조체처럼 선언해주면 되는데,

중괄호 안에 값1 = 초깃값1 처럼 선언해주면 되고,

구조체와 공용체처럼 변수도 선언하여 사용해야 한다.

이번에는 럭스 스킬에 대한 내용으로 재밌게 배울 수 있었다.

#include <stdio.h>

enum PROTOCOL_TYPE
{
    PROTOCOL_IP = 4,
    PROTOCOL_UDP,
    PROTOCOL_TCP
};

int main()
{
    enum PROTOCOL_TYPE p1, p2, p3;

    p1 = PROTOCOL_TCP;
    p2 = PROTOCOL_UDP;
    p3 = PROTOCOL_IP;

    printf("%d %d %d\n", p1, p2, p3);

    return 0;
}

출력값을 안보고 적으면 실수하게 된다. (출력값 6 5 4)

#include <stdio.h>

enum MasterYiSkill {
    AlphaStrike = 1,
    Meditation,
    WujuStyle,
    Highlander
};

int main()
{
    enum MasterYiSkill skill;

    skill = Meditation;

    switch (skill)
    {
    case AlphaStrike:
        printf("일격 필살\n");
        break;
    case Meditation:
        printf("명상\n");
        break;
    case WujuStyle:
        printf("우주류 검술\n");
        break;
    case Highlander:
        printf("최후의 전사\n");
        break;
     default:
        break;
    }
    return 0;
}

명상은 AP 마이 시절이,,,

#include <stdio.h>

// INTERFACE_TYPE은 Windows 커널의 winddk.h 헤더 파일에 정의된 열거형
typedef enum _INTERFACE_TYPE {
    InterfaceTypeUndefined = -1,
    Internal,
    Isa,
    Eisa,
    MicroChannel,
    TurboChannel,
    PCIBus,
    VMEBus,
    NuBus,
    PCMCIABus,
    CBus,
    MPIBus,
    MPSABus,
    ProcessorInternal,
    InternalPowerBus,
    PNPISABus,
    PNPBus,
    MaximumInterfaceType
} INTERFACE_TYPE, * PINTERFACE_TYPE;

int main()
{
    for (INTERFACE_TYPE i = Internal; i < MaximumInterfaceType; i++)
    {
        printf("%d ", i);
    }

    return 0;
}

이것도 문제만 보면 틀리는 것이,

출력 값이 0부터 임을 확인해야 한다.

 

 

Unit 58. 자료형

자료형 변환 후 포인터로 값을 출력하기 위해서는

자료형 변환에 포인터에 대한 값을 역참조 해주어야 한다.

그렇지 않으면 간접 참조가 잘못되었다는 컴파일 에러가 발생하게 된다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    float num1;
    int num2;

    scanf("%f", &num1);

    num2 = (int)num1;
    printf("%d\n", num2);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    unsigned long long* numPtr1 = malloc(sizeof(unsigned long long));
    unsigned int* numPtr2;

    scanf("%llx", numPtr1);

    numPtr2 = (unsigned int*)numPtr1;
    printf("0x%x\n", *numPtr2);

    free(numPtr1);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    long double* numPtr1 = malloc(sizeof(long double));
    void* ptr;

    scanf("%Lf", numPtr1);

    ptr = numPtr1;

    printf("%Lf\n", *(long double*)ptr);

    free(numPtr1);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Stats {
    float health;
    float healthRegen;
    unsigned int mana;
    float manaRegen;
    float range;
    float attackDamage;
    float armor;
    float attackSpeed;
    float magicResist;
    unsigned int movementSpeed;
};

int main()
{
    void* ptr = malloc(sizeof(struct Stats));
    struct Stats st;

    scanf("%u %u", &st.mana, &st.movementSpeed);

    memcpy(ptr, &st, sizeof(struct Stats));
    st.mana = 0;
    st.movementSpeed = 0;

    printf("%d\n", ((struct Stats*)ptr)->mana);
    printf("%d", ((struct Stats*)ptr)->movementSpeed);
    
    free(ptr);

    return 0;
}

 

 

Unit 59. 포인터 연산

해당 과정에서 메모리 주소가 커지는 것을 순방향 이동 (forward)로,

메모리 주소가 작아지는 것을 역방향 이동(backward)이라 설명한다.

또한, 구조체를 사용하면 구조체 멤버에 따른 바이트 수만큼

forward 하거나 backward 하게 된다.

이 때 화살표를 통해 포인터 연산에 접근이 가능하다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    short* numPtrA;
    short* numPtrB;
    short* numPtrC;

    scanf("%p", &numPtrA);

    numPtrB = numPtrA + 3;
    numPtrC = numPtrA + 5;
    
    printf("%X\n", numPtrB);
    printf("%X\n", numPtrC);

    return 0;
}

0에서 6까지 3, 6에서 A(10)까지 5를 더해준다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int numArr1[3] = { 0, };
    long long numArr2[3] = { 0, };
    int* numPtr = malloc(sizeof(int) * 3);
    void* ptr = malloc(sizeof(long long) * 3);
    int num1;
    long long num2;

    scanf("%d %d %d %lld %lld %lld",
        &numArr1[0], &numArr1[1], &numArr1[2],
        &numArr2[0], &numArr2[1], &numArr2[2]
    );

    memcpy(numPtr, numArr1, sizeof(int) * 3);
    memcpy(ptr, numArr2, sizeof(long long) * 3);
    numArr1[0] = numArr1[1] = numArr1[2] = 0;
    numArr2[0] = numArr2[1] = numArr2[2] = 0;

    num1 = *(numPtr + 2);
    num2 = *((long long*)ptr + 1);
    
    printf("%d %lld\n", num1, num2);

    free(ptr);
    free(numPtr);

    return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Point3D {
    float x;
    float y;
    float z;
};

int main()
{
    void* ptr = malloc(sizeof(struct Point3D) * 3);
    struct Point3D p[3];
    float result1, result2;

    scanf("%f %f %f %f %f %f %f %f %f",
        &p[0].x, &p[0].y, &p[0].z,
        &p[1].x, &p[1].y, &p[1].z,
        &p[2].x, &p[2].y, &p[2].z
    );

    memcpy(ptr, p, sizeof(struct Point3D) * 3);
    memset(p, 0, sizeof(struct Point3D) * 3);

    result1 = ((struct Point3D*)ptr + 1)->x;
    result2 = ((struct Point3D*)ptr + 2)->z;
    
    printf("%.1f %.1f\n", result1, result2);

    free(ptr);

    return 0;
}

 

 

Unit 60. 함수 사용

함수를 만드는 방법은 반환값자료형 함수이름 () {} 형태로

작성하게 돼서 처음 작성할 때 void로 시작하는 것을 알려준다.

이 때, main() 함수에서 실행되는 void로 선언된 함수로 다시

돌아가게 돼서 실행 이후 다시 main으로 돌아오게 되는데,

이 과정이 리버싱할 때 특정 메모리 주소로 CALL을 해서 가게 되거나

하는 등의 과정과 비슷하다는 생각이 들었다.

#include <stdio.h>

void printIPAddress() 
{
    char ip_address[20] = "192.168.10.5";
    printf("%s\n", ip_address);
}

void printHostname() 
{
    char hostname[20] = "Jupiter";
    printf("%s", hostname);
}

int main()
{
    printIPAddress();
    printHostname();

    return 0;
}

조건문 쓸때도 굉장히 많이 쓰는게 함수인데,

함수를 사용하면 집약적으로 표현이 가능하고

가독성이 좋아지는 것으로 알고 있다.

#include <stdio.h>

void printName(), printOrdinal();

int main()
{
    printName();
    printOrdinal();

    return 0;
}

void printName()
{
    printf("Beethoven\n");
}

void printOrdinal()
{
    printf("9th Symphony\n");
}

 

 

화이팅 ..!!