문자열의 길이 및 탐색
사용자로 부터 문자열을 입력받아 한 글자씩 출력하는 프로그램을 만들어 보겠습니다.
간단하게 for 루프를 통해 문자열의 인덱스를 하나씩 증가시켜가면서 해당하는 문자를 출력하면 될텐데요, 문자열의 끝은 어떻게 알 수 있을까요?
한가지 방법은 해당하는 인덱스의 문자가 널 종단 문자, 즉 ‘\0’와 일치하는지 검사하는 것입니다.
즉, s라는 문자열이 있다고 할 때 for (int i = 0; s[i] != ‘\0’; i++) { ..} 과 같은 루프를 사용하면 되겠죠.
하지만 아래 코드와 같이 strlen() 이라는 함수를 사용할 수도 있습니다.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Input: ");
printf("Output:\n");
for (int i = 0, n = strlen(s); i < n; i++)
{
printf("%c\n", s[i]);
}
}
strlen은 문자열의 길이를 알려주는 함수로, string.h 라이브러리 안에 포함되어 있습니다.
위 코드에서는 n이라는 변수에 문자열 s의 길이를 저장하고, 해당 길이 만큼만 for 루프를 순환합니다.
따라서 일일이 널 종단 문자를 검사하는 것 보다 훨씬 효율적입니다.
문자열 탐색 및 수정
사용자로부터 문자열을 입력받아 대문자로 바꿔주는 프로그램을 아래와 같이 작성할 수 있습니다.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for (int i = 0, n = strlen(s); i < n; i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
printf("%c", s[i] - 32);
}
else
{
printf("%c", s[i]);
}
}
printf("\n");
}
먼저 사용자로부터 입력받은 문자를 s라는 변수에 저장합니다.
그리고 s의 길이만큼 for 루프를 돌면서, 각 인덱스에 해당하는 문자가 ‘a’보다 크고 ‘z’보다 작은지 검사합니다.
즉, 소문자인지 검사하는 것과 동일합니다.
여기서 문자의 대소비교가 가능한 이유는 ASCII값, 즉 그 문자가 정의되는 ASCII 코드 상에서의 숫자값으로 비교할 수 있기 때문입니다.
또한 알파벳의 ASCII 값을 잘 살펴보면 각 알파벳의 소문자와 대문자는 32씩 차이가 남을 확인할 수 있습니다.
따라서 각 문자가 소문자인 경우 그 값에서 32를 뺀 후에 ‘문자’ 형태로 출력하면 대문자가 출력이 됩니다.
각 문자가 이미 대문자인 경우는 그냥 그대로 출력하면 됩니다.
이와 동일한 작업을 수행하는 함수가 ctype 라이브러리에 toupper() 이라는 함수로 정의되어 있습니다.
이를 이용하면 간단하게 아래와 같이 대문자 변환 프로그램을 작성할 수 있습니다.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for (int i = 0, n = strlen(s); i < n; i++)
{
printf("%c", toupper(s[i]));
}
printf("\n");
}
생각해보기
string.h와 ctype.h의 라이브러리에 다른 어떤 함수가 있는지 확인해 보고, 어떤 함수를 어떻게 활용해 볼 수 있을지 생각해봅시다.
* string.h와 ctype.h를 검색해보시면 사람들이 잘 정리한 글을 찾을 수 있을 것입니다. 코딩에서 자기가 검색해서 공부해보는 것도 매우 중요하기 때문에 직접 찾아보도록 하겠습니다.
comment
string.h의 strcpy : 문자열 복사
string.h의 strcat : 두 개의 문자열 합치기
ctype.h의 tolower : 소문자로 변환
ctype.h의 toascii : 아스키코드로 변환
tolower(a) 소문자로 a를 출력합니다.
strstr(s1, s2) 문자열 s1에서 문자열 s2를 찾습니다.
strcat(char* destination, const char* source) : 문자열합치기, destination의 널 종단 문자 위치에 source의 첫 문잘로 덮어 씌워진다. 만약 destination의 널 종단 위치 주소의 바로 뒤 주소가 이미 할당되어있다면 오륙가 발생한다.
toupper() : 대문자 변환, tolower() 소문자 변환, isupper() 대문자 여부 판단, islower() 소문자 여부 판단
string.h의 strncpy(문자열에서 지정한 부분 만큼 복사한다.) 함수를 이용하여 회원가입 시 개인정보 저장 후 식별에 있어 일부만을 추출하여 보이게 하여 개인정보를 보호할 수 있을 것 같다.
사용자로부터 입력받은 패스워드의 길이 및 영문자, 숫자, 특수문자의 혼합 여부를 파악하여 패스워드의 강도를 평가하고 특정 조건을 충족하지 못하면 사용자에게 알리는 패스워드 유효성 검사로 활용가능할 것 같다.
5분 30초 즈음에 나오는 코드 입력 시 컴파일이 안 되는 오류 발생.
1. n = strlen(s); i < n; 으로 입력 시: try using a double equals sign (==) instead of a single equals sign (=).
2. n == strlen(s); i < n; 으로 입력 시: you've used a name n on line 10 of string.c which hasn't been defined.
즉, =를 하나만 쓰든 두 개를 쓰든 오류가 발생해 이도저도 못하는 상황이 됨.
-> 해결) for문 작성 시 int i = 0 다음에 ,가 아닌 ;로 오작성한 문제 발견.
초기화 할 두 가지 변수를 쉼표로 구분함으로써 문제 해결.
string.h의 strcmp(두 문자열을 아스키코드 값 기준으로 비교)를 이용해 프로그램에서 값을 입력 받았을 때 그것이 정답과 일치하는지 확인할 수 있다. ctype.h에서도 비슷한 용도로 isblank 등을 이용해 공백이 없어야 하거나 숫자, 알파벳만 필요한 경우 검증하는 기능을 할 수 있다.
다른 질문으로 도우미 함수(#include <~~~.h>)를 사용할 때 순서 배치를 아무 열에다가 놓아도 되나요? 본문과 다르게 실행해봤는데 이상없이 잘 작동해서.. 나중에 오류가 생길만한 부분인가요?
string.h의 strchr 함수를 이용해서 문자열에서 특정 알파벳 이후의 글자들만 추출할 수 있다! -> 인덱싱을 가능하게 할 수 있지 않을까? (전화번호부 C 부터 시작하는건 몇페이지야? 등)
ctype.h의 tolower 함수를 이용해서 간단하게 위 강의의 반대로 이번엔 소문자로 바꿀 수 있을 것!
string.h 헤더 파일은 문자열 처리 함수를 제공합니다. 이 함수들을 사용하여 문자열을 조작, 복사, 비교 및 검색할 수 있습니다.
ctype.h 헤더 파일은 문자와 관련된 함수들을 제공합니다. 주로 문자의 속성을 확인하고 조작하는 데 사용됩니다.
string.h 에는 c문자열을 다룰 수 있는 함수들이 포함되어있다. strcat함수를 통해 로그인 문장을 만들 수 있을 것 같다.
ctype.h 에는 문자들이 조건에 맞는지 검사하고 변환하는 함수들을 포함하고 있다. 입력받은 문자열을 형식에 맞게 변환시킬 수 있을 것 같다.
ctype.h
-> 문자 검사함수, 문자 변환함수에 관련된 것들이 있음.
string.h
-> 문자열처리함수가 있음
string.h
이 헤더 파일에는 C 문자열과 배열을 조작하는 여러 함수가 정의되어있습니다. 복사, 연결, 비교, 검색 등의 기능을 가진 함수
ctype.h
이 헤더는 개별 문자를 분류하고 변환하는 여러 함수가 정의되어있습니다. 어떤 문자인지 구분하는 함수들, 대소문자를 변환하는 하
* int를 입력하는 부분에 char를 입력해도 자동으로 int로 변환됨
[string.h]
strcpy(char* s1, char* s2) : 스트링 복사
strcat(char* s1, const char* s2) : s1에 s2를 합침
strcmp(const char* s1, const char* s2) : s1과 s2가 같으면 0, 같지 않다면 -1
strchr(const char *s, int c (char 입력 가능)) : s에서 c 찾기 (가장 처음 나오는 문자 기준, 앞에서 끊음 ex) have a nice day에서 n을 찾는다고 하면 ice day가 출력됨)
[ctype.h]
isalpha(int c)
islower(int c)
isspace(int c)
isuppder(int c)
tolower(int c)
toupper(int c)
ctype.h : isalpha()(알파벳 판단), islower()(소문자 판단), isupper()(대문자 판단) 등
-> 정규표현식 없이 원하는 형식(알파벳, 대/소문자로만 구성된 스트링)으로 입력받도록 강제하거나 변환할 수 있음
string.h : strlen()(스트링 길이반환), strcpy()(스트링 복사), strcmp()(스트링 비교) 등
-> 입/출력 길이 제한, password 검사, 폼 입력 등 다양한 스트링 기반 처리가 가능
1. strcmp (문자열1, 문자열2) : 문자열1과 문자열2가 동일하다면 0 출력
- 해당 함수를 통해 아이디 비밀번호가 동일한지 비교하는 프로그램을 만들 수 있다. ex) 비밀번호 찾기
2. strcat (문자열 붙이기)
strcat("bus", "map") = busmap
strcat("hello, ", "world");
string s = get_string();
if (islower(s) === 0) {
printf("%s", tolower(s));
}
1. string.h 라이브러리의 함수 종류
1) 문자열을 복사하는 함수
2) 문자열을 합치는 함수
3) 문자열을 비교하는 함수
4) 문자열을 검색하는 함수
5) 기타
2. ctype.h 라이브러리의 함수
1) 문자를 검사하는 함수
2) 문자를 변환하는 함수
string.h
이 헤더 파일에는 C 문자열과 배열을 조작하는 여러 함수가 정의되어있습니다. 복사, 연결, 비교, 검색 등의 기능을 가진 함수들이 정의되있습니다.
ctype.h
이 헤더는 개별 문자를 분류하고 변환하는 여러 함수가 정의되어있습니다. 어떤 문자인지 구분하는 함수들, 대소문자를 변환하는 두 함수가 정의되있습니다.
ㅡ<string.h>
대략 100개 이상의 함수들이 내장되어있다.
이중에 중요한 5가지가 있다.
-strcpy, strcat, strcmp, strchr, strlen
1. strcpy(char * s1, const char*s2)
다른 배열로 모든 원소들을 복사한다.
ex)
char str1[] = "cs50", str2[11];
strcpy(str2, str1);
puts(str1);
puts(str2);
/* result:
cs50
cs50
*/
원형 배열을 건들이지 않고 복사하여 새로운 작업을 할때 사용할 수 있을 것 같다.
2. strcat(char* s1, const char*s2)
한 배열에 다른 배열을 이어 붙이는 함수이다.
char dest[30] = "C", source[30] = "cs50";
strcat(dest, source);
puts(dest);
// result: C cs50
서로 다른 배열을 합할 때 유용할 것 같다.
3. strcmp(const char*s1, const char*s2)
배열 2개를 대소문자로 비교하는 함수이다.
char str1[] = "cs50", str2[] = "ts50";
printf("%d", strcmp(str1, str2));
// result: -1
만약 앞 배열이 크다면 1, 같다면 0, 같지 않다면 -1을 출력한다.
주로 두 문자열이 같은 지 아닌 지 확인할 때 쓰면 좋을 것 같다.
4. strchr(const char*s, int c)는 배열에서 특정 문자를 찾는다.
char strTemp;
char string[] = "This is a good car!";
strTemp = strchr(string, 'a');
printf("%s
", strTemp);
strTemp = strchr(string, 'c');
printf("%s", strTemp);
/* result:
a good car!
car!
*/
strchr은 그 문자를 찾으면 그 부분 전에 끊는다.
특정 문자를 포함하는 단어를 출력할 때 유용할 것 같다.
5. strlen(const char*s)
문자의 수 (NULL 제외)를 세주는 함수이다.
반복문을 사용해서 문자를 하나하나 출력할 때 유용할 것 같다.
<ctype.h>
문자들을 분류하거나 대소문자를 전환하는데 사용되는 함수들의 집합이다.
int tolower (int c);
> c를 소문자로 변환한다.
대문자가 포함되어있는 string을 전부 소문자로 바꿀 때 유용할 것 같다.
int toupper (int c);
> c를 대문자로 변환한다.
전체 대문자로 바꿀 때 유용할 것 같다.
int _toascii (int c);
>c를 아스키 코드로 변환한다.
특정 코딩테스트 문제를 풀때 유용하다.
int isalpha (int c);
> c가 알파벳이면 0이 아닌 값을 반환한다.
변수에 알파벳이 있는지 확일 할 때 유용하다.
int isdigit (int c);
>c가 숫자이면 0이 아닌 값을 반환한다.
숫자인지 확인할 때 유용하다.
int islower (int c);
> c가 소문자이면 0이 아닌 값을 반환한다.
소문자인지 확인할 때 유용하다.
int isupper(int c);
>c가 대문자이면 0이 아닌 값을 반환한다.
대문자인지 확인할 때 유용하다.
int isalnum (int c);
> c가 알파벳 또는 숫자이면 0이 아닌 값을 반환한다.
알파벳이나 숫자인지 판별할 때 유용하다.