2013-02-12 4 views
3

문자열에서 문자를 계산해야하고 개수에 따라 정렬해야하며 cout 결과가 필요합니다. 이를 위해 vectorstruct을 사용하려고합니다. 여기에 내 코드의 일부이지만, 내가 뭔가 구현하는 방법을 모르기 때문에 그것은 작동하지 않습니다 :벡터 및 구조체를 사용하는 방법?

: 내가 처리하는 방법을 모르는이 개 부분이이 코드에서

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

using namespace std; 

struct int_pair{ 
    int key; 
    int value; 
}; 

bool sort_by_value(int_pair left, int_pair right){ 
    return left.value < right.value; 
} 

int main() {  
    string characters = "aasa asdfs dfh f ukjyhkh k wse f sdf sdfsdf";  
    vector<int_pair> most_frequent;  

    for (string::size_type i = 0; i <= characters.length(); i++) { 
     int int_char = (int)characters[i]; 
     most_frequent[int_char]++; <-- I want to do something like this, but it's not working 
    } 

    sort(most_frequent.begin(), most_frequent.end(), sort_by_value); 

    for (vector<int_pair>::iterator it = most_frequent.begin(); it != most_frequent.end(); ++it) <-- is this call correct? 
     cout << " " << it->key << ":" << it->value << endl;  

    return 0; 
} 

most_frequent[int_char]++; <-- I want to do something like this, but it's not working 

for (vector<int_pair>::iterator it = most_frequent.begin(); it != most_frequent.end(); ++it) <-- is this call correct? 

은 아마 당신은이 코드에서 다른 실수와 잠재적 인 문제를 볼 수 있습니다.

+0

벡터를 사용하는 연습입니까? 지도 또는 해시 맵이 작은 문자열에 더 잘 맞기 때문입니다. –

+0

@PeteKirkham 아니, 그렇지 않아. 내 해결책이야. –

답변

2

이것은 당신이 무엇을해야한다 :

most_frequent[int_char].key = int_char; 
most_frequent[int_char].value++; 

네,이 key 많은 시간을 설정, 그것은 필요하지 않더라도.

+0

나는이 줄을'most_frequent [int_char] ++;'코드로 갱신했고 이제 :'분할 오류 (코어 덤프 됨) ' –

+0

@viakondratiuk 이것은 벡터가 비어 있기 때문입니다. 벡터에 존재하지 않는 요소에 접근하는 것은 금지되어있다. (맵과는 대조적으로) 처음에는 256 개의 값으로 벡터를 채워야한다 ('vector'의 생성자에'256 '을 전달). – leemes

+0

@viakondratiuk :'벡터 most_frequent (256); ' –

1

키 (vector이 정수 인 "귀하"의 "키"로 색인 됨)를 사용하여 컨테이너에 액세스 할 때 컨테이너의 값 필드에 키를 다시 저장할 필요가 없습니다.

값 필드 만 필요하므로 struct이 필요하지 않으므로 벡터에 직접 발생 횟수를 저장할 수 있습니다.

아이디어는 처음에 256 개의 정수로 벡터를 채우는 것이며, 모두 0으로 초기화됩니다. 그런 다음 벡터 색인을 "키"(문자 코드)로 사용하여 요소 (발생 수)에 액세스하십시오.

이이 유사한 코드가 발생합니다 :

// initialize with 256 entries, one for each character: 
vector<int> counts(256); 

for (string::size_type i = 0; i <= characters.length(); i++) { 
    // for each occurrence of a character, increase the value in the vector: 
    int int_char = (int)characters[i]; 
    counts[int_char]++; 
} 

벡터의 충전이 완료되면, 당신은 최대 값 (값뿐만 아니라이 저장되어있는 키뿐만 아니라)를 사용하여 찾을 수 있습니다 std::max_element 알고리즘 : http://ideone.com/94GfZz

: 여기

vector<int>::iterator most_frequent = 
     std::max_element(counts.begin(), counts.end()); 

// getting the character (index within the container, "key"): 
std::cout << (char)(most_frequent - counts.begin()); 

// the number of occurrences ("value"): 
std::cout << (*most_frequent); 

가 변경하여 예입니다 (단지 가장 자주 문자를 인쇄, 여기 당신이 그것을 볼 수 없습니다 있도록 공간)

이 벡터를 정렬 할 수 있지만 요소가 이동하여 색인을 변경하므로 열쇠를 잃어 버리게됩니다.

multimap<int,int> keyForOccurrence; 
for (vector<int>::iterator i = counts.begin(); i != counts.end(); ++i) { 
    int occurrences = *i; 
    int character = i - counts.begin(); 
    keyForOccurrence.insert(std::pair<int,int>(occurrences, character)); 
} 

업데이트 코드 : http://ideone.com/Ub5rnL

마지막 것은 당신이해야 정렬 할 밖으로 반전 (다)지도 (반전 키, 값)를 사용하여 같은 통계를 처리하는 좋은 트릭이있다 이지도 내에서 데이터를 액세스하고 처리하는 방법을 직접 배우십시오. 이 지도가 역전 된에 대한 멋진 점은지도가 키순으로 정렬되므로 자동으로 항목별로 정렬된다는 것입니다.

+0

가장 빈번한 편지뿐만 아니라 모든 글자 수를 필요로합니다. –

+0

벡터에 모두 들어 있습니다. – leemes

+0

@viakondratiuk : leemes가 작성한 코드는 모든 문자를 셀 수있는 좋은 출발점이되어야합니다. 확실히 당신은 그가 당신을 위해 모든 숙제를하고 싶지 않습니까? –

4

std :: map을 사용하여 각 문자의 빈도를 확인한 다음 멀티 맵에 복사 한 다음 키와 값을 역순으로 정렬하여 순서대로 가져옵니다.

#include <iostream> 
#include <map> 
#include <algorithm> 

template<class T, class U> 
std::pair<U,T> flip_pair(const std::pair<T,U>& p) { 
    return std::make_pair(p.second,p.first); 
} 

int main(){ 
    std::string characters = "zxcvopqiuweriuzxchajksdui"; 
    std::map<char,int> freq; 
    std::multimap<int,char> rev_freq; 

    // Calculate the frequency of each letter. 
    for(char c: characters){ 
    freq[c]++; 
    } 

    // Copy the results into a multimap with the key and value flipped 
    std::transform(std::begin(freq), std::end(freq), 
       std::inserter(rev_freq, rev_freq.begin()), 
       flip_pair<char,int>); 

    // Print out the results in order. 
    for(std::pair<int,char> p : rev_freq){ 
    std::cout << p.first << ": " << p.second << std::endl; 
    } 
}; 
1

나는 각 문자의 발생을 저장하는 std::map 용기를 사용하는 것이 더 자연 찾을 수 있습니다. 문자의지도는 이며, 발생 횟수는지도의 입니다. 소스 문자열을 검사하고 std::map::operator[]++을 사용하여이 맵을 쉽게 작성하여 발생 횟수를 늘릴 수 있습니다.

그런 다음 키와 값 반전과 위의지도에서 두 번째지도를 구축 할 수 있도록이지도는 으로 분류됩니다은을 발생을, 그리고 당신은이 두 번째지도를 인쇄 할 수 있습니다. 키 (즉, 어커런스)를 반복 할 수 있기 때문에 std::multimap을 두 번째 맵으로 사용해야합니다.

샘플 코드는 (내가 VS2010의 SP1/VC10와 함께 테스트) 다음과

#include <stddef.h>  // for size_t 
#include <algorithm> // for std::transform 
#include <functional> // for std::greater 
#include <iostream>  // for std::cout 
#include <iterator>  // for std::inserter 
#include <map>   // for std::map, std::multimap 
#include <ostream>  // for std::endl 
#include <string>  // for std::string 
#include <utility>  // for std::pair 
using namespace std; 

int main() 
{  
    string str = "aasa asdfs dfh f ukjyhkh k wse f sdf sdfsdf";  

    // Build the occurrences map (char -> occurrences) 
    map<char, size_t> freq;  
    for (size_t i = 0; i < str.length(); ++i) 
     freq[ str[i] ]++; 

    // Build a new map from previous map with inverted <key, value> pairs, 
    // so this new map will be sorted by old map's value (i.e. char's 
    // occurrences), which is new map's key. 
    // Use the std::greater comparator to sort in descending order. 
    multimap<size_t, char, greater<size_t>> sorted_freq; 
    transform(
     freq.begin(), freq.end(),      // source 
     inserter(sorted_freq, sorted_freq.begin()),  // destination 
     [](const pair<char, size_t>& p)     // invert key<->value 
     { 
      return pair<size_t, char>(p.second, p.first); 
     } 
    ); 

    // Print results  
    for (auto it = sorted_freq.begin(); it != sorted_freq.end(); ++it) 
     cout << it->second << ": " << it->first << endl; 
} 

출력 :

: 9 
s: 7 
f: 7 
d: 5 
a: 4 
k: 3 
h: 3 
u: 1 
w: 1 
y: 1 
j: 1 
e: 1 

당신이 공백 문자의 발생을 인쇄하지 않으려면 , 당신은 쉽게 그것을 걸러 낼 수 있습니다.

std::map/std::multimap을 사용하면 ASCII가 아닌 문자 인 경우 std::vector보다 더 잘 확장됩니다. 유니 코드 UTF-32를 사용하는 경우 (유니 코드 문자가 256 이상이기 때문에).

관련 문제