[C] 백준 2908번 : 상수 (공백 포함해 scanf 받기, strtok 함수)

bokyungkim·2021년 8월 26일
0

https://www.acmicpc.net/problem/2908

C언어로 문자열 다루기는 정말 까다롭다.
출제 의도를 따르면 문자열로 푸는 것이 맞다. 그래서 당연히 나는 문자열로 풀었다.
그런데 다 풀고 검색해보니 그냥 정수로 푼 사람들도 많았다. 하지만 후회하지 않아!

풀이

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int change_n_convert(char s[])
{
	char tmp;
	int ret;

	tmp = s[2];
	s[2] = s[0];
	s[0] = tmp;
	ret = atoi(s);
	return (ret);
}

int main(void)
{
	char s[7] = {
		0,
	};
	int a = 0;
	int b = 0;

	scanf("%[^\n]s", s);
	char *ptr = strtok(s, " ");
	while (ptr != NULL)
	{
		if (a == 0)
			a = change_n_convert(ptr);
		else
			b = change_n_convert(ptr);
		ptr = strtok(NULL, " ");
	}
	if (a > b)
		printf("%d", a);
	else
		printf("%d", b);
	return (0);
}

흐름 설명

  1. s에 공백을 포함한 문자열을 한 번에 scanf로 받고
  2. strtok 함수를 이용해 문자열을 공백 기준으로 자른다.
  3. 자르는 과정에서 a에 아무 값이 안 들어와있다면 change_n_convert 함수로 들어가 첫번째 수와 마지막 수의 자리를 바꾸고, atoi 함수를 이용해 문자열을 정수로 반환한 후 그 값을 리턴한다.
  4. a0이 아니라면 b만 비어있을 것이기에 b에 동일하게 change_n_convert 함수를 적용해준다.
  5. ab보다 크면 a를, 아니면 b를 출력해준다.

알게 된 것

공백을 포함해 scanf 받는 법

scanf 함수의 형식 지정자를 보면 []를 사용하여 입력된 정보를 구분하는 기준 문자를 변경할 수 있다. 예를 들어, 입력된 정보를 공백 문자나 탭 문자 또는 줄바꿈 문자가 아닌 a로 구분하고 싶다면 아래와 같이 사용하면 된다. 즉, ^문자 뒤에 자신이 입력 값을 구분할 때 사용할 문자를 적어주면 된다.

scanf("%[^a]s", str); // 사용자가 입력한 값을 'a' 문자로 구분한다.

풀이에서 나는 공백을 그대로 읽기 원했기 때문에 문제에서 주어지는 입력에 따라 개행 문자를 입력된 정보를 구분하는 기준 문자로 설정해줬다.

scanf("%[^\n]s", s); // 풀이에서 내가 사용한 방식

strtok 함수

string.h 헤더 파일에 선언되어 있는 함수로, 특정 문자를 기준으로 문자열을 잘라주는 함수이다.

char *strtok(char *_String, char const *_Delimiter);

자른 문자열을 반환하고, 더 이상 자를 문자열이 없으면 NULL을 반환한다.

strtok 함수는 지정된 문자를 기준으로 문자열을 자른다. 즉, strtok(s1, " ");와 같이 " "(공백 문자)를 넣어주면 공백으로 구분하여 문자열을 자른다 (단, 기준 문자를 ' '로 묶으면 안 된다). 특히 strtok 함수는 잘린 문자열을 한 번에 얻을 수 없어서 while 반복문으로 문자열을 계속 자르다가 문자열이 나오지 않으면 반복문을 끝내는 방식으로 사용한다.

char *ptr = strtok(s1, " ");      // " " 공백 문자를 기준으로 문자열을 자름, 포인터 반환

while (ptr != NULL)               // 자른 문자열이 나오지 않을 때까지 반복
{
    printf("%s\n", ptr);          // 자른 문자열 출력
    ptr = strtok(NULL, " ");      // 다음 문자열을 잘라서 포인터를 반환
}

여기서 포인트는 처음에 문자열을 자르고 다음으로 넘어갈 때는 strtok의 첫 번째 인자로 NULL을 줘야한다는 것이다. 이 이유는 strtok의 작동 원리에 있다. strtok자를 문자열 부분에 NULL을 넣어준다. 그러므로 첫 인자에 NULL을 넣어줘야 직전 strtok 함수에서 처리했던 문자열에서 잘린 문자열만큼 다음 문자로 이동한 뒤 다음 문자열을 자를 수 있는 것이다. 그렇게 처음에만 문자열을 첫 인자로 받고 이후에는 NULL을 받다가, 문자열의 끝을 만나게 되면 그만 잘라야하기 때문에 while문의 조건을 ptr != NULL 로 걸어준다.

strtok를 사용하면서 주의할 점

문자열을 새로 생성해서 반환하는 것이 아니라 원본 문자열의 내용을 바꾸기 때문에 조심하기!




📚 참고
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=tipsware&logNo=221261284797
https://dojang.io/mod/page/view.php?id=376

0개의 댓글