본문 바로가기

별걸다하는 IT/프로그래밍언어

[C언어][string.h]문자열 관련 함수- strlen(길이)함수의 모든 것, 함수 코드, 사용법 및 예제, 주의사항 등

[C, C++완전정복 목차]

안녕하세요~!!

오랜만이예요 ㅎㅎ 그동안 할일이 초큼 쌓여있는걸 처리하느라..ㅎㅎㅎ

오늘은 무진장~~ 많이 쓰이는, 안사용할 수가 없는 문자열 관련 함수들을 정리해보려고 해요 ㅎㅎ

string.h에 있는 모든 함수를 이 한 포스팅에서 다룬다면 좋겠지만,, 워낙 많은 함수가 있으므로 나눠서 포스팅을 해보도록 합시다.

문자열 대상

C언어 기준, '\0'으로 끝나는 C형식 문자열 방식에서 사용되는 ,

string.h 라이브러리에 정의되어 있는 문자열 함수입니다. 따라서 #include <string> 라이브러리에 정의되어 있는 string 타입을 사용하시면 안됩니다~

문자열 길이 구하는 함수

strlen

문자열의 길이를 구합니다.

문자열의 끝을 알리는 널 문자는 제외하고 실제 들어가 있는 글자의 개수를 반환합니다. (공백 포함)

헤더파일

#include <string.h>

함수 프로토타입

size_t strlen(const char *str);

인자

const char * str : C style의 문자열

리턴값

문자열의 길이, 타입은 size_t를 갖는다. (참고로 size_t는 부호 없는 정수형을 의미, 결과값을 int에 받아도 자동형변환되므로 걱정하지 않아도 된다)

사용 예시

기본 사용법 비교 예시:

#include <stdio.h>
#include <string.h>
int main() {
	char str1[20] = "coding";
	printf("str1 문자열 길이: %d\n", strlen(str1));
	char str2[] = "nice day!";
	printf("str2 문자열 길이: %d\n", strlen(str2));
	char str3[] = { 'h','e','l','l','o' };
	printf("str3 문자열 길이: %d\n", strlen(str3));
	char str4[] = { 'h','e','l','l','o','\0' };
	printf("str3 문자열 길이: %d\n", strlen(str4));
	char str5[50] = { 'h','e','l','l','o','\0' };
	printf("str3 문자열 길이: %d\n", strlen(str5));
	return 0;
}

결과창

▶str1의 경우, 마지막 널문자를 제외한 coding 각 글자의 개수를 세서 반환했으므로 6이 반환됩니다.

▶str2의 경우, 띄어쓰기까지 개수에 포함시킨 다는 것을 보여주기 위한 예제.

▶str3의 경우, 일일이 할당했을 경우 마지막에 널문자를 넣어주지 않을 경우, 널문자가 읽힐때까지 무작정 개수를 세기 때문에 이상한 값이 나온 것을 보여주는 예시.

▶str4는 널문자를 넣어주면 길이를 잘 세주는 걸 확인시켜주는 예시

▶str5는 배열의 길이가 아무리 커도, strlen이 길이를 재는 기준은 널문자이기 때문에, 50이 아니라 5가 찍힌다는 것을 보여주기 위해 작성한 예시입니다

 

입력받은 문자열 길이 출력하는 예시:

#include <stdio.h>
#include <string.h>
int main() {
	char str[50];
	scanf("%s", str);
	printf("너가 입력한 문자열은: %s, 길이는: %d\n", str, strlen(str));
	return 0;
}

결과창

함수에서 사용되는 예시:

#include <stdio.h>
#include <string.h>
void func(char* str);
int main() {
	char str[] = "hello world!";
	func(str);
	return 0;
}
void func(char* str)
{
	printf("%d\n", strlen(str));
}

결과값: 12

함수의 인자로 문자열을 넘겨준 후, 함수 내부에서 문자열의 길이를 출력하는 예시입니다.

주의할 점 or 같이 알아두면 좋은 점

▶문자열의 끝을 알리는 널문자를 제외한 길이를 리턴해준다.

▶C언어의 문자열에서 사용해야한다. string 클래스 형태의 문자열에서는 사용 불가!

▶char*은 주소를 저장하는 포인터이기 때문에 선언된 문자배열을 함수 인자로 넘겨서 strlen을 하는 것은 가능하지만, char*에서 문자열을 초기화하면 안됩니다. 따라서 char*타입으로 문자열을 초기화한 후 strlen해도 오류입니다.

▶strlen은 NULL 문자가 기준이기 때문에 문자열 마지막을 의미하는 '\0'이 할당되어 있지않으면, 이상한 값을 리턴합니다.

▶아 참고로 NULL문자는 '\0'를 의미하며, 아스키코드상에서는 NUL로 표기하고 있습니다.

▶널문자와 공백('')은 다릅니다. 공백문자의 아스키 코드 값은 32지만, 널문자의 아스키코드값은 0입니다.

▶사실 널문자는 integer 상수 0과 동일합니다.

▶NULL의 길이를 잴 수 있나??[strlen(NULL)] --> 아니요!

▶문자열을 복사하는 함수 strcpy와 커플로 같이 많이 사용된다.

함수 원형 코드

궁금하신 분들이 있을 것 같아서 함수 원형 코드를 추가했어요. 참고정도만 하기~

BSD계열의 경우:

#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
#else
#include <lib/libkern/libkern.h>
#endif

size_t
strlen(const char *str)
{
	const char *s;
	for (s = str; *s; ++s)
		;
	return (s - str);
}

출처: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlen.c?rev=1.7&content-type=text/x-cvsweb-markup

간단합니다. ㅎㅎ *s가 0이 아니면계속 count를 증가시키는 거예요 (참고로 0은 널문자를 의미하기도 하죠 ㅎㅎ)

또 다른 원형 GNU C라이브러리 (glibc): (ex 리눅스)

   1 /* Copyright (C) 1991-2019 Free Software Foundation, Inc.
   2    This file is part of the GNU C Library.
   3    Written by Torbjorn Granlund (tege@sics.se),
   4    with help from Dan Sahlin (dan@sics.se);
   5    commentary by Jim Blandy (jimb@ai.mit.edu).
   6 
   7    The GNU C Library is free software; you can redistribute it and/or
   8    modify it under the terms of the GNU Lesser General Public
   9    License as published by the Free Software Foundation; either
  10    version 2.1 of the License, or (at your option) any later version.
  11 
  12    The GNU C Library is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15    Lesser General Public License for more details.
  16 
  17    You should have received a copy of the GNU Lesser General Public
  18    License along with the GNU C Library; if not, see
  19    <http://www.gnu.org/licenses/>.  */
  20 
  21 #include <string.h>
  22 #include <stdlib.h>
  23 
  24 #undef strlen
  25 
  26 #ifndef STRLEN
  27 # define STRLEN strlen
  28 #endif
  29 
  30 /* Return the length of the null-terminated string STR.  Scan for
  31    the null terminator quickly by testing four bytes at a time.  */
  32 size_t
  33 STRLEN (const char *str)
  34 {
  35   const char *char_ptr;
  36   const unsigned long int *longword_ptr;
  37   unsigned long int longword, himagic, lomagic;
  38 
  39   /* Handle the first few characters by reading one character at a time.
  40      Do this until CHAR_PTR is aligned on a longword boundary.  */
  41   for (char_ptr = str; ((unsigned long int) char_ptr
  42                         & (sizeof (longword) - 1)) != 0;
  43        ++char_ptr)
  44     if (*char_ptr == '\0')
  45       return char_ptr - str;
  46 
  47   /* All these elucidatory comments refer to 4-byte longwords,
  48      but the theory applies equally well to 8-byte longwords.  */
  49 
  50   longword_ptr = (unsigned long int *) char_ptr;
  51 
  52   /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
  53      the "holes."  Note that there is a hole just to the left of
  54      each byte, with an extra at the end:
  55 
  56      bits:  01111110 11111110 11111110 11111111
  57      bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
  58 
  59      The 1-bits make sure that carries propagate to the next 0-bit.
  60      The 0-bits provide holes for carries to fall into.  */
  61   himagic = 0x80808080L;
  62   lomagic = 0x01010101L;
  63   if (sizeof (longword) > 4)
  64     {
  65       /* 64-bit version of the magic.  */
  66       /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
  67       himagic = ((himagic << 16) << 16) | himagic;
  68       lomagic = ((lomagic << 16) << 16) | lomagic;
  69     }
  70   if (sizeof (longword) > 8)
  71     abort ();
  72 
  73   /* Instead of the traditional loop which tests each character,
  74      we will test a longword at a time.  The tricky part is testing
  75      if *any of the four* bytes in the longword in question are zero.  */
  76   for (;;)
  77     {
  78       longword = *longword_ptr++;
  79 
  80       if (((longword - lomagic) & ~longword & himagic) != 0)
  81         {
  82           /* Which of the bytes was the zero?  If none of them were, it was
  83              a misfire; continue the search.  */
  84 
  85           const char *cp = (const char *) (longword_ptr - 1);
  86 
  87           if (cp[0] == 0)
  88             return cp - str;
  89           if (cp[1] == 0)
  90             return cp - str + 1;
  91           if (cp[2] == 0)
  92             return cp - str + 2;
  93           if (cp[3] == 0)
  94             return cp - str + 3;
  95           if (sizeof (longword) > 4)
  96             {
  97               if (cp[4] == 0)
  98                 return cp - str + 4;
  99               if (cp[5] == 0)
 100                 return cp - str + 5;
 101               if (cp[6] == 0)
 102                 return cp - str + 6;
 103               if (cp[7] == 0)
 104                 return cp - str + 7;
 105             }
 106         }
 107     }
 108 }

코드 출처: git://soourceware.org

또 다른 참고하면 좋은 사이트: http://www.ic.unicamp.br/~islene/2s2008-mo806/libc/string/strnlen.c

혹시 glibc를 잘 모르시는 분들을 위한 위키 링크

 

코드를 보시면, 32주소체계일 때, 그리고 64주소체계일 때 두 가지 경우의 모두 적용된 것을 볼 수 있어요 ㅎㅎ

좀 수월하게 해석을 돕자면,

unsigned long int는 32비트 주소체계에서 하나의 워드 길이입니다. (메모리에서 한 줄 = 4바이트)

이 함수에서 정의내린 것을 보면 비트 연산이 많죠 ㅎㅎ 비트가지고놀기(bit twiddling hacks)를 참고하시면 이해하기 조금 수월해집니다)

또 다른 string.h 함수 보기

문자열 복사 함수 strcpy, strncpy

 

[C언어]문자열 복사 함수 strcpy, strcnpy와 주의사항, 널문자 (null) - string.h 라이브러리 파헤치기

[C언어, C++언어 완전정복 목차 링크!] 안녕하세요~! 저번 시간 strlen, strtok 함수에 이어서 string.h 라이브러리에 속한 또 다른 함수 중 하나를 살펴보려고 합니다. 오늘은 매우매우 보편적이고 기본적이고..

jhnyang.tistory.com

strlen 함수에 대해서 최대한 많은 것들을 담아보려고 노력했어요 ㅎㅎ

언제나 질문은 환영합니다 ~ :)

공감 & 댓글 & 광고보답은 지식공유에 힘이 됩니다