I need to know how to check how many times numbers were entered and print the numbers out from least to greatest while printing how many times a number that was repeated was entered (printed as a number written next to the number it's talking about).
Here's my code so far (specs for the exercise are written in it in comments, along with an example output (spaces probably not preserved properly):
// chapter11ex16.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 7 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 16
// Exercise Specification:
/**
* Write a program to read a file of whitespace-separated numbers and
* output them in order (lowest value first), one value per line. Write a value
* only once, and if it occurs more than once write the count of its
* occurrences on its line. For example, 7 5 5 7 3 117 5 should give
* 3
* 5 3
* 7 2
* 117
*/
#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
usingnamespace std;
cout << "Please enter some numbers separated by spaces:\n";
vector<int> numbers;
for (int number; cin >> number;)
{
cin.ignore();
numbers.push_back(number);
sort(numbers.begin(), numbers.end());
if (numbers[number - 1] == numbers[number])
{
}
}
}
I would create a struct to store the number and count and store it in a vector.
Whenever you read a number check if it is in the vector, if yes increment the count, otherwise create a new struct and add it to the vector. At the end you print the vector.
1 2 3 4 5 6 7 8 9 10
struct NumberInfo
{
int number,
count;
booloperator == (const NumberInfo& ni) // for use of find
{
returnthis->number == ni.number;
}
};
Write a program to read a file of whitespace-separated numbers
Where is this part of the assignment?
1 2 3 4 5 6
for (int number; cin >> number;)
{
cin.ignore();
numbers.push_back(number);
sort(numbers.begin(), numbers.end());
if (numbers[number - 1] == numbers[number])
You're invoking Undefined Behavior in this snippet, can you tell us where and why (Note: there is at least two places in this small snippet that are problems?
Why are you sorting the numbers every time you go through the loop? Sorting even a small vector multiple times can take a lot of resources, imagine what would happen if the vector grows to several hundred or several thousand elements.
What's with the cin.ignore()? By default the extraction operator skips leading whitespace characters so it shouldn't be needed.
@Thomas: My compiler is complaining about the assignment operator not being defined for NumberInfo (if I understand correctly). Quoting the message would make the post too long, so I can't do that. So I'll show my code and show the quote in another post if needed.
// chapter11ex16.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 7 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 16
// Exercise Specification:
/**
* Write a program to read a file of whitespace-separated numbers and
* output them in order (lowest value first), one value per line. Write a value
* only once, and if it occurs more than once write the count of its
* occurrences on its line. For example, 7 5 5 7 3 117 5 should give
* 3
* 5 3
* 7 2
* 117
*/
#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <algorithm>
#include <vector>
struct NumberInfo
{
int m_number;
int m_count;
booloperator==(const NumberInfo &ni);
NumberInfo operator=(const NumberInfo &ni);
NumberInfo(constint number, constint count);
};
void print_numbers_count(const std::vector<NumberInfo> &ni_v);
int main()
{
usingnamespace std;
cout << "Please enter some numbers separated by spaces:\n";
vector<NumberInfo> ni_v;
int number;
size_t iter = 0;
while (cin >> number)
{
cin.ignore();
ni_v.push_back(NumberInfo{ number, 0 });
if (ni_v[number].m_number == number)
{
++ni_v[iter].m_count;
}
++iter;
}
}
NumberInfo::NumberInfo(constint number, constint count)
:m_number{ number }, m_count{ count }
{
}
bool NumberInfo::operator==(const NumberInfo &ni)
{
returnthis->m_number == ni.m_number;
}
NumberInfo NumberInfo::operator=(const NumberInfo &ni)
{
this->m_number = ni.m_number;
this->m_count = ni.m_count;
return *this;
}
void print_numbers_count(const std::vector<NumberInfo> &ni_v)
{
usingnamespace std;
sort(ni_v.begin(), ni_v.end());
for (constauto &x : ni_v)
{
cout << x.m_number;
if (x.m_count > 0)
{
cout << '\t' << x.m_count;
}
cout << '\n';
}
}
My compiler is complaining about the assignment operator not being defined for NumberInfo (if I understand correctly).
I don't think you're understanding correctly (although I didn't bother tossing your code in a compiler.) Your operator= requires the presence of a copy constructor (as it returns by value,) but you don't have one. Typically, the return type of an operator= should be a reference.
As well, std::sort uses operator< by default for ordering and no such operator is provided for NumberInfo.
// Write a program to read a file of whitespace - separated numbers and output them in order(lowest value first), one value
// per line.Write a value only once, and if it occurs more than once write the count of its occurrences on its line.For
// example, 7 5 5 7 3 117 5 should give3
// 5 3
// 7 2
// 117
#include "std_lib_facilities.h"
struct NumberInfo
{
int number,
count;
NumberInfo(int number, int count)
{
this->number = number;
this->count = count;
}
};
// searches for a number num in the vector numbers
// return true if the number is found
// and sets index to the index of the elem that contains num
// if not found return false and leaves index untouched
bool FindNumber(vector<NumberInfo>& numbers, int num, size_t& index)
{
for (size_t i = 0; i < numbers.size(); i++)
{
if (numbers[i].number == num)
{
index = i;
returntrue;
}
}
returnfalse;
}
int main()
{
vector<NumberInfo> numbers;
size_t pos = 0;
for (int num; cin >> num;)
{
if (FindNumber(numbers, num, pos))
{
numbers[pos].count++;
}
else
{
numbers.push_back(NumberInfo(num, 1));
}
}
sort(numbers.begin(), numbers.end(),
[](const NumberInfo& n1, const NumberInfo& n2)
{
// your sort code
});
// print numbers here
system("pause");
return 0;
}
My compiler keeps complaining about not being able to find the overloaded function I'm trying to call. Did I not define them properly, or am I still not overloading the functions I need?
I can't quote the messages from the compiler here because it'd make the post more than 8,192 characters long. So I'll just show you my code again. Isn't there a way I can show you guys the error messages, though?
You really need to study up on const correctness. You have several places where you have failed to properly const qualify your class functions and places, like above, where you've passed a const then tried to modify that const.
Also posting the error messages would be helpful, and in this case the first dozen or so would have been helpful.
1 2 3 4 5 6 7 8 9 10
||=== Build: Debug (compiler: gcc 6.1.0) ===|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/predefined_ops.h||In instantiation of ‘constexprbool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1, _Iterator2) const [with _Iterator1 = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >; _Iterator2 = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >]’:|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/stl_algo.h|1844|required from ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/stl_algo.h|1882|required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/stl_algo.h|1968|required from ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/stl_algo.h|4714|required from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<const NumberInfo*, std::vector<NumberInfo> >]’|
/main.cpp|86|required from here|
/opt/gcc/6.1.0/include/c++/6.1.0/bits/predefined_ops.h|43|error: no match for ‘operator<’ (operand types are ‘const NumberInfo’ and ‘const NumberInfo’)|
main.cpp|71|note: candidate: bool NumberInfo::operator<(const NumberInfo&) <near match>|
main.cpp|71|note: passing ‘const NumberInfo*’ as ‘this’ argument discards qualifiers|
In the above the last two messages point you to the actual problem. That "near match" and "discards qualifiers" are two very very key words, and the fact that they are pointing to your code is also a key.
Let's take a step and recognize the tricky part with this problem.
1. To count the number of occurrences of a number, you need to lookup the count by the number.
2. To display the numbers in order of frequency, you need to sort the numbers by count.
This suggests two data structures.
For what it's worth, this is actually a pretty common problem in the real world: "what are the most common occurences of X?" At work I usually get the X's into a file, one per line, and then do sort | uniq -c | sort -n on the command line. sort sorts the lines. uniq -c prints unique lines, prepending the number of occurences (the count) sort -n sorts numerically (by the count)
// Write a program to read a file of whitespace - separated numbers and output them in order(lowest value first), one value
// per line.Write a value only once, and if it occurs more than once write the count of its occurrences on its line.For
// example, 7 5 5 7 3 117 5 should give
// 3
// 5 3
// 7 2
// 117
#include "std_lib_facilities.h"
struct NumberInfo
{
int number,
count;
NumberInfo(int number, int count)
{
this->number = number;
this->count = count;
}
};
// searches for a number num in the vector numbers
// return true if the number is found
// and sets index to the index of the elem that contains num
// if not found return false and leaves index untouched
bool FindNumber(vector<NumberInfo>& numbers, int num, size_t& index)
{
for (size_t i = 0; i < numbers.size(); i++)
{
if (numbers[i].number == num)
{
index = i;
returntrue;
}
}
returnfalse;
}
int main()
{
vector<NumberInfo> numbers;
size_t pos = 0;
for (int num; cin >> num;)
{
if (FindNumber(numbers, num, pos))
{
numbers[pos].count++;
}
else
{
numbers.push_back(NumberInfo(num, 1));
}
}
sort(numbers.begin(), numbers.end(),
[](const NumberInfo& n1, const NumberInfo& n2)
{
return n1.number < n2.number;
});
for (NumberInfo& ni : numbers)
{
cout << ni.number;
if (ni.count > 1)
cout << "\t" << ni.count;
cout << "\n";
}
system("pause");
return 0;
}
Okay, the errors were taken care of, but now there's a logic error; here's an example output:
Please enter some numbers separated by spaces:
7 5 5 7 3 117 5 |
3 1
5 1
5 1
5 1
7 1
7 1
117 1
Please enter a character to exit
Press any key to continue . . .
What's with the 1's? And why didn't wait for a character input exiting (that's two logic errors, not one, but yeah).
Here's the code (I took the sort() out of the printing function and put it in main, so that the vector is sorted before being passed to the function):
// chapter11ex16.cpp : Defines the entry point for the console application.
// Osman Zakir
// 3 / 7 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 11 Exercise 16
// Exercise Specification:
/**
* Write a program to read a file of whitespace-separated numbers and
* output them in order (lowest value first), one value per line. Write a value
* only once, and if it occurs more than once write the count of its
* occurrences on its line. For example, 7 5 5 7 3 117 5 should give
* 3
* 5 3
* 7 2
* 117
*/
#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <algorithm>
#include <vector>
struct NumberInfo
{
int m_number;
int m_count;
booloperator<(const NumberInfo &ni);
NumberInfo(constint number, constint count);
NumberInfo();
};
void print_numbers_count(const std::vector<NumberInfo> &ni_v);
int main()
{
usingnamespace std;
cout << "Please enter some numbers separated by spaces:\n";
vector<NumberInfo> ni_v;
int number;
size_t iter = 0;
while (cin >> number)
{
cin.ignore();
ni_v.push_back(NumberInfo{ number, 0 });
if (ni_v[iter].m_number == number)
{
++ni_v[iter].m_count;
}
++iter;
}
sort(ni_v.begin(), ni_v.end());
print_numbers_count(ni_v);
cin.clear();
keep_window_open();
}
NumberInfo::NumberInfo(constint number, constint count)
:m_number{ number }, m_count{ count }
{
}
NumberInfo::NumberInfo()
: m_number{}, m_count{}
{
}
bool NumberInfo::operator<(const NumberInfo &ni)
{
returnthis->m_number < ni.m_number;
}
void print_numbers_count(const std::vector<NumberInfo> &ni_v)
{
usingnamespace std;
for (constauto &x : ni_v)
{
cout << x.m_number;
if (x.m_count > 0)
{
cout << '\t' << x.m_count;
}
cout << '\n';
}
}