Post

c 공부 2024.04.09

문자열 연산 함수

  • 오류발생 코드:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{   
    // 부호있는 int 부호없으면 unsigned
    int a = 10;
    int b = 20;
    
    char c[10] = "apple";
    char d[10] = "pie";
    
    printf("%d\n", a + b);
    printf("%s\n", c + d);
    
    return 0;
}

문자열은 더하기 연산자로 문자열을 더할 수 없음

문자열 연산에 사용하는 함수를 따로 사용해야함

올바른 방법은 두 개의 문자열을 연결하여 하나의 문자열로 만든 다음 이를 출력하는 것.

  • 수정된 코드:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    cCopy code
    #include <stdio.h>
    #include <string.h> 
    // 문자열 연결을 위해 추가 한 h
    int main()
    {
      int a = 10;
      int b = 20;
    
      char c[10] = "apple";
      char d[10] = "pie";
    
      printf("%d\n", a + b);
      printf("%s%s\n", c, d);  // 두 개의 문자열을 연결하여 출력합니다.
    
      return 0;
    }
    

    d변수 최소 배열 크기 = 4
    char d[4] = “pie”; « 방을 4개 를 주는이유 널값이 들어감

    strcpy vs strncpy

링크 : 차이점 strcpy vs strncpy

2024-04-09-100219

  • strcpy는 뒤에 값을 앞에 복사해줌 …
    strcpy (1, 2);

  • strcpy는 그냥 복사고 strncpy는 얼만큼 복사를 하는건지

strcat vs strncat

2024-04-09-101134

  • strncpy도 마찬가지로 얼만큼 이어붙일지 정할 수 있음

strlen vs sizeof

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>   // 표준 입력과 출력 함수들을 사용하기 위한 헤더 파일을 포함합니다.
#include <string.h>  // 문자열 관련 함수들을 사용하기 위한 헤더 파일을 포함합니다.

int main()  // main 함수의 정의
{
    char str1[80], str2[80];  // 최대 79개의 문자로 이루어진 두 개의 문자열을 저장할 배열을 선언합니다.
    char *resp;  // 문자열을 가리킬 포인터를 선언합니다.
    
    printf("2개의 과일 이름 입력: ");  // 사용자에게 메시지를 출력하여 과일 이름을 입력하라고 요청합니다.
    scanf("%s%s", str1, str2);  // 사용자로부터 과일 이름을 입력받습니다. 여러 개의 입력이 가능하며, 공백을 기준으로 문자열을 분리합니다.

    // 두 개의 입력된 과일 이름 중에서 더 긴 과일의 이름을 선택하여 포인터 resp에 할당합니다.
    if (strlen(str1) > strlen(str2))  // 첫 번째 과일의 이름이 두 번째 과일의 이름보다 더 긴 경우
        resp = str1;  // 첫 번째 과일의 이름을 resp에 할당합니다.
    else  // 그렇지 않은 경우, 즉 두 번째 과일의 이름이 더 긴 경우
        resp = str2;  // 두 번째 과일의 이름을 resp에 할당합니다.

    printf("이름이 긴 과일은 : %s\n", resp);  // 더 긴 과일의 이름을 출력합니다.
    
    return 0;  // 프로그램의 종료를 나타내는 정수 값을 반환하고 main 함수를 종료합니다.
}

sizeof는 NULL문자를 포함한 메모리의 할당크기를 바이트단위로 구합니다.
연산자입니다.
strlen는 순수하게 문자열의 길이만을 구합니다.
함수입니다.양주종의 코딩스쿨

strcmp vs strncmp

2024-04-09-103241

사전에 나중에 나오면 str1 이 1이 되고 str1이 먼저 나오면 -1이되므로 크기비교로 뭐가 먼저 나온지 알 수 있음

  • 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>   // 표준 입력과 출력 함수들을 사용하기 위한 헤더 파일을 포함합니다.
#include <string.h>  // 문자열 관련 함수들을 사용하기 위한 헤더 파일을 포함합니다.

int main()  // main 함수의 정의
{
    char str1[80] = "pear";   // 사전 순서에 나중에 나오는 과일의 이름을 저장하는 문자열 배열을 선언하고 초기화합니다.
    char str2[80] = "peach";  // 사전 순서에 먼저 나오는 과일의 이름을 저장하는 문자열 배열을 선언하고 초기화합니다.
    
    printf("사전에 나중에 나오는 과일 이름 : ");  // 사용자에게 메시지를 출력하여 사전 순서에 나중에 나오는 과일의 이름을 출력할 것임을 알립니다.

    // strcmp 함수를 사용하여 두 과일의 이름을 비교하고, 사전 순서에 따라 나중에 나오는 과일의 이름을 출력합니다.
    if (strcmp(str1, str2) > 0)  // str1이 str2보다 사전 순서상으로 뒤에 나오는 경우
        printf("%s\n", str1);    // str1의 값을 출력합니다.
    else  // 그렇지 않은 경우, 즉 str2가 str1보다 사전 순서상으로 뒤에 나오는 경우
        printf("%s\n", str2);    // str2의 값을 출력합니다.
    
    return 0;  // 프로그램의 종료를 나타내는 정수 값을 반환하고 main 함수를 종료합니다.
}

변수

변수명의 사용범위와 저장공간이 할당되는 방식에 따라 변수를 나누고 그 특징을 살펴보기

지역변수

void는 입력도 없고 출력도 없다는 뜻
2024-04-09-111217

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h> // 표준 입출력 헤더 파일을 포함한다. 이 파일은 printf 같은 함수를 사용하기 위해 필요하다.

void assign(void); // 'assign'이라는 이름의 함수를 선언한다. 이 함수는 아무 인자도 받지 않고, 반환값도 없다.

int main(void) // 'main' 함수를 시작한다. C 프로그램의 실행 진입점이다.
{
    auto int a = 0; // 'main' 함수의 지역 변수 'a'를 선언하고 0으로 초기화한다. 'auto' 키워드는 지역 변수가 자동으로 'auto' 저장 클래스를 가지므로 생략 가능하다.

    assign(); // 'assign' 함수를 호출한다.

    printf("main 함수 a : %d\n", a); // 'main' 함수의 'a' 변수 값을 출력한다. 여기서 'a'는 'assign' 함수에서 변경된 값이 아니라 'main' 함수에서 초기화한 0이 출력된다.

    return 0; // 'main' 함수의 실행을 종료하고 0을 반환한다. 이는 프로그램이 성공적으로 실행되었음을 나타낸다.
}

void assign(void) // 'assign' 함수를 정의한다.
{
    int a; // 'assign' 함수의 지역 변수 'a'를 선언한다. 이 변수는 'main' 함수의 'a' 변수와는 별개의 변수다.

    a = 10; // 'assign' 함수의 지역 변수 'a'에 10을 할당한다.

    printf("assign 함수 a : %d\n", a); // 'assign' 함수의 'a' 변수 값을 출력한다. 여기서 'a'는 이 함수 내에서 10으로 변경되었다.
}

assingn에서 10이 출력되는데 main a는 0을 출력함

2024-04-09-111319

만약 a에 같은 값을 넣으려면 ?

assign 함수에서 a가 10으로 설정되었을 때 main 함수에서도 a가 10이 되려면, a 변수를 assign 함수로 전달하여 그 값을 변경해야 한다. 그러나 C에서는 변수를 값으로 전달하면 원본 변수의 값이 변경되지 않기 때문에, 변수의 주소를 전달하여 참조를 통해 변수를 직접 변경해야 함. 이를 위해서는 포인터를 사용해야 한다.

  • 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

void assign(int *ptr); // 포인터를 매개변수로 받는 함수 선언

int main(void)
{
    int a = 0; // 'main' 함수의 지역 변수 'a'를 선언하고 0으로 초기화한다.

    assign(&a); // 'a'의 주소를 'assign' 함수에 전달한다.

    printf("main 함수 a : %d\n", a); // 'main' 함수의 'a' 변수 값을 출력한다. 이제 'a'는 10이 출력된다.

    return 0;
}

void assign(int *ptr) // 포인터를 매개변수로 받는 'assign' 함수 정의
{
    *ptr = 10; // 'ptr'이 가리키는 주소에 10을 할당한다.
}

assign 함수는 이제 포인터 ptr을 매개변수로 받아, 그 포인터가 가리키는 값에 10을 할당.
main 함수에서 assign(&a);를 호출하면,a의 주소를 assign에 전달하게 되고,따라서 assign 함수 내에서 a의 값을변경할 수 있게 됨.

블록안의 지역변수를 사용해서 두 변수 교환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>  // 표준 입력과 출력 함수들을 사용하기 위한 헤더 파일을 포함합니다.#include <string.h> // 문자열 관련 함수들을 사용하기 위한 헤더 파일을 포함합니다.int main(void) // main 함수의 정의
{
   int a = 10, b = 20; // 변수 a와 b를 정의하고 각각 값을 초기화합니다.

   printf("교환 전 a와 b의 값 : %d, %d\n", a, b); // 교환 전의 a와 b의 값을 출력합니다.
   {
       int temp; // 임시 변수 temp를 정의합니다.

       temp = a; // temp에 a의 값을 저장합니다.
       a = b;    // a에 b의 값을 저장합니다.
       b = temp; // b에 temp의 값을 저장합니다.
   }
   printf("교환 후 a와 b의 값 : %d, %d\n", a, b); // 교환 후의 a와 b의 값을 출력합니다.
   return 0; // 프로그램의 종료를 나타내는 정수 값을 반환하고 main 함수를 종료합니다.
}

이중괄호 {}를 사용하여 교환하는 부분을 블록으로 묶었고, 이 블록은 변수 temp를 사용하여 ab의 값을 교환하는 역할을 함. 변수 temp를 사용하여 두 변수의 값을 임시로 저장하고, 그 후에 변수들 간의 값을 서로 교환하는 방식으로 동작. 이러한 방식을 이용하면 두 변수의 값을 교환가능.

  • {} 의 의미

C 언어에서 {} 기호는 코드 블록을 정의하는 데 사용. 코드 블록은 여러 문장을 하나의 그룹으로 묶어서 그 문장들이 함께 실행되어야 함을 나타낸다. 함수의 본문, 제어 구조(if, for, while 등)의 본문, 그리고 변수의 유효 범위(scope)를 제한하는 데에도 사용.

예시:

1
2
3
if (condition) {
    // 조건이 참일 경우에 실행될 코드 블록
}

위 예에서 {}는 if 조건이 true일 때 실행할 문장들을 묶음.

또한 변수의 유효 범위를 제한하는 데 사용.

예시:

1
2
3
4
5
{
    int temp; // 이 블록 안에서만 유효한 지역 변수 'temp'
    // ...
}
// 여기서 'temp' 변수에 접근할 수 없음
  • 정적지역변수

사용하는이유 :

static 키워드를 사용하는 경우와 전역 변수를 선언하는 경우에는 각각 다른 이유로 사용. 두 가지 방식의 차이점:

  1. 범위와 생존 기간:
    • 전역 변수: 전역 변수는 프로그램의 시작부터 끝까지 메모리에 상주하며, 프로그램 어디서든 접근할 수 있다. 이는 전역 변수의 범위가 프로그램 전체로 확장되고, 생존 기간이 프로그램 실행 동안 지속되는 것을 의미.
    • static 변수: static 변수는 특정 함수나 블록 내에서 선언되었을 때 해당 함수나 블록의 실행 동안만 메모리에 상주하며, 해당 함수 또는 블록 내에서만 접근할 수 있다. 이는 static 변수의 범위가 선언된 함수나 블록 내로 제한되고, 해당 함수 또는 블록의 실행이 완료될 때까지만 생존한다는 것을 의미.
  2. 데이터 은닉과 모듈성:
    • 전역 변수: 전역 변수는 프로그램의 어느 곳에서나 접근할 수 있으므로 다른 모듈이나 파일에서 전역 변수를 변경할 수 있다. 이는 데이터 은닉을 어렵게 만들고, 모듈 간의 의존성을 높일 수 있다.
    • static 변수: static 변수는 해당 함수나 블록 내에서만 접근할 수 있으므로 다른 모듈이나 파일에서 직접 접근할 수 없다. 이는 데이터 은닉을 촉진하고, 모듈 간의 의존성을 줄일 수 있다.

따라서 static 키워드를 사용하는 것과 전역 변수를 선언하는 것은 서로 다른 목적과 상황에서 사용. 전역 변수는 프로그램의 다양한 부분에서 사용되어야 하고, 해당 변수의 값을 공유해야 할 때 사용. 반면에 static 변수는 특정 함수나 블록 내에서만 사용되어야 하고, 해당 변수의 범위를 제한하고 데이터 은닉을 보장해야 할 때 사용.

2024-04-09-112322

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
#include <stdio.h>  // 표준 입력과 출력 함수들을 사용하기 위한 헤더 파일을 포함합니다.

void auto_func(void);   // auto_func 함수의 프로토타입 선언
void static_func(void); // static_func 함수의 프로토타입 선언

int main(void) // main 함수의 정의
{
   int i; // 반복문에서 사용할 변수 i를 선언합니다.

   printf("일반 지역 변수(auto)를 사용한 함수...\n"); // 메시지를 출력합니다.
   for (i = 0; i < 3; i++) // 반복문을 사용하여 auto_func 함수를 세 번 호출합니다.
   {
       auto_func(); // auto_func 함수를 호출합니다.
   }
   
   printf("정적 지역 변수(static)를 사용한 함수...\n"); // 메시지를 출력합니다.
   for (i = 0; i < 3; i++) // 반복문을 사용하여 static_func 함수를 세 번 호출합니다.
   {
       static_func(); // static_func 함수를 호출합니다.
   }
   
   return 0; // 프로그램의 종료를 나타내는 정수 값을 반환하고 main 함수를 종료합니다.
}

void auto_func(void) { // auto_func 함수의 정의
    auto int a = 0; // auto 지정자를 사용하여 일반 지역 변수 a를 선언하고 초기화합니다.
    a++; // 변수 a를 증가시킵니다.
    printf("%d\n", a); // 변수 a의 값을 출력합니다.
}

void static_func(void) { // static_func 함수의 정의
    static int a; // static 지정자를 사용하여 정적 지역 변수 a를 선언합니다.
    
    a++; // 변수 a를 증가시킵니다.
    printf("%d\n", a); // 변수 a의 값을 출력합니다.
}

레지스터 변수

cpu안에서 빨리 처리 하겠다는거… 주로 많이 쓰지는 않지만..

2024-04-09-1131062024-04-09-113127

핵심

2024-04-09-113304

실험

  • 오류코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;

    char c[10] = "apple";
    char d[10] = "pie";
    char n = c + d;
    printf("%d\n", a + b);
    printf("%s %s\n", c, n);  // 두 개의 문자열을 연결하여 출력합니다.

    return 0;
}

주어진 코드에서 문제는 다음 줄에서 발생

1
char n = c + d;

여기서 nchar 타입으로 선언하고, 두 개의 문자열 cd의 시작 주소를 더하려고 하고 있음.
이는 잘못된 방법.

문자열을 연결하려면 별도의 연결 작업이 필요하며, 두 문자열의 시작 주소를 더하는 것으로는 올바른 문자열 연결이 이루어지지 않는다. 또한, char 타입의 변수는 단일 문자를 저장하는 데 사용되므로, 두 개의 문자열을 저장하는 데에는 적합하지 않다.

올바른 방법은 두 문자열을 연결하여 새로운 문자열을 생성하고 이를 출력하는 것. 따라서 코드를 수정하여 두 문자열을 연결하고 그 결과를 출력해야 한다.

  • 수정된코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h> // 문자열 연결을 위해 추가
int main()
{
    int a = 10;
    int b = 20;

    char c[10] = "apple";
    char d[10] = "pie";
    char n[20]; // 두 문자열을 저장할 충분한 크기의 배열 선언

    // 문자열 c와 d를 연결하여 n에 저장
    strcpy(n, c);
    strcat(n, " "); // 공백 추가
    strcat(n, d);

    printf("%d\n", a + b);
    printf("%s\n", n);  // 두 개의 문자열을 연결하여 출력합니다.

    return 0;
}

GIT

https://sfida.tistory.com/46 깃다운

깃허브에 git init 등등.. git clone 등등.. git push 등등..

무튼 협업 가능

협업

https://velog.io/@shin6403/Git-git-커밋-컨벤션-설정하기

깃 커밋에 항상 일정하게 무엇을 바꿧는지 추가

  1. Commit Type

타입은 태그와 제목으로 구성되고, 태그는 영어로 쓰되 첫 문자는 대문자로 한다.

태그 : 제목의 형태이며, :뒤에만 space가 있음에 유의한다.

  • feat : 새로운 기능 추가
  • fix : 버그 수정
  • docs : 문서 수정
  • style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
  • refactor : 코드 리펙토링
  • test : 테스트 코드, 리펙토링 테스트 코드 추가
  • chore : 빌드 업무 수정, 패키지 매니저 수정
This post is licensed under CC BY 4.0 by the author.