강의 정리/씨언어 백준

(오답노트) 백준(BOJ) 1152번, scanf("%[^\n]",ptr) - c언어

PurpleGuy101 2022. 2. 5. 18:15

//(주의)비전공 코딩초짜의 오답노트입니다.. 

//문제

단어의 개수 성공

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 128 MB 212257 64264 50610 30.232%

문제

영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.

입력

첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 공백 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열은 공백으로 시작하거나 끝날 수 있다.

출력

첫째 줄에 단어의 개수를 출력한다.

예제 입력 1 복사

The Curious Case of Benjamin Button

예제 출력 1 복사

6

예제 입력 2 복사

 The first character is a blank

예제 출력 2 복사

6

예제 입력 3 복사

The last character is a blank 

예제 출력 3 복사

6

출처

알고리즘 분류

//// 문제점

 

문자의 배열을 선언한뒤 문자열을 입력받기 위해서 가장 처음 배우는 함수는 getchar 일지 모르나

막상 써먹는 것은 scanf(혹은 scanf_s) 였다.

하지만 무작정 scanf를 사용하여 문자열을 입력받는다면 공백인 ' '이나 줄바꿈인 '\n' 단위로 끊어서 받기 때문에 중간에 공백이 있는 문장을 입력하다면 맨 처음 단어만 입력받는 참사가 일어난다.

char a[1000000] = { 0, };

scanf("%s", a);
printf("%s\n", a);
scanf("%s", a);
printf("%s\n", a);

 

라고 입력한 뒤  Ben bought a guitar라고 입력한다면

Ben

bought 만 출력되는 셈.

 

하지만 우리는 문장전체를 한번에 입력받고 싶고 이럴 경우 몇가지 스킬을 통하여 해결할 수 있다.

 

/// 해결책

첫번째 방법은 scanf("%[^\n]",a)를 사용하는 것이다.

굳이 \n이 아니더라도 scanf("%[^e]", a); 이런식으로 다른문자를 넣어도 되며

저 문자 앞까지를 문자열로 받게 해준다.

 

두번째 방법은 gets를 사용하는 것이다.

gets(a); . '\n'을 찾을 때 까지 문자열을 받아주는 함수이다.

대놓고 한줄씩 읽겠다고 만들어준 함수이다.

 

사실 근본있는 학습을 했다면 이 방법으로 접근해야 하였다. 

이녀석은 데이터의 가상전송통로인

표준입력스트림(stdin)을 통하여 입력버퍼에 있는 정보를 받는 함수이며

앞에 f가 붙은 fgets는 stdin이외의 다른 스트림을 지정하여

정보를 받아오는 함수인 것이다.(gets는 fgets에서 만들어진 함수일뿐)

 

마찬가지로 puts함수는 표준출력스트림(stdout)을 통해 모니터 같은 곳으로 출력해주는 함수이며

마지막에는 \n을 추가적으로 입력한다.

최근에는 보안상의 문제로 버퍼오버플로우를 방지한 _s가 붙는 함수들을 쓴다.

여튼 버퍼개념을 더욱 학습할 필요가 있는 함수들이며

문제가 생기면 fflush(stdin) 이나 fflush(stdout)등으로 버퍼를 비워야 할 상황이 오기도 한다.

 

// 여담으로 printf, scanf, gets, puts등에는 반환값이라는 것이 존재한다.

그냥 쓰면 void함수처럼 자기 작업만 수행하지만 

char *ptr = gets(a)를 한다면 문자열a의 주소(a[0] 주소값)을 반환해준다.

제대로 입력이 안되었다면 NULL값을 반환하는것.

 

//// 제출코드

 

#define _CRT_SECURE_NO_WARNINGS

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

int main() {
// 문자열입력
int count;
char a[1000000] = { 0, };
scanf("%[^\n]", a);
int len = strlen(a);

//길이가 0이면 바로종료
if (len == 0) { 
printf("0");
return 0;


//초기값 설정
char previous, present;
if (a[0] == ' ') {
count = 0;
}
else {
count = 1;
}


//Counting
for (int i = 1; i < len; i++) {

present = a[i];
previous= a[i - 1];

if ((present != ' ') && (previous == ' ')) {
count++;
}
}

printf("%d", count);
return 0;
}

 

//

참고자료 : https://blockdmask.tistory.com/343