혼자 공부하는 C언어 (3)

Erdos·2024년 10월 5일
0

감상

목록 보기
40/42
post-thumbnail

chapter10 배열과 포인터


10-1 배열과 포인터의 관계

배열명으로 배열 요소 사용하기

  • 주소는 정수처럼 보이지만 자료형에 대한 정보를 갖고 있는 특별한 값

주소 + 주소 = 주소 + (정수 * 주소를 구한 변수의 크기)

  • 배열 요소를 사용할 때는 상황에 따라 대괄호나 포인터 연산식 중 적당한 것을 골라 쓰면 된다.
  • 특별한 경우 대괄호가 편함
  • &ary[2] 와 같은 경우 ary + 2 로 쓰면 연산 과정을 줄일 수 있음

배열명 역할을 하는 포인터

배열명과 포인터의 차이

  1. sizeof 연산의 결과가 다르다.
    배열명에 사용하면 배열 전체의 크기를 구하고, 포인터에 사용하면 포인터 하나의 크기를 구한다. 고로, 배열명을 포인터에 저장함녀 배열 전체의 크기를 확인할 수 없게 된다.

  2. 변수와 상수의 차이가 있습니다.
    포인터는 그 값을 바꿀 수 있지만, 배열명은 상수이므로 값을 바꿀 수 없다.

포인터 pa로 첫번쨰 배열 요소를 출력하는 3가지 방법

  1. pa를 배열명처럼 사용
printf("%d", pa[0]);
  1. pa[0]을 그대로 포인터 연산식으로
printf("%d", *(pa + 0));
  1. *(pa+0)에서 의미없는 0과 괄호 제거
printf("%d", *pa);

포인터로 배열의 데이터를 처리할 때 주의할 점

  1. 포인터의 값이 변할 수 있으므로 유효한 값인지 확인하는 습관이 필요
  2. 포인터에 증가 연산자와 간접 참조 연산자를 함께 사용할 때, 전위 표현을 사용하면 안 된다.

포인터의 뺄셈과 관계 연산

#include <stdio.h>

int main(void)
{
    int ary[5] = {10,20,30,40,50};
    int *pa = ary;
    int *pb = pa + 3;
    
    printf("pa : %p\n", pa);
    printf("pb : %p\n", pb);
    pa++;
    printf("pb - pa: %ld\n", pb - pa);
    
    printf("앞에 있는 배열 요소의 값 출력: ");
    if (pa < pb) 
        printf("%d\n", *pa);
    else
        printf("%d\n", *pb);
    
    return (0);
}

chapter11 문자


11-1 아스키 코드 값과 문자 입출력 함수

아스키코드

  • 특징
    • 알파벳과 숫자는 각각 연속된 아스키 코드 값을 갖느다.
    • 소문자가 대문자보다 아스키 코드 값이 크다(-32).
    • 제어 문자는 백슬래시와 함께 표시하며 출력할 때 그 기능을 수행한다.

getchar, putchar 함수

  1. getchar함수 구현
#include <unistd.h>

int my_getchar(void) 
{
    char c;
    int bytesRead;

    bytesRead = read(0, &c, 1); 

    if (bytesRead == 0) 
    {
        return -1;  // Return -1 as EOF
    }
    return (unsigned char)c;  
}
  • getchar 함수의 반환형이 int형인 이유
    • 입력의 끝 조건을 수용하기 위해 (getchar가 입력의 끝에 도달하면 EOF를 반환하는데, 이 값은 일반적으로 -1로 정의되어 있다. char 타입은 0~255까지의 값만 표현할 수 있으므로, int 타입을 사용한다.
    • 유효한 문자 입력과 EOF 조건 간의 혼동을 방지할 수 있다.

EOF(End Of File)

  • 일반적으로 -1로 정의
  • 파일의 끝을 표현하기 위해 정의해놓은 상수
  1. putchar 구현
void ft_putchar(char c)
{
	wrtie(1, &c, 1);
}

11-2 버퍼를 사용하는 입력 함수

  • scanf나 getchar 함수와 같은 표준 입력 함수는 키보드로부터 입력된 데이터를 버퍼를 거쳐 처리한다.
  • 입출력 함수가 버퍼를 사용하면 좋은 점
    • 데이터를 안정적으로 입력받을 수 있다
    • 입력 장치와 독립적으로 사용할 수 있다.

chapter12 문자열


12-2 문자열 연산 함수

문자열을 대입하는 strcpy 함수

  • 구현하기
char *ft_strcpy(char *dest, char *src) 
// dest: 복사 받을 곳
// src : 복사할 내용
{
	char *origin;

	origin = dest;
	while (*src != '\0')
	{
		*dest = *src;
		src++;
		dest++;
	}
	*dest = '\0';
	return (origin);
}

원하는 개수의 문자만을 복사하는 strncpy 함수

  • 구현하기
char *ft_strncpy(char *dest, char *src, unsigned int n)
{
	char *origin;
	
	origin = dest;
	while (0 < n && *src != '\0')
	{
		*dest = *src;
		src++;
		dest++;
		n--;
	}
	while (0 < n)
	{
		*dest = '\0';
		dest++;
		n--;
	}
	return origin;
}

문자열을 붙이는 strcat, strncat

  • 주의사항
    • strcat 함수는 메모리를 침범할 수 있다. 붙여 넣기되는 배열의 크기가 충분히 커야 함
    • strcat 함수를 사용할 때는 배열을 초기화해야 한다. 초기화 되지 않으면 쓰레기 값의 중간부터 붙여 넣을 가능성이 크다.
  • strcat 구현
char *ft_strcat(char *dest, char *src)
{
    char *temp;
    
    temp = dest;
    while(*temp != '\0')
    {
        temp++; // 포인터 끝으로 이동 '\0'위치 도달
    }
    while(*src != '\0')
    {
        *temp = *src;
        temp++;
        src++;
    }
    *temp = '\0';
    return (dest);
}
  • strncat 구현
char	*ft_strncat(char *dest, char *src, unsigned int nb)
{
	unsigned int i;
	char *temp;
	
	temp = dest;
	i = 0;
	while (*temp)
	    temp++;
	while (i < nb && *src != '\0')
	{
	    *temp = *src;
	    temp++;
	    src++;
	    i++;
	}
	*temp = '\0';
	return (dest);
}

문자열 길이를 계산하는 strlen 함수

size_t ft_strlen(const char *str)
{
    size_t len = 0;
    while (str[len])
        len++;
    return len;
}
  • sizeof 연산자와의 차이
    • sizeof 연산자는 배열에 저장된 문자열 길이와 상관없이 배열 전체 크기를 계산함
    • 헷갈리지 말기!

문자열을 비교하는 strcmp, strncmp

  • 참고: 아스키코드 값으로 비교하기 때문에, 반드시 대소문자를 일치시켜야 함!
int ft_strcmp(const char *s1, const char *s2)
{

	while(*s1 != '\0' && *s2 != '\0')
	{
		if (*s1 != *s2)
			return *s1 - *s2;
		else
		{
		    s1++;
		    s2++;
		}
	}
	return (*s1 - *s2); 
}
int ft_strncmp(const char *s1, const char *s2, unsigned int n) 
{
    unsigned int i;

		i = 0;
    if (n == 0)
        return 0;
    i = 0;
    while ((i < n) && (*s1 != '\0' || *s2 != '\0'))
    {
        if (*s1 != *s2)
            return (*s1 - *s2);
        s1++;
        s2++;
        i++;
    }
    return 0;
}
profile
수학을 사랑하는 애독자📚 Stop dreaming. Start living. - 'The Secret Life of Walter Mitty'

0개의 댓글