2017-11-29 13 views
0

메시지의 문자 빈도를 내림차순으로 정렬하는 시저 암호 해독 프로그램을 작성했습니다. 내 문제는 배열의 주파수 위치가 더 이상 내가 설정 한 문자와 일치하지 않는 결과를 인쇄 할 때입니다. 이 문제를 어떻게 해결할 수 있습니까? 구두점과 대문자를 제거하는 다른 코드, 디코딩중인 메시지의 공백과 소문자 이외의 모든 문자가 있습니다.정렬하는 동안 배열의 위치를 ​​어떻게 동일하게 유지할 수 있습니까?

질문을 받고있는 코드를 정리했습니다.

#include<iostream> 
#include<string> 
#include<fstream> 

using namespace std; 

void sortArray(int*, int); 

int main() 
{  

    string fileContent = "a coded message which is several hundreds of characters long is being passed into the program"; 

    int count[26]; 

// This code is skipping over spaces and other characters 

    for(int f = 0; f < fileContent.length(); f++) 
    { 
      if(fileContent[f] == 32) 
      { 
        continue; 
      } 

      if(fileContent[f] >= 48 && fileContent[f] <= 57) 
      { 
        continue; 
      } 

      count[(fileContent[f]-'a')%26]++; 
    } 

// Here is where my issue begins. In sortArray, the position of the characters are being changed. 

    cout << "Letter frequency: Most common to least common" << endl; 

    sortArray(count, 26); 

    for(int p = 0; p < 26; p++) 
    { 
      cout << char(p + 97) << ": " << count[p] << endl; 
    } 

    return 0; 
} 



void sortArray(int* srcArray, int numElements) 
{ 
     for(int x = 0; x < numElements; x++) 
     { 
      int max = srcArray[x]; 
      int maxIndex = x; 
      int hold; 

      for(int y = x + 1; y < numElements; y++) 
      { 
        if(srcArray[y] > max) 
        { 
          max = srcArray[y]; 
          maxIndex = y; 
        } 
      } 

      hold = srcArray[x]; 
      srcArray[x] = max; 
      srcArray[maxIndex] = hold; 
      hold = 0; 

     } 
} 

친절 내가, 내가 이론화 봤는데이 문제를 해결할 수 있지만이 가능한 솔루션을 알아낼 수없는 방법을 알려 주시기 바랍니다.

+0

출력물을 게시 해주십시오. 예상되는 내용은 무엇입니까? – Valgrind1691

+0

주파수 또는 단지 표준 :: pair 을위한 문자와 정수를 포함하는 구조체를 생성하고 그에 따라 배열을 만들고 이에 따라 정렬하십시오. – lamandy

+0

@ Valgrind1691 예."count [(fileContent [f] - 'a') % 26] ++;"각 문자를 배열 int count [26]의 위치로 저장하고 있습니다. 그런 다음이 배열을 sortArray에 전달하고 있습니다. 이 질문에 대한 대답이 있습니까? 더 많은 프로그램이나 실행 후 리턴되는 코드를 포함하도록이 제공된 코드를 편집하고 싶다면 알려주십시오. – hammonak

답변

1

횟수 배열에서 빈도를 계산 한 후. 이 내림차순으로 배열을 정렬한다

bool myCompare(const std::pair<char, int>& p1, const std::pair<char, int>& p2) 
{ 
    return p1.second > p2.second; 
} 

myCompare 들어

std::array<std::pair<char, int>, 26> pairArray; 
for (int i = 0; i < 26; ++i) 
{ 
    pairArray[i] = std::make_pair('a' + i, count[i]); 
} 

std::sort(pairArray.begin(), pairArray.end(), myCompare); 

for (int i = 0; i < 26; ++i) 
    std::cout << pairArray[i].first << ": " << pairArray[i].second << std::endl; 

.

+0

나는 이것을 사용하여 sortArray 함수가 전혀 필요하지 않습니까? 또한, pairArray는 count []를 대체할까요? – hammonak

+0

여전히 sortArray를 사용할 수 있지만 주파수 인 두 번째 값을 기준으로 정렬하려면이를 수정해야합니다. 위의 코드는'count []'에서 계산 빈도를 마친 후에 의미가 있지만, pairArray로 즉시 시작하여 주파수를 사용하도록 선택할 수도 있습니다. – lamandy

+0

또한 int count [26] = {0};을 실행하여 count []를 0으로 초기화하는 것에 유의하십시오. C++은 변수 나 배열을 선언 할 때 값을 초기화하지 않습니다. – lamandy

0

문제는 배열에 주파수가 있지만 해당 주파수에 주파수가 매핑되어 있지 않기 때문에 발생합니다. 빈도가 정렬되면 배열은 재 배열되지만 주파수 인쇄는 문자에 의존하지 않으므로 a-z 문자를 인쇄하고 정렬 된 배열에있는대로 주파수를 할당합니다.

당신이 할 수있는 일은 주파수를 해당 문자로 매핑하는 것입니다. 하나의 솔루션은 정렬되지 않은 맵을 사용할 수 있습니다. char가 키입니다. 정렬되지 않은 맵은 문자 값에 대한 맵을 내부적으로 정렬하지 않으므로 주파수 순서도 유지할 수 있습니다.

@lamandy와 같이 쌍으로 벡터를 사용할 수도 있습니다.

bool sortbysecVal(const pair<int, int> &a, const pair<int, int> &b) 
    return (a.second > b.second); 

당신이 주파수를 계산하면 후, 당신이 사용할 수있는 쌍

의 두 번째 값으로

vector< pair <char, int> > vect; 
for (int i = 0; i < 26; i++) 
{ 
    vect.push_back(make_pair(char(i + 97), count[i])); 
} 

sort(vect.begin(), vect.end(), sortbysecVal); 

// Printing the sorted vector(after using sort()) 
cout << "The vector after sort operation is:\n"; 
for (int i = 0; i<26; i++) 
{ 
    // "first" and "second" are used to access 
    // 1st and 2nd element of pair respectively 
    cout << vect[i].first << " " 
     << vect[i].second << endl; 
} 

종류,이 목적을 해결하고 당신은 늘 당신의 정렬 기능이 필요합니다.

추 신 : 초기화되지 않은 경우 처음에는 가비지가 포함되어 있으므로 int count [26] = {0}과 같이 (배열 수)를 0으로 초기화해야합니다 (count [(fileContent [f ]] '% 26] ++)을 쓰레기로 보내면 결과 (빈도)가 나오지 않는다.

0

대답은 표준 라이브러리 전문가에게 3 라이너 일 것이다. 나는 표준 라이브러리가 싫다. 프로그래밍으로 누구나 쉽게 할 수 있습니다.

여기에는 두 가지 버전이 있습니다. 이 재미.

#include <map> 
#include <string_view> 
#include <vector> 
#include <algorithm> 
using counted = std::pair<char, unsigned>; 

std::vector<counted> 
counted_chars(const std::string_view input) { 
    // Return a vector of <char, count> pairs, where char is an uppercase 
    // letter, and count is the number of occurrences of the letter (upper or lower). 
    // It is sorted from highest count to lowest. 
    using namespace std; 
    map<char, unsigned> count; 
    // Count them. 
    for(char next: input) {if (isalpha(next)) {count[toupper(next)] += 1;}} 

    // Sort them 
    vector<counted> sorted(count.size()); 
    copy(count.cbegin(), count.cend(), sorted.begin()); 
    sort(sorted.begin(), sorted.end(), [](counted c1, counted c2) 
     { return c1.second > c2.second; }); 

    return sorted; 
} 

int main() { 
    std::string str = "a coDed; MESSage which_is several hundreds of characters long is being passed into the program"; 
    auto result = counted_chars(str); 
    return 0; 
} 

std :: map을 사용하지 않는 또 하나.

#include <map> 
#include <vector> 
#include <algorithm> 
using counted = std::pair<char, unsigned>; 

std::vector<counted> counted_chars(std::string input) { 

    using namespace std; 
    input.resize(remove_if(input.begin(), input.end(), [](char ch) { return !isalpha(ch); })-input.begin()); 
    for(char &ch: input) { ch = toupper(ch); } 
    sort(input.begin(), input.end()); 
    string present {input}; 
    present.resize(unique(present.begin(), present.end())-present.begin()); 
    std::vector<counted> sorted; 
    for (char ch:present) {sorted.push_back(make_pair(ch, count(input.begin(), input.end(), ch)));} 
    sort(sorted.begin(), sorted.end(), [](counted c1, counted c2) { return c1.second > c2.second; }); 
    return sorted; 
} 

int main() { 
    std::string str = " -- I have always wished for my computer to be as easy to use as my telephone; My wish has come true because I can no longer figure out how to use my telephone."; 
    auto result = counted_chars(std::move(str)); 

    return 0; 
} 
+0

값을 쌍의 순서를 바꾸는'map '에 복사함으로써 정렬을 줄일 수 있습니다. Boost를 사용할 수있는 경우 [bimap] (http://www.boost.org/doc/libs/1_65_1/libs/bimap/doc/html/index.html)이이 상황에 맞습니다. – Caleth

+0

@Caleth -지도에 값을 복사하고 쌍의 순서를 바꾸는 것에 대한 부분을 이해하지 못합니다. –

+0

'for (자동 및 쌍 : 개수) {reversed [pair.second] = pair.first; }' – Caleth