본문 바로가기

건승하고있어요/알고리즘

[1차원배열] 단어의 개수 찾기

반응형

내가 집중할 것은 코드를 가장 짧게 짜려는 것보다 어떤 순서로 어떤 이유로 이걸 짰는지 알면서 짜는게 제일 중요할 것 같당. 하다보면 여러 방법도 생기고 점차 코드도 줄겠지!!! 논리적으로 생각하자 논리적으로 생각하자 바보 말고 논리

이클립스에서는 답 나오는데 제출만 하면 런타임오류든 틀렸습니다든 다 실패해서 뭘 쓸 수가 없다. 뭐가 틀렸는지 알아야 말이지... 디버깅이란 말을 하는거 자체가 웃기지만 참 코드 한 줄 한 줄 보면서 이거일까, 이거일까 하고 고치는 데도 한계가 있는 것 같다.

아는게 별로 없으니 뭐가 틀린지 아는 것도 넘나 어려운거 ... 뭐 암튼 하다 만 문제들 빨리 맞았습니다 받고싶다. 유유

문제: 영어 대소문자와 띄어쓰기만으로 이루어진 문장이 주어진다. 이 문장에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오.
        문장의 길이는 1,000,000을 넘지 않는다. 단어는 띄어쓰기 한 개로 구분된다. 
(출처:https://www.acmicpc.net/problem/1152)

아오.
ㅋㅋㅋㅋㅋ
이거 하나 하면 저게 안 되고 저거 하나 하면 쩌거 안 되고 코딩할라믄 꼼꼼해야 한다더니 진짜 여러모로 으아으아으아 ㅋㅋㅋㅋㅋㅋㅋㅋ

입력받을 때 조건이 영어 대소문자 혹은 숫자만 받기 이런 경우가 되게 많은 것 같다. 그래서 그런 메소드를 아예 정형화 해 놓은 경우도 많았다. 역시 이번에도 아스키코드가 빠질 수 없었다. char를 다룰 때는 아스키코드를 빼놓고 얘기할 수가 없는 것 같다. 

순서순서를 밟아서 계획을 세우는 과정이 필요했는데, 처음엔 이정도만 짜면 되겠지 하고 시작을 했다. 
    1) 문장의 길이 1,000,000 안넘기기
    2) 문장 받아서 글자 하나하나 알파벳인지 공백인지 구분하기
    3) 문장의 단어가 몇 개인지 확인하기

1)의 경우,
매번 하듯 while문으로 돌렸는데 계속 런타임 오류가 나서 지워버렸더니 그냥 넘어갔다. -.,- 아니 백자 넘기지 말래서 굳이 예외처리 했더니 안하니까 맞았대냐.. 이유가 뭐냐... 그거 지우기까지 시간 오래 걸렸다 ㅠㅠㅠㅠㅠㅠ 이게 문제인줄 몰라서

2) 문장 받아서 알파벳인지 구분하기,
문장이라는 것 자체가 단어들의 나열이기 때문에 당연히 공백이 들어있고 알파벳이 들어있겠지. 하지만 특수문자가 들어갔는지, 아닌지를 확인하려면 하나씩 구분해야하지 않을까 하는 생각밖에 들지 않았다.ㅠ_ㅠ 그래서 또 문장을 char로 다 나눠서 한글자씩 돌렸다.

 char chrinput;
        while(YN) {
            for(int i=0 ; i<N ; i++) {
                chrinput = VOCA.charAt(i);
                if(chrinput >= 0x61 && chrinput <= 0x7A) {
                    YN = false;
                    System.out.println(chrinput);
                } else if(chrinput >= 0x41 && chrinput <= 0x5A) {
                    YN = false;
                    System.out.println(chrinput);
                } else if (chrinput == 0x20) {
                    YN = false;
                    System.out.println("공백");
                } else {
                    System.out.println("알파벳과 띄어쓰기만 가능합니다. 다시 입력해주세요.");
                    VOCA = scan.nextLine();
                }
                
                YN = false;
            }
            
            
        }

string으로 받은 문장을 char로 나눠서 일일이 확인해야 한다는 생각은 했었는데, 이걸 도대체 알파벳인지 아닌지 어케 구분한다는 거지? 하는 생각이 스멀스멀.. 구글에는 없는게 없다. 저번에 char를 int로 출력했을 때 10진수 숫자로 해당 알파벳에 대한  아스키코드가 나왔던 것처럼, 여기서도 아스키코드를 이용해서 이 글자의 범위를 정해주면 되는거였다. 다만, 여기서는 int가 아니기 때문에 10진수가 아니라 16진수를 쓴다. 왜지.. 왜인지는 나도 몰랑... 왜인가여..


보면 알 수 있듯 대문자 A의 16진수는 0x41이고, Z는 0x5A이다. 그래서 범위를 정할 때 [해당문자>=0x41 && 해당문자<=0x5A] 이렇게 지정해주면 [해당문자>=A && 해당문자<=Z]가 되는거당. 그런식으로 소문자의 범위도 정해주고, 공백은 딱히 범위가 없이 고거 하나면 되니까 고걸로 else if문을 하나 더 넣어줬다... 나에게 포문은 저거뿐이라....ㅋㅋㅋㅋㅋㅋ

그렇게 우선 받은 문장에 대한 예외처리를 해주고 , 
3)문장의 단어가 몇 개인지 확인을 해야 하는데 문제에서 주어진 조건은 띄어쓰기를 기준으로 해서 단어를 세라고 했으니 string에 딸린 메소드 split을 활용해서 자르기로 했다. 

 String voca [] = VOCA.split(" ");

배열을 선언해서 잘라야 하는 이유는 공백을 기준으로 자른 단어들을 배열에 넣기 때문이다. 이를테면

Hola me llamo ciel
-----^--^------^---
띄어쓰기를 기준으로 voca[0]=Hola, voca[1]=me, voca[2]=llamo, voca[3]=ciel 이렇게 들어가는거! 

이렇게 해서 System.out.println(voca.length); 로 하면 끝나겠지 했는데... (배열이 몇개인지 세어 주는 숫자출력)
단순히 공백을 여러개를 동시에 넣으면 공백 하나도 배열에 들어가게 되는거다. 공백을 연속으로 넣는 경우를 생각지 못했다. 

그리하여 4) 공백 여러개 들어왔을 때 예외처리 를 해줘야 했다. 

int vocaN = voca.length;
        for(int i=0 ; i<voca.length ; i++) {
            if(voca[i].isEmpty()) {
               vocaN--;
            } else {
                
            }
            System.out.println("voca" + i + ": " + voca[i]);
        }
        System.out.println("총 단어개수: " + vocaN);

위에도 엉망진창으로 생각나는대로, 그때그때 맞게 짜서 뒤죽박죽이지만, 특히 여기는 더 심하다. ㅋㅋㅋㅋㅋㅋ
우선 split으로 자른 배열의 크기를 확인하기 위해 vocaN을 선언해서 그 길이를 변수로 받아놓고, 포문을 짰다. 
처음엔 어떻게 해야 공백을 저장을 안 할까 생각했는데 배열에 아무것도 들어있지 않을 때마다 vocaN에서 1씩 뺐다. 

배열이 공백인지 아닌지 확인할 때는 보이는 것처럼 .isEmpty() 함수를 활용하면 된다. 

암튼 그리하여 

너무 오랜만이다.. 초록색글씨... 빨간색만 보다가...ㅠㅠ


물론 코드의 길이와 방식은 별로 바람직하지 않습니다 .ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.util.Scanner;
 
public class VocaNum {
 
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String VOCA = scan.nextLine();
        boolean YN = true;
        int N = VOCA.length();
        
        
        System.out.println("글자수: " + N);
        //예외처리를 해야해! charAt()으로 하나하나 해야해!
        
        YN = true;
        char chrinput;
        while(YN) {
            for(int i=0 ; i<N ; i++) {
                chrinput = VOCA.charAt(i);
                if(chrinput >= 0x61 && chrinput <= 0x7A) {
                    YN = false;

                } else if(chrinput >= 0x41 && chrinput <= 0x5A) {
                    YN = false;
                    
                } else if (chrinput == 0x20) {
                    YN = false;
                    
                } else {
                    System.out.println("알파벳과 띄어쓰기만 가능합니다. 다시 입력해주세요.");
                    VOCA = scan.nextLine();
                }
                
                YN = false;
            }
            
            
        }
        
        String voca [] = VOCA.split(" ");
        int vocaN = voca.length;
       
        for(int i=0 ; i<voca.length ; i++) {
            if(voca[i].isEmpty()) {
                vocaN--;

            } else {
                

            }
            System.out.println("voca" + i + ": " + voca[i]);
        }
        System.out.println("총 단어개수: " + cnt);
        
        scan.close();
    }
}
 
cs


반응형

'건승하고있어요 > 알고리즘' 카테고리의 다른 글

[문자열사용] 아스키코드  (0) 2018.02.01
[이항계수] 팩토리얼  (0) 2018.02.01
[별찍기] 별찍기4  (2) 2018.01.28
[별찍기] 별찍기3  (0) 2018.01.28
[나누기] A/B 출력하기  (0) 2018.01.28