PS/백준

[백준/Baekjoon]<1152번> 단어의 개수 [C/C++/Python][Class 1]

DigIT_JHB 2022. 9. 12. 15:30

 

 

문제

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


입력

첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 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

#문제 풀이 방법

1. 문자열이 입력되고, 문자열에 속한 단어의 개수를 출력한다.(단어는 공백으로 구분되고 중복될 수 있다.)

2. 문자열을 공백에 따라 구분하고, 개수를 파악하여 출력한다. 앞의 공백과 뒤의 공백, 개행문자는 제외시킨다.

→C/C++의 경우에는 strtok 함수를 이용하여 개수를 파악한다.(추가적인 방법도 있다.)

→Python의 경우에는 split()함수를 이용하여 개수를 파악한다.

 

반응형

 

#C/C++

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
  char str[1000000];
  scanf("%[^\n]",str);
  int a=0;
  char *ptr=strtok(str," ");
  while (ptr != NULL)              //ptr이 NULL일때까지 (= strtok 함수가 NULL을 반환할때까지)
	{
    ptr = strtok(NULL, " ");     //자른 문자 다음부터 구분자 또 찾기
    a++;
	}
    printf("%d\n",a);
    return 0;    
}

cf.

C의 경우에는 공백이 포함된 문자열을 입력받기 위해서는 주의해야하는데

gets함수의 경우 백준에서 사용할 수 없다.

나도 처음에 gets를 사용했다가 컴파일 에러가 뜨길래 당황했는데 찾아보니 

"gets는 C에서 오래 전부터 deprecated 였으며, C++에서는 removed된지 오래입니다." 라고 한다.

(https://www.acmicpc.net/board/view/63336)

 

cf.

fgets를 이용해서 풀어보려고 해봤는데 계속해서 틀렸다고 나왔다. 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char str[1000001];
    fgets(str, sizeof(str), stdin);
    int a=0;
    char *ptr=strtok(str," ");   
	while (ptr != NULL)              //ptr이 NULL일때까지 (= strtok 함수가 NULL을 반환할때까지)
	{
     ptr = strtok(NULL, " ");     //자른 문자 다음부터 구분자 또 찾기
     a++;
	}
    printf("%d\n",a); 
    return 0;
    
}

 

 c언어의 입력 함수들을 살펴보면 

  • scanf함수는 공백문자(or 개행문자) 전까지 읽어드리고 마지막에 \0을 붙인다.
  • gets는 개행문자까지 읽어드리고, 개행문자를 \0으로 바꾼다.
  • fgets는 개행문자까지 읽어드리고, 그 뒤에 \0을 붙인다.

따라서 '\n'가 단어로 추가될 수 있기 때문에 다음과 같이 개행문자를 널문자로 바꿔주는 작업을 해야한다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char str[1000001];
    fgets(str, sizeof(str), stdin);
    str[strlen(str)-1]='\0';
    int a=0;
    char *ptr=strtok(str," ");   
	while (ptr != NULL)              //ptr이 NULL일때까지 (= strtok 함수가 NULL을 반환할때까지)
	{
     ptr = strtok(NULL, " ");     //자른 문자 다음부터 구분자 또 찾기
     a++;
	}
    printf("%d",a); 
    return 0;
    
}

cf.

 C++의 경우에는 Java나 Python처럼 간편하게 split()을 이용하여 풀 수가 없고

위와 같이 string헤더파일에 있는 strtok을 이용해야 한다.

추가적으로 다른 방법이 있나 살펴보았는데  getline 함수를 사용할 수 있었다.

1.cin.getline()함수(istream 클래스의 멤버함수로서의 getline : std::istream::getline)

(https://cplusplus.com/reference/istream/istream/getline/)

istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
    int a=0;
    char str[1000002];//문자열의 길이가 100만이고 개행문자가 포함가능, 널문자까지 포함되므로 1000002이어야 한다!
    while(cin.getline(str,sizeof(str),' '))
    {             
        if(strcmp(str,"")==0||strcmp(str,"\n")==0)
        {
            continue;
        }      
        a++;
    }
    cout<<a;
    return 0;    
}

2.getline함수 (std namespace의 일반함수:std::getline)

(https://cplusplus.com/reference/string/string/getline/?kw=getline)

istream& getline (istream&  is, string& str, char delim);
//Extracts characters from is and stores them into str 
//until the delimitation character delim is found

2번의 경우, 보다시피 매개변수로 istream객체를 받는다. 

cin은 istream클래스의 객체이므로 이것을 사용할 수 있을 것이다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
    int a=0;
    string s;
    while(getline(cin,s,' '))
    {        
        if(s.size()==0||s.compare("\n")==0)
        {           
            continue;
        }      
        a++;
    }
    cout<<a;
    return 0;
    
}

cf.

생각해보니 C++의 cin을 쓰면 훨씬 더 간결하게 표현이 가능했다......

cin은 공백과 개행을 무시한다.(개행의 경우 버퍼에 남겨둔다.)

따라서 다음과 같이 쓸 수 있다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
    int a=0;
    string s;
    while(cin>>s)
    {          
        a++;
    }
    cout<<a;
    return 0;    
}

 

 

#Python

S=input()
print(len(S.split()))
반응형