Unit 42 문자열을 복사하고 붙이기
-strcpy-
strcpy는 문자열을 다른 배열이나 포인터로 복사해주는 함수다. strcmp 등과 마찬가지로 string.h 헤더에 선언돼 있다.
사용은 strcpy(<대상 문자열>, <원본 문자열>);로 하면 된다.
strcpy 역시 취약점이 있는 함수이므로 #define _CRT_SECURE_NO_WARNINGS를 써줘야한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char a[10] = "Hello";
char b[10];
// 10 크기의 char형 배열 a, b를 선언하고 문자열 Hello를 a에 저장
strcpy(b, a); // a의 문자열을 b에 복사
printf("%s %s", a, b); // a, b의 문자열 출력
}
위는 a에 저장된 "Hello" 문자열을 strcpy로 b에 복사한 후 a, b의 문자열을 출력하는 코드다.
출력 결과를 보면 제대로 문자열이 복사됐음을 알 수 있다.
이 strcpy로 복사를 해도 NULL 문자 역시 복사되기 때문에 대상 문자열은 NULL 문자까지 저장 가능해야한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *a = "Hello";
char *b = malloc(sizeof(char) * 10); // 10byte 동적 할당
strcpy(b, a);
printf("%s %s", a, b);
free(b); // 메모리 해제
}
위는 배열로 복사했던 것을 포인터로 복사해보는 것이다. 동작은 똑같다.
제대로 복사됐음을 알 수 있다.
마찬가지로 동적할당이 아닌 *a = "" 식의 포인터는 사용이 불가능한데, 그 이유는 복사할 공간도 없을뿐더러 읽기만 가능해서 복사(쓰기)가 불가능하기 때문이다. 따라서 malloc으로 동적할당을 해주는 방법으로 사용해야한다.
-strcat-
strcat는 문자열을 서로 붙여주는 함수다. 마찬가지로 string.h 헤더에 선언돼 있다.
사용은 strcat(<최종 문자열>, <붙일 문자열>);로 하면 된다.
#include <stdio.h>
#include <string.h>
int main()
{
char *a = "World!"; // 포인터 a에 문자열 World! 저장
char b[30] = "Hello "; // 배열 b에 문자열 Hello 저장
strcat(b, a); // a의 문자열을 b 문자열 끝 부분에 연결
printf("%s", b); // b의 문자열 출력
}
위는 포인터 a에 저장된 문자열 "World!"을 배열 b에 저장된 문자열 "Hello "에 연결한 후, 그 문자열을 출력하는 코드다.
제대로 연결돼서 b에 저장됐음을 알 수 있다.
연결 시 연결 된 문자열이 저장될 변수는 크기가 넉넉해야하고 일반 포인터(동적 할당 되지 않은)면 안된다. 일반 포인터의 경우 쓰기를 할 수 없기 때문에 붙인 문자열을 저장(쓰기)을 할 수 없다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *a = malloc(sizeof(char) * 30);
char b[30] = "Hello!";
strcpy(a, "Dypar, ");
strcat(a, b);
printf("%s", a);
free(a);
}
이런식으로 동적할당 된 경우는 쓰기가 가능하므로 문자열 연결 또한 가능하다. 다만 연결했을 때의 문자열도 저장할 수 있을 정도로 공간이 있어야한다.
제대로 연결되는 것을 볼 수 있다.
참고로 배열과 (동적 할당된)포인터 끼리의 연결도 가능하다.
Unit 43 문자열 만들기
-sprintf-
sprintf 함수는 서식을 지정하여 문자열을 만드는 역할을 한다.
사용은 sprintf(<배열, 포인터>, <서식>, <값1>...);로 하면 된다.
#include <stdio.h>
int main()
{
char a[100]; // 넉넉하게 100 크기의 char 형 배열 선언
sprintf(a, "Hello %s!", "dypar"); // Hello %s!를 서식으로 지정하여 a에 저장
printf("%s", a); // a의 문자열 출력
}
100 크기의 char형 배열 a를 선언하고 sprintf 함수로 지정 서식으로 만들어진 문자열을 a에 저장한 후 a를 출력하는 코드다.
지정 서식대로 Hello dypar!이 출력됐다.
보통 위 코드처럼 a 같이 문자열을 저장할 빈 배열을 버퍼(buffer)라고 부른다.
코드는 다르지만 대략적으로 위 사진처럼 문자열이 만들어지고 버퍼에 저장된다고 이해하면 될듯 하다.
#include <stdio.h>
int main()
{
char a[100];
sprintf(a, "%s %d!","Hello", 2021); // %s %d! 서식에 맞게 만들어진 문자열을 a에 저장
printf("%s", a);
}
위처럼 %d, %f 등 여러 서식 지정자도 사용할 수 있다.
지정한 서식대로 Hello 2021!이 출력됐다.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a = malloc(sizeof(char) * 30); // 30byte 크기의 메모리 확보
sprintf(a, "%s %d!","Hello", 2021); // 지정 서식대로 포인터 a에 문자열 저장
printf("%s", a); // a의 문자열 출력
free(a); // a가 가리키는 주소의 메모리 해제
}
위 코드처럼 동적할당된 포인터에도 sprintf로 문자열을 저장할 수 있다. 당연하지만 사용 후 free를 꼭 해줘야한다.
배열과 똑같이 동적할당된 포인터 역시 지정한 서식대로 잘 출력되는 것을 볼 수 있다.
배열과 마찬가지로 a와 같이 문자열을 생성할 메모리 공간도 버퍼라 부른다.
코드는 다르지만 배열과 비슷하게 동적할당된 포인터도 메모리 주소를 기준으로 sprintf로 만들어진 문자열이 저장되는 것을 알 수 있다.
Unit 44 문자열 검색하기
-strchr-
strchr은 문자열에서 특정 문자를 검색해서 해당 포인터를 반환하는 함수다. 마찬가지로 string.h 헤더에 선언돼 있다.
사용은 strchr(<대상 문자열>, <검색할 문자>);로 사용하면 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char a[30] = "origin, AoS, orgarn"; // 크기 30 char형 배열 선언
char *p = strchr(a, 'o'); // o로 시작하는 문자열 검색, 포인터 반환
while (p != NULL) // 더 이상 o로 시작하는 문자열이 없을 때까지 반복
{
printf("%s\n", p); // 검색된 문자열 출력
p = strchr(p + 1, 'o'); // 포인터에 1을 더하여 o 다음부터 검색
}
}
먼저 30 크기의 char형 배열 a를 선언하고 문자열을 저장한다. 그리고 포인터 p를 선언하는데 p에는 o로 시작하는 문자열을 strchr로 검색한 후 포인터를 반환한다. 그리고 p가 NULL이 아닐때 까지(검색되면) 반복을 하면서 검색된 문자열을 출력한 후 p + 1 위치를 기준으로 o로 시작하는 문자열을 검색하고 포인터를 반환한다.
o로 시작하는 문자열들이 모두 출력된 것을 볼 수 있다.
#include <stdio.h>
#include <string.h> // strchr 함수가 선언된 헤더 파일
int main()
{
char s1[30] = "A Garden Diary"; // 크기가 30인 char형 배열을 선언하고 문자열 할당
char *ptr = strchr(s1, 'a'); // 'a'로 시작하는 문자열 검색, 포인터 반환
while (ptr != NULL) // 검색된 문자열이 없을 때까지 반복
{
printf("%s\n", ptr); // 검색된 문자열 출력
ptr = strchr(ptr + 1, 'a'); // 포인터에 1을 더하여 a 다음부터 검색
}
return 0;
}
위 사진은 c언어 코딩도장에 나와 있는 위 코드를 사진으로 나타낸 것이다. 처음에는 strchr가 이해가 안되서 좀 해맸지만 위 사진을 보고 단박에 이해해서 사진을 첨부한 것이다. 참고하면 좋을 것 같다.
-strrchr
strrchr은 strchr과 비슷하게 문자를 검색해서 문자열을 반환하지만 strrchr 함수는 strchr과 다르게 문자열의 끝에서(오른쪽 right)부터 문자를 검색한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char a[30] = "origin, AoS, orgarn";
char *p = strrchr(a, 'o'); // 오른쪽부터 o로 시작하는 문자열 검색
printf("%s", p);
}
strrchr를 써서 a에 저장된 문자열의 끝부터 문자열을 검색하도록 했다.
오른쪽 부터 검색이기 때문에 origin이 아닌 orgarn이 출력되는 것을 볼 수 있다.
-strstr-
strchr이 문자를 검색하는 함수였다면 strstr은 문자열을 검색하고 포인터를 반환하는 함수다.
사용은 strstr(<대상 문자열>, <검색할 문자열>);로 하면 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char a[30] = "origin, AoS, orgarn";
char *p = strstr(a, "or"); // or로 시작하는 문자열 검색, 포인터 반환
printf("%s\n", p);
}
strstr 함수로 or 문자열로 시작하는 문자열을 검색하는 코드다.
시작 단어부터 or로 시작하기 때문에 모든 문자열이 출력됐다.
Unit 42 ~ Unit 44 문제
NULL 포함 6 크기의 배열이 필요하다.
답 : b
널은 문자열을 연결 했을 때, 맨 끝에만 붙기 때문에 널 포함 11바이트다.
답 : 11
strcpy 함수가 선언된 헤더 파일은 string.h다.
답 : c
s1에 저장된 문자열을 s2에 복사하는 것이 목적이므로 빈 칸에 strcpy 함수를 사용하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char *s1 = "C Language";
char s2[20];
strcpy(s2, s1); // s1의 문자열을 s2에 복사
printf("%s\n", s2);
return 0;
}
s1의 문자열을 포인터 s2에 복사하는 것이 목적이다. 일반 포인터는 쓰기가 불가능하기 때문에 malloc으로 동적할당 한 후 strcpy로 s1의 문자열을 동적할당된 s2에 복사하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *s1 = "The Little Prince";
char *s2 = malloc(sizeof(char)*20); // 넉넉하게 20만큼 동적 할당
strcpy(s2, s1); // s1의 문자열을 s2에 복사
printf("%s\n", s2);
free(s2);
return 0;
}
s1 문자열을 s2에 붙이는 것이 목적이므로 strcat 함수를 이용하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char s1[20] = " 9th Symphony";
char s2[40] = "Beethoven";
strcat(s2,s1); // s1의 문자열을 s2에 붙임
printf("%s\n", s2);
return 0;
}
동적할당된 s2에 s1을 붙여서 Alice in Wonderland 문자열을 만들어야하므로 먼저 strcpy로 s2에 Alice in 문자열을 복사한 후 s1의 문자열을 strcat로 s2에 연결하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *s1 = " Wonderland";
char *s2 = malloc(sizeof(char) * 30);
strcpy(s2, "Alice in "); // Alice in 문자열을 s2에 복사
strcat(s2, s1); // s1의 문자열을 s2 끝 부분에 연결
printf("%s\n", s2);
free(s2);
return 0;
}
s1, s2 모두 입력된 문자열을 저장해야하니 둘 중 한 변수가 입력된 문자열을 저장하고, 나머지 변수는 문자열을 저장한 변수의 문자열을 strcpy 함수로 복사하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char s1[31];
char s2[31];
scanf("%s", s1); // 입력된 문자열을 s1에 저장
strcpy(s2, s1); // s1에 저장된 문자열을 s2로 복사
printf("%s\n", s1);
printf("%s\n", s2);
return 0;
}
scanf로 입력 받은 문자열을 먼저 s1에 저장하고 strcpy 함수로 s1에 저장된 문자열을 s2로 복사했다.
입력된 문자열 뒤에 "th"를 붙여서 출력하는 것이 목적이다. scanf로 s1에 입력된 문자열을 저장하고 strcat로 "th"를 s1 뒤에 연결하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char s1[40];
scanf("%s", s1); // s1에 입력된 문자열 저장
strcat(s1, "th"); // s1 문자열 뒤에 "th"를 연결
printf("%s\n", s1);
return 0;
}
scanf로 s1에 입력된 문자열을 저장하고 strcat로 s1의 문자열 뒷 부분에 th를 연결해서 저장했다.
a : 만들어진 문자열을 저장할 변수는 맨 앞에 있어야 한다. X
b : 만들어진 문자열을 저장할 변수가 없다. X
c : 만들어진 문자열을 저장할 변수는 맨 앞에 있어야 한다. X
e : 만들어진 문자열을 저장할 변수는 맨 앞에 있어야 한다. X
답 : d
'a'는 %c, 10은 %d 서식 지정자를 사용하면 된다.
답 : "%c %d"
sprintf 함수로 문자열을 생성할 때 사용하는 배열이나 메모리 공간은 버퍼(buffer)라고 부른다.
답 : 버퍼
sprintf의 서식 지정자에 들어갈 값을 넣어서 9th Symphony가 출력되게 하는 것이 목적이다. %d에는 9, %s는 Symphony가 들어가면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char s1[20];
sprintf(s1, "%dth %s", 9, "Symphony"); // 지정 서식에 맞게 9, "Symphony"를 넣어줌
printf("%s\n", s1);
return 0;
}
sprintf로 10 20 30 c 99 문자열을 만들어 s1에 저장하는 것이 목적인데, 서식 지정자 부분만 빼고 다 주어져 있다. 10, 20, 30, 99는 정수이므로 %d, 'c'는 문자이므로 %c 서식 지정자를 써주면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char s1[20];
sprintf(s1, "%d %d %d %c %d", 10, 20, 30, 'c', 99);
printf("%s\n", s1);
return 0;
}
1~7 범위의 숫자와 길이 30 이하의 문자열이 입력되는데, 입력된 숫자를 바탕으로 1이면 1st, 2면 2nd 식의 서수와 입력된 문자열을 출력하게 만드는 것이 목적이다. 1,2,3을 제외한 다른 숫자들은 모두 th이므로 1, 2, 3일 경우만 조건문으로 st, nd 등을 strcat으로 연결해 주면 될 것 같다. 나머지는 strcat으로 th를 연결하면 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int number;
char name[31], result[40];
scanf("%d %s", &number, name); // 숫자, 문자열을 입력 받음
char *tmp = malloc(sizeof(char) * 3); // st, nd, th 등을 담을 임시 문자열 변수 동적 할당
if (number < 4) // 입력 숫자가 4보다 작을 경우
{
if (number == 1) // 입력 숫자가 1일 경우
tmp = "st"; // tmp에 st를 저장
else
tmp = number == 2 ? "nd" : "rd";
// 입력 숫자가 2면 tmp에 nd를 입력 숫자가 3이면 tmp에 rd를 저장
}
else
tmp = "th"; // tmp에 th를 저장
sprintf(result, "%d%s %s", number, tmp, name);
// result에 서식 지정자로 만들어진 문자열 저장
printf("%s\n", result);
return 0;
}
먼저 숫자와 문자열을 scanf로 입력 받는다. 임시 변수 tmp를 선언해 3byte의 메모리 할당(서수 줄임말에 붙는 문자열은 모두 2글자이므로..)을 한다. 입력 받은 숫자가 4보다 작으면 서수 줄임말 문자열이 "th"가 아니라는 뜻이므로 따로 조건식을 작성해 st, nd, rd중 무엇을 tmp에 넣어줄지를 결정한다. 만약 4보다 크다면 th가 붙으므로 tmp에 "th"를 저장한다.
끝으로 sprintf로 result에 %d%s %s 형식으로 입력한 숫자, tmp의 문자열, name로 문자열을 만들어 저장하도록 작성했다.
문자열 안에서 문자로 검색하는 함수는 strchr, strrchr이 있다.
답 : c, e
a : 검색할 문자열을 strstr의 첫 인자로 줘야한다. X
c : ptr은 char 포인터 형으로 선언해야한다. X
d : s1은 문자 배열, ptr은 메모리 주소 포인터다. X
e : ptr을 포인터형으로 선언해야한다. X
답 : b
문자열 안에서 문자를 검색해서 반환된 포인터부터의 문자열을 출력하는 원리다. 1번 칸에는 포인터를 선언하고 strchr로 문자를 검색해서 포인터를 반환 받고, 2번 칸에는 while문을 작성해 포인터가 NULL일 때 까지(더 이상 검색이 되지 않을 때 까지) 반복하도록 한다. 3번 칸에는 strchr을 한번 더 작성해 p+1의 문자열에서 n으로 시작하는 단어를 찾아 주소를 포인터 변수에 반환하게하면 될 것 같다.
#include <stdio.h>
#include <string.h>
int main()
{
char s1[30] = "Alice in Wonderland";
char *ptr = strchr(s1, 'n'); // s1 문자열에서 n인 문자의 주소를 반환
while (ptr != NULL) // 더 이상 n으로 시작하는 문자열의 주소가 없을 때까지
{
printf("%s\n", ptr);
ptr = strchr(ptr + 1, 'n'); // ptr+1 주소부터 n인 문자의 주소를 반환
}
return 0;
}
오른쪽 부터 문자를 검색하는 것이 목적이므로 strrchr 함수를 사용하면 될 것 같다.
#include <stdio.h>
#include <string.h>
int main()
{
char s1[30] = "The Little Prince";
char *ptr = strrchr(s1, 'i');
printf("%s\n", ptr);
return 0;
}
길이가 1000 이하인 문자열이 입력되면 그 문자열에 존재하는 공백의 개수를 출력하는 것이 목적이다. while로 반복하며 strchr로 공백을 검색하고 count를 해서 출력하면 될 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char a[1001]; // 1001 크기의 문자열 배열 변수 선언
scanf("%[^\n]s", a); // 공백을 포함해서 a에 입력된 문자열을 저장
char *p = strchr(a, ' '); // a의 문자열에서 공백을 검색해서 해당 메모리 주소를 포인터 p에 저장
int count = 0; // 공백의 수를 count할 count 변수 선언
while (p != NULL) // 공백이 더 이상 없을때 까지
{
count += 1; // count +1
p = strchr(p + 1, ' '); // p+1 위치부터 공백을 검색해서 해당 메모리 주소를 포인터 p에 저장
}
printf("%d", count); // count를 출력
}
NULL 포함 1001 크기의 문자열 배열 변수를 선언하고 scanf와 %[^\n]s로 입력된 문자열을 공백 포함으로 a에 저장한다. strchr로 a의 문자열에서 공백을 찾고 그 주소를 포인터 변수 p에 저장한다. 마지막으로 공백 수를 count할 count 변수를 선언하고 while문으로 반복을 한다.
while의 조건은 p != NULL, 즉 공백이 더 이상 없을때 까지 반복하는 것으로 매 반복마다 count를 +1해주고 p+1 위치부터 공백을 검색해서 해당 메모리 주소를 다시 포인터 p에 저장한다.
위 반복이 다 끝난 후 공백의 수만큼 +1된 count 수를 출력하도록 작성했다.
'Old (2021.01 ~ 2021.12) > Programming' 카테고리의 다른 글
c언어 코딩도장 Unit 48 ~ Unit 50 (0) | 2021.03.13 |
---|---|
c언어 코딩도장 Unit 45 ~ Unit 47 (0) | 2021.03.13 |
c언어 코딩도장 Unit 39 ~ Unit 41 (0) | 2021.03.13 |
c언어 코딩도장 Unit 36 ~ Unit 38 (0) | 2021.03.06 |
c언어 코딩도장 Unit 34 ~ Unit 35 (0) | 2021.03.01 |