C 이론(20)

Hi Beck·2023년 6월 15일

TIL-Language(C & C++)

목록 보기
25/34

문자와문자열

A. 문자와 문자열(1)
문자 - character
문자열 - 문자의 배열 stirng

1.문자표현방법
컴퓨터에서는 각각의 문자에 숫자코드를 붙여서 표시한다.
아스키코드(ASCII code): 표준적인 8비트 문자코드
0에서 127까지의 숫자를 이용하여 문자표현

한 글자에 8비트를 쓰는 문자며, 알파벳 케렉터가 여기에 해당한다.
127인 이유는 2의 8승 -1이 127이여서

유니코드(unicode) : 표준적인 16비트 문자코드
전세계의 모든 문자를 일관되게 표현하고 다룰 수 있도록 설계

한 글자에 16비트를 쓰는 문자며 자음 모음 받침이 있는 한국어처럼 복잡한 언어를 표현할 때는 유니코드가 쓰인다.

수많은 언어를 위처럼 대응을 못하니깐 표현을 하는데 한계가 있어 16비트가 되었다.

2.아스키코드 출력문

#include <stdio.h>
int main(void)
{
unsigned char code;

for(code = 32; code < 128; code++)
{
printf("아스키 코드 %d은 %c입니다.\n", code, code);
}
return 0;
}

아스키 코드 32은 입니다.(SP라는 기호로 나옴)
아스키 코드 33은 !입니다.
...
아스키 코드 65은 A입니다.
아스키 코드 66은 B입니다.
...
아스키 코드 97은 a입니다.
아스키 코드 98은 b입니다.
...
아스키 코드 126은 ~입니다.
아스키 코드 127은 입니다.(DEL)

일대일 대응되는 문자를 각 형식지정자로 다르게 출력하면 위와 같이 나온다는 코드다.

3.문자열 표현 방법

  • printf를 받을땐 문자열로 받는다 그래서 큰따옴표를 사용하는 것

  • 문자열을 받는 형식지정자는 %S다.

    문자열 예
    "A"
    "HELLO WORLD!"
    "변수 SCORE의 값은 %d 입니다."

    근데 컴퓨터는 이 문자열을 볼 때 문자가 언제끝나는지 알 수가 없다.
    문자열의 끝을 나타내는 NULL문자가 나와야 끝으로 인식한다.
    안그러면 뒤에 있는 글자를 계속 읽어버린다.
    (C++에선 NULL을 자동으로 셋팅해주는데 C언어는 사용자가 해줘야됨)

4.문자 배열의 초기화

  1. 문자 배열 원소들을 중괄호 안에 넣어주는 방법
    char str[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };

    -> NULL을 의미하는 \0를 넣어줘야한다. 안써주면 오류뜰때까지 이상한 값을 계속 샘

  2. 문자열 상수를 사용하여 초기화하는 방법
    char str[6] = "Hello";

    -> ""를 이용해서 변하지않는 상수화 시키면 NULL 문자까지 끼워서 자동으로 인덱스를 넣어준다.

  3. 만약 배열을 크기를 지정하지 않으면 컴파일러가 자동으로 배열의 크기를 초기화값에 맞추어 설정
    char str[] = "CBible"; // 배열의 크기는 7이 된다.

    -> 글자수 + 1을 해서 배열의 크기를 정해준다.(C언어는 공백도 글자로 본다.)

5.strcpy() (=String copy,문자열을 복사한다.)

strcpy()를 사용하여 문자열을 문자 배열에 복사한다.

strcpy(str,"World");
-> 왼쪽(str)에다가 오른쪽("World")을 복사한다.여기서 str은 배열인데 크기를 정해준다음에(char str[] 이렇게) 복사를 해주면 아래와 같이 된다.

str[0] = 'W';
str[1] = 'o';
str[2] = 'r';
str[3] = 'l';
str[4] = 'd';
str[5] = '\0';

  • c++에선 str이 문법적으로 편히 쓸 수 있게 지원해줌

6.C언어에서 문자열 길이 계산하는법

#include <stdio.h>
int main(void)
{
char str[30] = "C language is easy";
int i = 0;
while(str[i] != 0)
i++;
printf("문자열\"%s\"의 길이는 %d입니다.\n", str, i);
return 0;
}

결과 : 문자열 "C language is easy"의 길이는 18입니다.

문자열길이라는건 "실제 의미있는 값이 들어간 문자열의 길이"를 뜻한다.
예시처럼 배열의크기는 30이지만 실제 문자열길이는 다르다.
( 배열의크기와 문자열길이는 다른것!)

코드를 보면 0이 아닐때까지 ++하면서 배열 원소에 접근해서 출력하는것인데 여기서 0은
아스키코드로 NULL을 의미한다.결국은 NULL이 나올때까지 반복해서 문자열 출력하라는것이다.근데 ""은 자동으로 넣어주니깐 코드를 동작시키면 문자열길이가 제대로 출력되는것

  • 스페이스바 즉 공란도 문자열길이에 인식된다.

B. 문자와 문자열(2)

1.scanf(), printf() 문자열 입출력

  • 이전에는 변수에 담아서 문자를 입력했다고하면 문자열도 담을 수 있다.

ㄱ. scanf()의 사용법
char str[10];
scanf("%s", str)

배열을 선언 및 초기화 해서 문자열을 표현하고 scanf에 주소값과 같은 배열의 이름을 넣어주면 문자열을 입력할 수 있다.

ㄴ. scanf()는 한 번에 두개 이상의 문자열도 받아들일 수 있다.

char s1[10];
char s2[10];
char s3[10];
scanf("%s%s%s", s1,s2,s3);

// 사용자가 one two three와 같이 입력하면 s1에는 one이, s2에는 two가, s3에는 three가 할당된다.

문자열에선 띄어쓰기도 공백으로 인식되는 일부라고 했는데 scanf에서는 문자열의 띄어쓰기가 적용돼서 출력되는 이유가 입력한 문자열들을 구분할 방법이 없어서 ,를 써주면 구분의 목적으로 띄어쓰기가 적용돼서 문자열들이 출력된다.

ㄷ. printf는 쓰던대로 printf("%s", str) 이렇게 쓰면 된다.

2.문자 처리 라이브러리 함수(암기x)
isalpha(c) -> c가 영문자인가?(a-z, A-Z)
isupper(c) -> c가 대문자인가?(A-Z)
islower(c) -> c가 소문자인가?(a-z)

3.문자열 처리 라이브러리 함수(c++에서 많이 쓰임)

strlen(s) -> 문자열s의 길이를 구한다.
strcpy(s1, s2) -> s2를 s1에 복사한다.
strcat(s1, s2) -> s2를 s1의 끝에 붙여넣는다.(=문자 붙힐때 사용)
strcmp(s1, s2) -> s1과 s2를 비교한다.
(같거나 다르거나, 같으면 0반환 다르면 0이 아닌 수를 반환)

-----------문자열 일부를 다룰때 --------------------
strncpy(s1, s2, n) -> s2의 최대n개의 문자를 s1에 복사한다.
장점: 코드가 작동될 때 성공 실패를 반환해줌.만약 배열은 [10]인데 복사하는 글자가 11이면 오류나는걸 얘가 한번 방어해줌
strncat(s1, s2, n) -> s2의 최대n개의 문자를 s1의 끝에 붙여넣는다.
strncmp(s1, s2, n) -> 최대n개의 문자까지 s1과 s2를 비교한다.
strchr(s, c) -> 문자열 s안에서 문자c를 찾는다.
strstr(s1, s2) -> 문자열 s1에서 문자열 s2를 찾는다.

4.문자열 연결

NULL 문자는 구분을 위해 넣어준 문자지 공간을 차지하는 문자가 아니기때문에 문자열끼리 붙혔을때는 각 문자열 끝에 있던 NULL 문자가 그냥 합쳐진 후에 끝에 하나로 오고 끝

5.문자열 비교
문자열이 크고 작은 기준은 '알파벳순서'를 의미한다.(정렬할 때 사용함)
작을수록 앞에 있는 알파벳 클수록 뒤에 있는 알파벳

int strcmp( const char s1, const char s2 );

반환값 s1과 s2의 관계

<0 -------> s1이 s2보다 작다. >0 -------> s1이 s2보다 크다.

0 s1이 s2와 같다.

예시

result = strcmp(s1, s2);
if( result < 0 )
printf("%s가 %s보다 앞에 있읍니다.\n", s1, s2);
else if( result == 0 )
printf("%s가 %s와 같습니다.\n", s1, s2);
else
printf("%s가 %s보다 뒤에 있습니다.\n", s1, s2);
return 0;


구조체

  • c언어는 절차지향언어( 코드가 순차적으로 실행되는 언어 )
    c++은 절차지향언어 + 객체지향언어
  1. 구조체란 무엇인가?
    자료형에는 2가지 종류가 있다.

기본자료형 : char int float double 등
파생자료형 : 배열, 열거형, 구조체, 공용체

구조체( 사용자정의자료형 )
= 서로 다른 자료형을 하나로 묶는 구조.묶이면 또 다른 자료형으로 취급됨
= 사용자가 원하는 크기, 용도대로 묶어서 사용

구조체 내부에는 기본자료형들이 들어간다.

우리가 int num이라고 변수를 선언했듯이 구조체도 '구조체 num;'이라고 선언하면 구조체 변수가 되는 것(구조체의 크기는 그때그때마다 다름)

그리고 선언된 이 변수를 객체라고 부른다.c++에선 이 선언된 구조체 변수를 가지고 프로그래밍을 한다.

class가 곧 구조체다! 즉 위에서 말한 구조체 변수 = 객체 = 클래스임

그리고 구조체 안에는 자료형 뿐만 아니라 함수도 들어간다.

구조체를 쓰는 이유
우리가 비슷한 요소들을 한꺼번에 관리할 목적으로 배열을 썼다싶히 구조체도 어떠 한 대상의 여러가지 정보들을 관리하기위해 그에 따른 자료형 여러개를 합쳐 한 틀로 관리를 하는것 (ex: 이름 배열, 전화번호 배열, 주소 배열 등등 자료형이 다양함)
이게 없으면 다일일히 해야되는 비효율적인 상황이 발생됨

붕어빵틀 처럼 생각 : 붕어모양 입모양 비늘몇개 등등 여러가지 생각하고 하나의 틀을 만듬.그리고 그 속에 여러가지(값)을 넣을 수 있음.그래도 나오는건 붕어빵이다.

구조체를 만든다 = 붕어빵틀을 만든다.

2.구조체 선언과 구조체의 변수 선언( != 변수를 선언)

구조체 선언과 구조체 변수 선언은 다르다!!!

ㄱ.구조체 선언(=구조체 정의)
구조체는 struct라는걸 통해 정의하는데 아래와 같이 정의한다.(함수처럼 main밖에서)

struct 구조체태그이름 {
자료형 멤버이름;
자료형 멤버
이름;
};

예시)
struct student{
int number;
char name[20];
double height;
};

이전에는 자료형 변수 끝이였는데, 이번엔 자료형까지도 정의해줘야된다.구조체는 자료형의 집합이고 내가 만든 자료형이니깐 컴퓨터에 알려줘야돼서 선언을 해줘야되는것
-> 사용자정의자료형 틀에 이름을 붙혀서 알려준다.

구조체태그이름 : 자료형의 이름(=태그 / 단,자료형들을 대표하는 이름으로)

구조체를 선언할 때도 중괄호로 묶는다.

자료형 멤버_이름; : 자료형과 속성 중 하나가 들어간다.근데 이때 변수선언처럼 보이지만 아직 변수가 선언된게아니라 변수들을 묶어놓은것 뿐(자료형만 선언했다고봐야된다.저 변수들은 아직 어디에도 못쓴다.)

근데 변수 선언된거 아니냐? -> 얘네들은 일반적인 변수가 아닌 '멤버 변수'라고 한다.
(함수에서의 지역변수랑 비슷.함수에서 지역변수들이 항상 있는게 아니라 호출될때만 생기는거라고했는데 얘도 구조체변수가 선언이 될 때만 멤버 변수가 생성이 되는것)

ㄴ. 구조체 변수 선언

int main(void){
struct student s1

...

}

변수 선언문 구조

struct = student가 구조체 변수라는것을 식별해주기 위해 붙혀주는 것
student = 선정한 구조체 이름
s1 = 구조체 변수의 이름

이렇게 선언하면 위 정의문을 기준으로 하면 변수 s1 안에 4바이트짜리 number, 20바이트짜리 배열 name, 8바이트짜리 height가 들어간다.

여기서 s2도 선언하면 위처럼 똑같은게 하나 더 만들어짐

ㄷ. 구조체 변수 초기화
배열처럼 하면된다.
struct student {
int number;
char name[10];
double height;
};

struct student s1 = { 24, "Kim", 178.9 };

ㄹ.구조체의 멤버 변수 참조(=메모리에 접근)
구조체 정의문에서 우리가 변수들 안에 있는 값을 넣고싶을때는 .연산자로 그 값을 참조한다. -> .과 변수 이름으로 메모리에 접근이 가능한 것

s1.number = 26; // 정수 멤버
-> s1 안에 들어있는 number를 가져와서 26을 대입해라
strcpy(s1.name, "Kim"); // 문자열 멤버
-> s1 안에 들어있는 name(주소값)에 kim을 카피해라
s1.height = 183.2; // 실수 멤버

ㅁ.구조체 변수의 입출력

printf("학번: %d\n", s.number);
printf("이름: %s\n", s.name);
printf("신장: %f\n", s.height);

여기서 scanf할때도 똑같이하고 다만 s.number, s.height 앞에 &만 붙혀주면됨.
s.name은 여기서 배열이여서 자체로 가능

profile
Emotional realizer

0개의 댓글