2016-03-21 3 views
0

Я пытаюсь закончить проблему, когда я прочитал файл в программе и вывел файл со средним значением, min, max и количеством, сколько раз это число произошло в программа. Однако я не могу понять, как создать массив для дублированного числа «счетчиков».Как подсчитать дублированные числа в отсортированном массиве

Если файл, который я пытался читать имел значение 19 5 26 5 5 19 16 8 1,

мне нужна выведенный файл для чтения 5---3 times; 8---1 time; 16---1 time; 19--2 times; 26--1 times.

Я сначала отсортировал мой массив, чтобы читать 5 5 5 8 16 19 19 26.

Ниже мой код с объяснениями, что я пытаюсь сделать:

#include <iostream> 
#include <fstream> 
#include <cstdlib> 
#include <string> 
using namespace std; 

double averageArray(int a[], int length); // user defined function to get average 
int maxval(int a[], int length); //user defined function to get max val 
int minval(int a[], int length); //user defined function to get min val 
void bsort(int arr[], int length);// udf to sort array from min to max 
int countArray(int a[], int length); //attempt to create a function to get the number of occurrences of a number that is duplicated 

int main() 
{ 
    char infilename[16]; 
    int nums[50];//newly created array to read in the numbers from the file 
    int length(0);//array has a length defined by "length" 
    ifstream fin; 
    ofstream fout; 


    cout << "Please enter an input file name: "; 
    cin >> infilename; 
    cout << endl; 

    fin.open(infilename); 
    if (fin.fail()) 
    { 
     cerr << "The file " << infilename << " can't be open!"<<endl; 
     return 1; 
    } 


    cout<<"The output to the file statistics.txt should be as follows: "<<endl; 
    fout.open("statistics.txt"); 
    fout<<"N"<<"\t"<<"Count"<<endl; 
    cout<<"N"<<"\t"<<"Count"<<endl; 


    while (fin >> nums[length]) 
     length++; 

    bsort(nums, length); 
    for (int i=0; i<length; i++) { 
     if (nums[i]==nums[i-1]) { 
      continue; 
     } 
     cout<<nums[i]<<"\t"<<countArray(nums,length)<<endl; 
     fout<<nums[i]<<"\t"<<endl; 
    } 

    cout << "\nAverage: " << averageArray(nums,length) << endl; 
    cout << "Max: "<< maxval(nums,length)<<endl; 
    cout << "Min: "<< minval(nums,length)<<endl; 


    fin.close(); 


    return 0; 
} 



double averageArray (int a[], int length) 
{ 
    double result(0); 

    for (int i = 0; i < length ; i++) 
     result += a[i]; 
    return result/length; 
} 

int maxval(int a[], int length) 
{ 

    int max(0); 

    for (int i=1; i<length; i++) 
    { 
     if (a[i]>max) 
      max=a[i]; 
    } 
    return max; 
} 

int minval(int a[], int length) 
{ 

    int min(100); 

    for (int i=1; i<length; i++) 
    { 
     if (a[i]<min) 
      min=a[i]; 
    } 
    return min; 
} 

void bsort(int a[], int length) 
{ 
    for (int i=length-1; i>0; i--) 
     for (int j=0; j<i; j++) 
      if (a[j]>a[j+1]) 
      { 
       int temp=a[j+1]; 
       a[j+1]=a[j]; 
       a[j]=temp; 
      } 
} 

int countArray(int a[], int length) 
{ 
    int counter(0); 
    for (int i=0; i<length; i++){ 
     if (a[i]==a[i+1]) //loop through array and if the number after is the same as the previous number, then count one 
     counter++; 
    } 
    return counter; 
} 

Хотя он компилирует, счетчик показывает только «3» s, как показано на рисунке:

output image.

+0

Я думаю, что вы можете сделать это в Интернете, используя [станд :: Количество()] (http://en.cppreference.com/w/cpp/algorithm/count), выбирая один элемент, выводя результат и запоминая его, и продолжайте до конца массива. – Incomputable

+0

btw вы получаете из связей – Incomputable

+0

Возможно, вы захотите использовать 'std :: map' или' std :: unordered_map' (любой из которых делает эту задачу довольно тривиальной). Очевидной альтернативой было бы хранить входы в массиве , затем сортируйте его, затем пройдите через поиск несоответствий. –

ответ

0

Ваша функция int countArray(int a[], int length) не имеет ввода для действительного числа. Всегда учитывается, как часто в вашем массиве одинаковые числа стоят друг за другом. Это случается два раза для пяти и один раз в течение 19 => 3 раза.

Решение:

int countArray(int a[], int length, int num) 
{ 
    int counter(0); 
    for (int i=0; i<length; i++){ 
     if (a[i]==num) //loop through array and if the number is the one you are looking for 
      counter++; 
    } 
    return counter; 
} 

и позвоню функционируют: countArray(nums, length, nums[i]);

1

Перед тем, как дать вам решение, пожалуйста, найдите время, чтобы вспомнить, вы программируете на C++, а не C. Таким образом, вы должны использовать векторы, итераторы istream и std::sort. Вы также должны использовать std::map, который легко решает эту задачу цель:

template <typename It> 
std::map<int, int> count_occurrences(It it, It end) 
{ 
    std::map<int, int> output; 
    while (it != end) output[*it++]++; 
    return output; 
} 

Как совместить это с существующим кодом остается в качестве упражнения для читателя. Я предлагаю вам прочитать об итераторах.

0
void countArray(int a[], int length) 
{ 
    int counter(1); 
    bool flag(false); 
    //you take (i+1) index, it can go out of range 
    for (int i = 0; i < length - 1; i++){ 
     if (a[i]==a[i+1]){ //loop through array and if the number after is the same as the previous number, then count one 
      flag = true; 
      counter++; 
     } 
     else { 
      if (flag){ 
       cout<<a[i] << counter << endl; 
      } 
      flag = false; 
      counter = 1; 
     } 
    } 
} 

Я долгое время не набирал код на C, но надеюсь, что это поможет. Эта процедура выдаст вам ответ, и вы должны позвонить ему только один раз.

0

Я предлагаю использовать std::map, что является лучшим решением для решения проблемы. Я попытаюсь объяснить легко дифферент шаги, чтобы сделать это:

  1. Я считаю ваши переменные инициализируются, например:

    int length = 9; 
    int nums[length] = {19, 5, 26, 5, 5, 19, 16, 8, 1}; 
    
  2. Создание std::map<int,int>, где key ( первый Int) будет ваш номер и номер value ( второй int) номер входа этого номера в ключ.

    std::map<int,int> listNumber; 
    
  3. Заполните вашу карту

    // For all numbers read in your file 
    for(int i=0; i<length; ++i) 
    { 
        // Get number value 
        int n = nums[i]; 
    
        // Find number in map 
        std::map<int, int>::iterator it = listNumber.find(n); 
    
        // Doesn't exists in map, add it with number of occurence set to 1... 
        if(it == listNumber.end()) 
        { 
         listNumber.insert(std::pair<int,int>(n,1)); 
        } 
        // ... otherwise add one to the number of occurence of this number 
        else 
        { 
         it->second = it->second+1; 
        } 
    } 
    
  4. Читать карту

    // Read all numbers and display the number of occurence 
    std::cout << "N" << "\t" << "Count" << std::endl; 
    for(std::map<int, int>::iterator it = listNumber.begin(); it!=listNumber.end(); ++it) 
    { 
        std::cout << it->first << "\t" << it->second << std::endl; 
    }