[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);
}
간단합니다. ㅎㅎ *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 함수에 대해서 최대한 많은 것들을 담아보려고 노력했어요 ㅎㅎ
언제나 질문은 환영합니다 ~ :)
공감 & 댓글 & 광고보답은 지식공유에 힘이 됩니다
'별걸다하는 IT > 프로그래밍언어' 카테고리의 다른 글
[Java/C/C++] 변수 선언, 초기화 방법과 변수 명명 규칙, 카멜(Camel) 파스칼 표기법 (1) | 2019.10.23 |
---|---|
[Java, C, C++ 강좌] 연산자란? 연산자 종류 - 단항 연산자, 이항연산자, 삼항연산자 (3) | 2019.10.20 |
[Java, C, C++ ] 배열이란, 배열 선언 및 초기화 - 프로그래밍기초 (4) | 2019.10.13 |
[C언어]문자열 복사 함수 strcpy, strcnpy와 주의사항, 널문자 (null) - string.h 라이브러리 파헤치기 (3) | 2019.10.10 |
[C, C++, Java 등 언어 공통] 반복문 상세설명!(for, do while, 향상된 for문 사용법, 차이점 및 실행 순서) (1) | 2019.10.07 |
최신 댓글