반응형

Open Challenge> 아래< 5-1>을 참고하여 영문 텍스트, 숫자, 몇 개의 특수 문자로 구성되는 텍스트를 모스 부호로 변환하는 프로그램을 작성하라. 모스 부호는 전보를 쳐서 통신하는 시절에 사용된 유명한 코딩 시스템이다. 각 모스 코드들은 하나의 빈칸으로 분리되고, 영문 한 워드가 모스 워드로 변환되면 워드들은 3개의 빈칸으로 분리된다. 실행 예는 다음과 같다. 영문 텍스트를 입력받아 모스 부호로 변환하여 출력하고, 변환이 잘 되었는지 확인하기 위해 다시 모스 부호를 영문 텍스트로 변환하여 원문을 출력한 사례이다.


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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <iostream>
#include <algorithm>
#include <string>
 
using namespace std;
 
class Morse{
private:
    string alphabet[26]; //알파벳의 모스 부호 저장
    string digit[10]; //숫자의 모스 부호 저장
    string slash, question, comma, period, plus, equal; //특수 문자의 모스 부호 저장
public:
    Morse(); //alphabet[], digit[] 배열 및 특수 문자의 모스 부호 초기화
    void text2Morse(string text, string& morse); //영문 텍스트를 모스 부호로 변환
    bool morse2Text(string morse, string& text); //모스 부호를 영문텍스트로 변환
};
Morse::Morse(){
    string Malphabet[26]=".-""-...""-.-.""-.."".","..-.""--.""...."".."".---",
                   "-.-"".-..""--""-.""---",".--.""--.-"".-.""...""-",
                   "..-""...-"".--""-..-""-.--""--.."};
    string Mdigit[10]={"-----"".----""..---""...--""....-"".....""-....""--...""---..""----." };
    slash= "-..-.";    question= "..--..";    comma= "--..--";
    period= ".-.-.-";  plus= ".-.-.";     equal= "-...-"//모스 특수문자 초기화
    int i;
    for(i=0;i<26;i++){alphabet[i]=Malphabet[i];} //모스 알파벳 초기화
    for(i=0;i<10;i++){digit[i]=Mdigit[i];} //모스 숫자 초기화
}
void Morse::text2Morse(string text, string& morse){
    transform(text.begin(),text.end(),text.begin(),tolower); // 입력한 문자열을 전부 소문자로 바꾼다.
    for(int i=0;i<text.length();i++){
        if(text[i]>=97&&text[i]<=122){morse=morse+alphabet[text[i]-97]+" ";} //해당 인덱스가 알파벳일 경우 해당 모스 부호 삽입
        else if(text[i]==' '){morse+="   ";} //해당 인덱스가 공백문자 일경우 공백문자 3개 입력
        else if(text[i]>=48&&text[i]<=57){morse=morse+digit[text[i]-48]+" ";} //해당 인덱스가 숫자 일경우 해당 모스 부호 삽입
        else if(text[i]=='/'){morse=morse+slash+" ";}
        else if(text[i]=='?'){morse=morse+question+" ";}
        else if(text[i]==','){morse=morse+comma+" ";}
        else if(text[i]=='.'){morse=morse+period+" ";}
        else if(text[i]=='+'){morse=morse+plus+" ";}
        else if(text[i]=='='){morse=morse+equal+" ";} //해당 인덱스가 특수문자 일경우 해당 모스 부호 삽입
    }
}
bool Morse::morse2Text(string morse, string& text){
    string regen; //다시 읽을 수 있게 복원한 것을 넣을 스트링
    string sub; // 공백 문자 단위로 자름
    int i;
    int startindex=0//문자를 찾기 시작할 첫번째 index
    int blankindex=-1//공백문자의 index
    int swch=1//모스부호가 무엇인지 검사하는데 사용할 플래그
    while(1){
        swch=1//플래그는 루프 돌때마다 1로 ON
        startindex=blankindex+1//찾기 시작할 인덱스는 공백 인덱스 더하기 1
        blankindex=morse.find(" ",blankindex+1); //전에 찾았던 것을 또 찾으면 안되니 더하기 1을해서 공백문자를 찾는다.
        sub=morse.substr(startindex,blankindex-startindex); // 공백 문자를 제외한 무언가를 나타내는 모스부호 부분만 자른다.
        for(i=0;i<26;i++){
            if(alphabet[i]==sub)
                {regen+=(char)(97+i);
            swch=0;break;}    //알파벳일 경우 변환하여 regen에 더하고 플래그 OFF 후 루프 탈출
        }
        if(swch==1){
            for(i=0;i<10;i++){
                if(digit[i]==sub)
                {regen+=(char)(48+i);
                swch=0;break;}
            } //숫자일 경우 변환하여 regen에 더하고 플래그 OFF 후 루프 탈출
        }
        if(swch==1){
            if(sub==slash){regen+="/";}
            else if(sub==question){regen+="?";}
            else if(sub==comma){regen+=",";}
            else if(sub==period){regen+=".";}
            else if(sub==plus){regen+="+";}
            else if(sub==equal){regen+="=";}
        } //특수문자일 경우 regen에 더한다. 
 
        if(blankindex==morse.length()-1){break;} //여기서 검사하는 이유는 인덱스가 맨 마지막일때 +1,+2,+3 을 검사하면 오류가 나기 때문이다.
        if((morse[blankindex+1]==' ')&&(morse[blankindex+2]==' ')&&(morse[blankindex+3]==' ')){
            regen+=" ";     cout<<regen<<endl//제대로 이어졌나 확인.
            blankindex+=3//공백문자가 연달아 3개 있으면 실제에서는 공백문자 하나를 뜻한다. 이를 검사하기 위함.
        }
        }
    if(regen==text) return true//새로 만든 문자열과 원래 문자열이 같으면 true리턴
    else return false//아니면 false 리턴
}
int main(void){
    Morse m;
    string english;
    string morse;
    cout<<"아래에 영문 텍스트를 입력하세요. 모스 부호로 바꿉니다."<<endl;
    getline(cin,english,'\n'); //개행문자 나올 때까지 문자열 받는다
    m.text2Morse(english,morse); //모스부호로 전환
    cout<<morse<<endl;
    cout<<"모스 부호를 다시 영문 텍스트로 바꿉니다."<<endl;
    if(m.morse2Text(morse,english)) //다시 읽을 수 있는 텍스트로 전환
        cout<<english<<endl//만약 같으면 원래 문자열 출력
    else
        cout<<"오류 발생"<<endl//다르면 오류발생 출력
    return 0;
}
 
cs




반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C++' 카테고리의 다른 글

virtual 함수  (0) 2017.11.23
operator overloading  (0) 2017.11.14
Book 클래스  (1) 2017.11.09
Accumulator 클래스  (0) 2017.11.09
MyIntStack 클래스  (0) 2017.11.09
반응형

4.9> 다음은 이름과 반지름을 속성으로 가진 Circle 클래스와 이들을 배열로 관리하는 CircleManager 클래스이다. 키보드에서 원의 개수를 입력받고, 그 개수만큼 원의 이름과 반지름을 입력받고, 다음과 같이 실행되도록 main() 함수를 작성하라. Circle, CircleManager 클래스도 완성하라.


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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <string>
 
using namespace std;
 
class Circle{ 
private:
    int radius;
    string name;
public:
    void setCircle(string name, int radius){ //멤버 name과 radius를 set해줌.
        this->name=name; this->radius=radius;
    }
    double getArea(){return radius*radius*3.14;} //원의 면적 리턴
    string getName(){return name;} //원의 이름 리턴
};
 
class CircleManager{
private:
    Circle *p; //Circle형 포인터 p
    int size;
public:
 
    CircleManager(int size){ //컨스트럭터
        this->size=size
        p=new Circle[size]; //size크기만큼의 Circle형 동적 객체 배열 생성
        int radius; string name;
        for(int i=0;i<size;i++){
            cin.ignore(100,'\n'); //cin은 개행문자를 버퍼에 남겨놓기 때문에 버퍼에서 비워줘야 한다.
                                //그렇지 않으면 다음 루프의 getline이 개행문자 + 입력한 문자열을 받아버린다.
            cout<<"원 "<<i+1<<"의 이름과 반지름 >>";
            getline(cin,name,' '); // space를 delimeter로 설정하여 이름을 받는다.
            cin>>radius;     //radius는 cin으로 받는다.
            p[i].setCircle(name,radius); //Circle을 set 해줌.
        }
    cin.ignore(); //마지막 개행문자 버퍼에서 제거
    }
    ~CircleManager(){delete []p;} //동적 Circle 객체 배열 해당 메모리 힙으로 반환
    void searchByName(){
        string cmp;
        cout<<"검색하고자 하는 원의 이름>> ";
        getline(cin,cmp,'\n'); //cmp를 getline으로 개행문자 나올때까지 받는다.
        for(int i=0;i<(this->size);i++){
            if(cmp==(p[i].getName()))  //cmp와 i번째 동적circle의 name이 같으면
            {cout<<"도넛의 면적은 "<<p[i].getArea()<<endl//i번째 동적circle의 area 반환
            break;}
        }
    }
    void searchByArea(){
        int area;
        cout<<"최소 면적을 정수로 입력하세요>> ";
        cin>>area; //area를 받는다.
        cout<<area<<"보다 큰 원을 검색합니다."<<endl;
        for(int i=0;i<(this->size);i++){ //동적 객체 배열 전부 순회하여 area보다 
            if(p[i].getArea()>area) //p번째 circle 객체의 넓이가 크면 출력
                cout<<p[i].getName()<<"의 면적은 "<<p[i].getArea()<<", ";
        }
        cout<<endl//개행 출력
    }
};
 
int main(void){
    int size;
    cout<<"원의 개수 >> " ; 
    cin>>size//원의 개수 정함
    CircleManager m(size); //CircleManager객체 생성
    m.searchByName(); //Name으로 찾기
    m.searchByArea(); //특정 Area 초과인것 찾기
    
    return 0;
}
 
cs




반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C++' 카테고리의 다른 글

float와 double  (0) 2017.11.05
히스토그램  (0) 2017.11.03
Person, Family 클래스  (0) 2017.11.03
원의 개수와 반지름  (0) 2017.11.03
문자열 문자 랜덤 수정  (0) 2017.11.03
반응형

4.3> string 클래스를 이용하여 사용자가 입력한 영문 한 줄을 입력받고 글자 하나만 랜덤하게 수정하여 출력하는 프로그램을 작성하라.


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
#include <iostream>
#include <cstdlib> //random 사용 위함
#include <ctime> //srand 사용 위함
#include <string> //string 객체 사용 위함
 
using namespace std;
 
int main(void){
    string s; //string 객체 s
    srand((unsigned)time(0)); //시드값 설정
    
    cout<<"아래에 한 줄을 입력하세요.(exit를 입력하면 종료합니다)"<<'\n';
    while(true){ //무한루프
    cout<<">>";
    getline(cin,s,'\n'); //delimeter '\n'으로 한 줄 받아 s에 저장
    if(s=="exit"//s가 exit면 루프 탈출
        break;
    int rand_index=(rand())%(s.length()); //rand_index에 임의 인덱스 저장(s.length로 나눈 나머지는 무조건 0~length-1이 나옴)
    //조심해야 할것은 알파벳만 인덱스에 포함되는 것이 아니라 공백문자, 마침표와 같은 문자도 포함된다.
    int Daeso=rand()%2//글자를 바꾸는데 소문자로 바꿀 것인지 대문자로 바꿀 것인지 랜덤으로 정한다.
    if(Daeso==0//대문자로 정해짐
    s[rand_index]=(char)((rand()%26)+65); //아스키코드 65~90 대문자 알파벳
    else if(Daeso==1//소문자로 정해짐
    s[rand_index]=(char)((rand()%26)+97); //아스키코드 97~122 소문자 알파벳
    cout<<s<<endl//s출력
    }
    return 0;
}
 
cs



반응형
반응형

fgets 함수는 개행문자가 (\n) 나올 때까지 문자열을 받아준다.

그런데 중요한 것은 예를들어 Hi World 를 입력하고 엔터를 쳤다고 치면

Hi World\0 이아니라

Hi World\n\0 이 받아진다는 것이다. 이것을 잘 알아야 한다.



\n : 개행문자

\0 : 문자열의 긑을 나타냄 (null 문자)


char *fgets(char *str, int num, FILE *stream);


스트림에서 문자열을 받아서 num-1 개의 문자를 입력 받을 때 까지나 개행 문자(\n) 나 파일의 끝(EOF)에 도달할 때 까지

입력 받아 문자열로 저장한다.

NULL문자는 자동으로 문자 뒤에 붙기 때문에 num-1 개의 문자이다.

마지막에 치는 엔터는 \n 의 형태로 문자열에 포함된다 주의!!


예제 ( 내가만든 것임)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
    FILE *fp=NULL;
    char a[5];
    fp=fopen("4.txt","r");
    while(1)
    {
    if(feof(fp)!=0)
        break;
    fgets(a,sizeof(a),fp);
    printf("%s\n",a);
    }
    return 0;
}
cs

배열 a의 크기가 5이기 때문에 실제로 \0을 제외하면 4개의 문자가 들어갈 수 있다.

아래 텍스트 파일을 실제로 나타내보면

abcdefgh\nidonthave\nhave\nfuckyoumuc 이다.

따라서

abcd\0efgh\0\n\0idon\0thav\0e\n\0have\0\n\0fuck\0youm\0uc\0

가 되고 printf 자체에도 개행문자를 넣어줬기 때문에


다음과 같은 결과가 나오는 것이다.


마지막 줄에 개행문자가 왜 없냐면 파일 포인터가 아랫줄로 내려가지 않았기 때문이다...


반응형

'컴퓨터 & 프로그래밍 & 전자공학 > C언어' 카테고리의 다른 글

성적 평균 구하기  (0) 2017.02.12
텍스트 파일 비교  (0) 2017.02.11
파일 복사  (0) 2017.01.31
대문자로 변경  (0) 2017.01.31
텍스트 파일 비교  (0) 2017.01.31

+ Recent posts