본문 바로가기
C언어

C언어 기초 part 2-4. 문자열

by algosketch 2020. 3. 20.
  • 문자열
  • 아스키 코드
  • 문자열 변수
  • 문자열 입력

 

1. 문자열

 지금까지는 숫자만을 다뤄왔다. 하지만 문자열을 다뤄야하는 경우도 많다. 문자열이란, 한 단어, 문장 혹은 그 이상의 글자를 말하고 이를 통칭하여 문자열이라 부른다. 지금부터 우리는 문자열을 변수 형태로 다루는 것이 목표다.

 

2. 아스키 코드

 ASCII 코드는 American Standard Code Information Interchange code이다. 컴퓨터는 문자열을 그대로 받아들일 수 없다. 따라서 컴퓨터는 문자를 숫자로 바꿔서 처리한다. 각각의 문자는 숫자와 대응하게 되는데, 이것을 정리한 표가 아스키 코드 표다. 포털에서 검색하여 쉽게 찾을 수 있다. 숫자 또한 문자열의 일부라면 문자로 처리된다. 1은 숫자 1을 의미하고 '1'은 문자 1을 의미한다. 기본적으로 아스키 코드는 7bit로 128가지(2의 7제곱) 문자 표현이 가능하다. (7bit에 오류 검출 코드 1bit를 추가해 1byte(==8bit)로 사용한다.) 단, 1byte로는 한글 표현이 제한되어 만약 한글을 다룬다면 한 문자에 2byte가 할당된다.

 

3. 문자열 변수

 배열은 문자열을 표현하기에 가장 적절한 도구(자료구조)이다. 같은 자료형을 가진 여러 요소를 다루는데, 문자열 또한 1byte 크기의 코드를 여러 개를 묶어서 다루기 때문이다. ASCII코드는 1byte를 사용하는데, 1byte 자료형으로 가장 흔한 char형은 바로 문자를 담기 위한 자료형이다. (character -> char)따라서 문자열을 문자 자료형의 배열인 char형 배열을 이용한다.

 "Hello, World!" 문자열을 분석해 보자. 우선, 변수에 저장하는 방법은 다음과 같이 여러 가지가 있다.

char str1[] = "Hello, World!";
char str2[] = {'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\0'};
char * str3 = "Hello, World!";

printf("%s\n", str1); // Hello, World!
printf("%s\n", str2); // Hello, World!
printf("%s\n", str3); // Hello, World!

 

 우선, 첫 번째와 두 번째는 결과가 동일하다. 첫 번째는 문자열을 할당하고 그 크기에 맞는 배열을 메모리에 할당한다. 두 번째는 문자열의 요소를 각각 배열의 원소로 넣는다. 첫 번째와 두 번째의 결과가 동일하다고 했는데, str2의 마지막 원소 '\0'에 의문이 생길 것이다. 이것은 NULL문자라고 부르며, ASCII 코드 0번에 대응한다. '\0' 대신 0이나 NULL을 입력해도 된다. 컴퓨터는 문자열을 출력할 때 NULL문자를 만나기 전까지 출력한다. 만약 마지막에 NULL문자를 넣지 않고 출력한다면 배열의 범위를 초과하고도 계속해서 0을 만날 때까지 출력한다.

 앞서 설명하면서 세 번째 문자열은 성격이 다르다는 느낌을 주었다. 세 번째 문자열은 문자열 상수라고 부르며, 수정이 불가능하다. 반대로 str1, str2는 배열로 접근하여 수정이 가능하다.

char str1[] = "Hello, World!";
char str2[] = {'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\0'};
char * str3 = "Hello, World!";

str1[0] = 'h';
str2[0] = 'h';
str3[0] = 'h'; // 에러

 

 str3은 의미가 조금 다르다. str1과 str2의 경우에는 배열이 사용할 자리를 먼저 확보해 두고 저장하는 반면, str3은 이미 메모리 어딘가에 "Hello, World!"가 저장되어 있는데 그 주소를 가리키기만 할 뿐이다. str1, str2의 경우엔 집을 갖고 있는 것이고 str3은 주소만 알고 있는 것이다. 집 주소만 알고 있는데 찾아가서 인테리어 바꾸고 그러면 불법이듯이 프로그래밍 할 때도 그러면 안 된다.

 문자의 서식문자는 %c, 문자열의 서식문자는 %s, 숫자의 서식문자는 %d이다. 문자열도 실제로 저장되는 값은 아스키 코드로 숫자이다. 즉, 숫자로도 출력이 가능하다.

char str[] = "Hello, World!";

printf("%s %c %d", str, str[1], str[1]); // 출력:Hello, World! e 101

 

4. 문자열 입력

char character;
char str[20];

scanf("%c %s", &character, str);

 

 문자를 입력하는 방법도 변수를 입력하는 방법과 다를 게 없다. 하지만 문자열 입력을 보라. &기호가 붙어있지 않다. 왜 문자열 입력에서는 &기호가 빠졌을까? 그러고 보니 &기호는 값을 주소값으로 변경시켜주는 포인터 연산이다. 우리가 지금까지 외워서 사용했던 scanf의 인자도 알고보니 포인터였던 것이다! 문자열은 배열에 저장되어 있다. 배열의 이름은 포인터다. scanf() 함수는 원래 포인터를 받는다. 즉, str을 그대로 입력하는 것이 원래 scanf의 규칙에 맞는 것이지 문자열이라서 특별히 다른 것이 아니다!