80 – 고급 변환 함수

기본 변환 함수에서 봤던 변환은 간단한 정수와 실수만을 변환하였던 것이라면, strtol과 strtoul 함수를 이용하면 변환이 종료된 지점을 알 수 있는 데다가 10진 정수 형태의 문자열 이외에도 처리가 된다. 그 외에도 고급 함수가 있는데 간단히 살펴보면 다음과 같다.

  • 함수이름 | 기능
  • strtol | 특정 진수 형태의 문자열을 정수(long)형으로 변환한다.
  • strtoul | 특정 진수 형태의 문자열을 정수(unsigned long)형으로 변환한다.
  • strtod | 실수 형태의 문자열을 실수(double)형으로 변환한다.
  • strtof | 실수 형태의 문자열을 실수(float)형으로 변환한다.

strtol에 대한 예시는 다음과 같다.

20170427_011816

첫 번째 변환은 10진수 형태의 문자열을 long형 10진수로 변환한 것이다. 두 번째 변환은 8진수 형태의 문자열을 long형 10진수로 변환한 것이다. 세 번째는 진수 판별 자리에 0을 넣어 자동으로 판별하도록 한 것이다. 그런데 문자열 앞에 0이 있기 때문에 8진수로 인식되었다. 마지막으로 16진수 형태로 변환하는데, 16진수에 쓰이는 문자가 아닌 @가 있어서 그 앞의 부분만 변환하고 포인터가 @를 가리킨 상태이다. 그래서 마지막 출력문에 포인터가 가리킨 문자열이 별도로 나온 것이다.

실수 변환에 대해서는 진법을 지정할 수 없으며 10진 실수 형태의 문자열만 처리할 수 있다. 실수 변환에 대한 예제를 보고 설명을 남기겠다.

앞에서 정수를 봤던 것과 거의 같다. 표현을 다 처리하지 못한 부분에 포인터가 지정되어 가는 것까지 완전히 똑같은 구조이다.

79 – 기본 변환 함수

기본 데이터 변환 함수는 정수나 실수 형태의 문자열을 정수나 실수로 변환하는 함수로 가장 기본적인 변환 함수이다. 이 함수를 실제로 어떻게 사용하는지 알아보기 전에 숫자가 아닌 문자열을 더하려고 하는 경우를 예제로 만들었다. 분명 오류가 발생한다.

정수가 아닌 10진 정수 형태의 문자열이라는 걸 알기 때문에 옳지 못하다는 걸 출력해줬다. 이러한 연산이 가능하기 위해서는 10진 정수 형태의 문자열을 정수 형태로 변환해 주어야 하는데, 이럴 때 사용하는 함수가 atoi이다. atoi를 사용하여 제대로 실행되도록 예제를 바꿨다.

그럼 이제 어떤 문자열을 처리할 수 있는지를 보여주도록 하겠다. 그래서 다양한 형태로 만든 예제를 삽입하였다.

위의 예제를 보면, 우선 부호를 지정할 수 있다는 것을 알 수 있다. 그리고 또한 공백 문자를 무시하고 수치 문자까지만 처리한다는 점도 알 수 있다. (그래서 뒤에 알파벳이 없어졌다.)

이러한 함수들은 여럿이 있는데, 간단히 정리해 보겠다.

  • 함수이름 | 기능
  • atoi | 10진 정수 형태의 문자열을 정수(int)형으로 변환한다.
  • atol | 10진 정수 형태의 문자열을 정수(long)형으로 변환한다.
  • atof | 10진 정수 형태의 문자열을 실수(double)형으로 변환한다.

atof를 이용해 실수형이 어떻게 진행되는지 또한 예제로 만들어보았다. 소수점 형태의 문자열과 지수 형태의 문자열을 모두 처리하고 부호 지정이 가능하며 실수 형태의 문자까지만 처리한다.

78 – 데이터 변환 함수

소스 파일은 ASCII 코드로 이루어진 문자열이므로 컴파일러는 이를 실행 파일로 변환하기 이ㅜ해 여러 절차를 거치는데 이 중 하나가 “123”같은 정수 형태의 문자열을 정수로 변환하고 “3.56”과 같은 실수 형태의 문자열을 실수로 변환해 컴퓨터가 이해할 수 있는 언어로 바꾸는 일이다. 이 외에도 컴퓨터는 0과 1 밖에 모르기 때문에 프로그래밍을 하다 보면 데이터를 변환하는 작업이 자주 발생해 라이브러리에서는 정수나 실수 형태의 문자열을 정수와 실수로 변환하는 함수를 제공하고 있다. 그런 변환 함수에 대해서 확인해보려고 한다.

77 – 문자열을 단어로 자르는 함수

앞에서 문자열을 연결하는 함수를 보았다면, 이젠 반대로 문자열을 자르는 함수를 보게 된다. 주어진 조건에 맞는 단어 단위로 자르고 싶을 때에는 strtok 함수를 이용하면 된다. 지정한 구분자가 나오면 단어로 자르고 단어의 첫 분자에 대한 포인터를 반환한다.

  • 함수이름 | 기능
  • strtok | 문자열에서 구분자와 일치하는 문자가 나오면 단어로 자른다.

예제를 보면 좀 더 쉽게 이해할 수 있다. 예제에서는 어떤 구분자를 기준으로 단어를 자를 지 지정한다. delim에 공백문자를 넣었는데, 이는 공백 문자가 나오면 자르겠다는 것이다. 그렇게 하여 4 개의 단어로 다르는 것이다.

그리고 예시에서 보면 두 번째 strtok가 쓰이는 걸 보면 NULL이 있다. 이것이 중요하다. 문장과 포인터를 선언한 상태를 확인하자.

이 상태에서 strtok 함수를 호출하면 Hello라는 단어로 잘리고 ptr은 첫 글자를 가리키는 상태가 된다.

그 다음에 호출되는 strtok 호출부터는 str이 아닌 NULL을 첫 인수로 설정해야 한다. 그래야 두 번째 호출을 하면 Linux라는 단어로 잘리고 ptr은 두 번째 단어의 첫 글자를 가리킨다.

여기서 내 글로 C언어를 처음 배우는 사람을 위해, 왜 두번째부터 인수에 NULL을 삽입하는지를 작성하겠다. strtok 메뉴얼에도 나와있는 것이지만, 첫 번째 작업을 하고 났을 때에 잘리고 난 상태에서는 NULL이 아닌 다른 값으로 되어 있다. 그렇기 때문에 앞에서 자르고 남은 서브 문자열에서의 시작점을 만들어 줘야 하는데, 그것이 첫 번째로 잘리고 난 다음의 문자열이 끝났다는 것으로 할 수 있게끔 NULL을 삽입하여 주는 것이다. 즉, “Hello” 바로 다음에 공백문자를 발견하여 문자열을 자르고, 그 잘린 포인터에 NULL을 넣어서 앞의 문자열은 잘려서 끝났고 이제 그 다음의 나머지 문자열을 텀색하도록 하는 것이다. 그러면 두 번째부터는 “Linux C Programming”이라는 서브 문자열에서 탐색을 진행한다. Linux를 잘라낸 다음에도 또 NULL을 삽입해서 서브스트링을 “C Programming”으로 만들어주는 것이다. 이런 식으로 반복해서 문자열을 하나 하나 잘라내기 위해 포인터를 초기화 해주는 것이다.

76 – 문자열 검색 함수

검색은 사실 여러 곳에서 많이 쓰인다. 데이터베이스에서 쿼리문을 이용해 필요한 데이터를 찾는 것과 같이, 표준 라이브러리에서는 문자열의 특정 문자 혹은 특정 문자열을 검색할 수 있는 함수들을 제공한다. strchr, strrchr, strstr, strspn, strpbrk이 문자열 검색 함수이다. 함수에 대한 정리를 우선 한번 하고 나서 몇몇 함수의 예시를 확인하겠다.

  • 함수이름 | 기능
  • strchr | 문자열에서 임의의 문자가 처음으로 발견된 위치를 검색한다.
  • strrchr | 문자열에서 임의의 문자가 마지막으로 발견된 위치를 검색한다.
  • strstr | 문자열에서 임의의 문자열을 검색한다.
  • strspn | 문자열에서 특정 문자들로 이루어진 초기 문자열의 길이를 검색한다.
  • strcspn | 문자열에서 특정 문자들이 아닌 문자들로 이루어진 초기 문자열의 길이를 검색한다.
  • strpbrk | 문자열에서 특정 문자들 중 일치하는 첫 분째 문자를 검색한다.

이렇게만 적으면 딱 와닿지는 않는다. 그래서 예시를 하나 하나 확인해보겠다.

알파벳 문자열에서 K가 처음으로 나오는 위치를 찾는 예시이다.

해당되는 포인터 ptr이 K를 찾아서 K를 가리키고 있는 상태인 것이다. 그래서 K부터의 문자열이 출력된 것이다.

strrchr의 예제로는 문자열 A가 마지막으로 발견되는 위치를 검색해서 마지막 A의 위치를 포인터로 가지고 있는 것을 만들었다. 그 예제가 아래의 것이다.

다음 예제는 “Linux” 문자열을 찾는 프로그램이다. strstr 함수는 두 군데 있으면 처음 발견되는 위치에 대한 포인터를 반환하는데, 이 예시가 그것을 잘 보여줄 것이다.

다음으로 strspn의 예제를 살펴볼 것이다. 앞에 문자열에서 뒤에 문자들로 이루어진 곳을 찾는데, 이게 조금 헷갈릴 수 있다.

“seoulKorea” 문자열에서 문자 집합 “elmnopsu”의 문자로만 이루어진 문자열을 찾는데, 여기서 s 뿐만 아니라 e,o,u,l도 문자 집합에 속한다. 그러나 K는 문자 집합에 있지 않다. 즉, 찾고자 하는 문자열이 seoul이 된다. 그리고 나서 두번째로 나오는 것은 e인데 첫 번째에 나온 문자열에 대해서만 처리를 한다. 그래서 seoul 문자열의 길이인 5가 반환되어 나온 것이다.

마지막으로 strpbrk 함수를 보겠다. 문자열에서 문자 집합의 문자 중 일치하는 첫 번째 문자를 찾아서 그 포인터를 반환한다.

K가 첫 번째로 일치하기 때문에 K를 가리키는 문자열 포인터가 되어 Korea가 반환된 것이다.

문자열 검색의 경우에는 함수가 좀 어려우면 구글에서 예제를 좀 더 찾아서 보는 것을 권장한다.

75 – 문자열 길이 계산 함수

각 문자를 세어서 문자열의 길이를 구할 수도 있지만 strlen 함수를 이용해서 간단하게 구할 수 있다. 길이에 따라서 변환 처리를 해야 할 수도 있는데 일일이 길이를 구하는 작업을 통하는 것보다 함수가 있는 편이 더 편하기 때문이다.

  • 함수이름 | 기능
  • strlen | 문자열의 길이를 계산한다.

입력받은 문자열의 길이를 파악하고, 그 길이를 이용해 문자열을 거꾸로 출력하는 예시를 만들어보았다. 이런 식으로 문자열을 가지고 놀 때, 문자열의 길이를 아는 것이 중요하기 땜에 예시로 썼다.

74 – 문자열 복사 함수

배열 변수에 저장되어 있는 문자열은 배열을 복사하는 방법으로도 복사를 할 수 있겠지만 문자열 복사 함수를 쓰면 간단하게 복사할 수 있다. 쓰이는 함수는 셋인데 요약하면 다음과 같다.

  • 함수이름 | 기능
  • strcpy | 문자열을 복사한다.
  • strncpy | n개의 문자열을 복사한다.
  • strdup | 문자열을 저장하고 포인터를 반환한다.

우선 strcpy 함수를 사용한 예제를 확인하겠다. 두 번재 버퍼 배열의 내용이 전부 Linux로 바뀌어있다.

strdup 함수를 사용한 예시를 보도록 하겠다. 이 함수는 문자열에 대한 메모리 영역을 할당하고 포인터를 반환한다. 주로 문자열 포인터 변수에 사용한다. 아래의 예제는 “Hello Linux”라고 메모리에 할당된 문자열의 포인터를 문자열 포인터 변수에 연결하는 것을 보여준다. 즉, 함수의 반환값이 문자열 포인터인 것이다.

73 – 문자열 비교 함수

두 개의 문자열이 같은지를 비교하는 문자열 비교 함수가 있다. 4 개의 함수가 있는데, 다음과 같다.

  • 함수이름 | 기능
  • strcmp | 두 문자열을 비교한다.
  • strncmp | 두 문자열의 n개의 문자를 비교한다.
  • strcasecmp | 대소문자를 구별하지 않고 두 문자열을 비교한다.
  • strncasecmp | 대소문자를 구별하지 않고 두 문자열의 n문자를 비교한다.

우선 strcmp가 어떻게 쓰이는지 예시로 확인하겠다. strcmp 함수는 string.h에 정의되어 있기 때문에 헤더를 더 추가한다.

quit과 비교하였을 때, 같지 않기 때문에 계속 입력받다가 quit이 들어오니 종료된 것이다.

72 – 문자열 연결 함수

어떤 작업을 하다 보면 따로따로 되어 있는 문자열을 연결하여야 하는 경우가 있다. 물론 일일이 연결해서 작업하는 방법도 있다만 연결할 문자열이 많다면 은근 귀찮을 것이다.  이런 작업을 일일이 구현하지 않아도 되도록 문자열을 연결하는 함수가 존재한다. 함수 이름만 알려주고 예시를 보여줄 것이다. 자세한 것은 검색하면 형태가 나온다.

  • 함수이름 | 기능
  • strcat | 문자열 src를 문자열 dest 끝에 연결한다. 연결 후 문자열을 반환한다.
  • strncat | 문자열 src 중 n 문자열(문자열 수)을 dest 끝에 연결한다. 연결 후 문자열을 반환한다.

위의 두 함수는 어떤 차이가 있는 것인지를 예시로 보여주도록 하겠다. strncat에서 말하는 n은 문자열 수다. 즉, 문자열 처음에서부터 n까지의 문자만을 떼어서 삽입한다는 것이다.