-
Dec 15th, 2014, 08:04 AM
#1
Thread Starter
Lively Member
How to put this code into separate classes in separate files
Hi!
Just recently started learning C++
I had an excercise which had 3 parts:
1. Ask the user a number of random integers to be created. Ask the user the range of integers (min and max). Then write these integers to a file.
2. Read integers from file line by line into array. Sort array.
3. Make a summary and show it: How many times integers occured and what is the occurence percentage.
This excercise was quite easy and I got it solved.
Now I think that putting everything into one main is an awful way of coding. Therefore I would like some help putting this piece of code into separate classes in separate files (.h and .cpp). I know how to do it in C# and in JAVA and in VB but C++ seems to be a little bit different.
So here's the code I have so far. Any help and hints are appreciated.
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
int main ()
{
/*
Setting variables
*/
int quantity; //The amount of random integers to create.
int min; //Smallest random number.
int max; //Largest random number.
string file; //File name without extension
string extension = ".txt"; //Set file extension
//Asking for user input
cout << "Insert number of random integers to be created: ";
cin >> quantity;
cout << quantity << " random integers to be created!\n\n";
//Sanity test: largest number cannot be greater than the smallest
while (true)
{
cout << "Smallest allowed integer: ";
cin >> min;
cout << "Largest allowed integer: ";
cin >> max;
if (max >= min)
{
break;
}
else
{
cout << "Largest allowed integer cannot be less than smallest, try again!\n";
}
}
cout << "Save as: ";
cin >> file;
string fileName = file + extension; //Add file .txt extension to filename.
ofstream myfile;
//All the heavylifting starts here
cout << "\nLoading...\n";
//TODO
//ofstream myfile(fileName.c_str());
/* //Clear file contents if file already exists.
while (myfile)
{
string confirm;
cout << "File already exists! Overwrite? (Y/N): ";
cin >> confirm;
if(confirm == "Y" || confirm == "y")
{
myfile.open(fileName.c_str(), ios::trunc);
myfile.close();
break;
}
}*/
//Start generating random numbers and append to file.
srand (time(NULL));
for( int a=0; a < quantity; a++ )
{
int randomNumber=min + (rand() % (int)(max - min + 1));
myfile.open(fileName.c_str(), ios::app);
myfile << randomNumber << endl;
myfile.close();
}
cout << "\nFile saved!\n";
//Set vector variables
fstream fp;
vector<int> numbers;
int number;
//Push values from file to vector array
fp.open(fileName.c_str(), ios::in | ios::binary);
if(fp.is_open())
{
while(fp >> number)
{
numbers.push_back(number);
fp.get();
}
}
fp.close();
cout << "\nUnsorted array of integers:\n\n";
//Loop through array and display values
for (int i=0; i < numbers.size(); i++)
{
cout << numbers[i] << " ";
}
cout << "\n\n"<< "Sorted array of integers: " << "\n\n";
//Start sorting vector array
sort( numbers.begin(), numbers.end() );
//Display sorted array
for (vector<int>::const_iterator it=numbers.begin(); it!=numbers.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
//Count integer occurence in vector
int size = numbers.size();
//cout << "\n\nTotal of " << size <<" integers.\n";
printf ("\n\nTotal of %d integers.\n", size);
cout << "\n\nSummary:\n\n";
for( int a = min; a <= max; a++ )
{
int mycount = std::count (numbers.begin(), numbers.end(), a);
if (!mycount == 0)
{
float z = (float)mycount;
float y = (float)numbers.size();
float c = (z / y)* 100; //
/*//Can also be done like this:
cout << "Integer " << a << " appears " << mycount << " times";
cout << " (" << c << "%).\n";*/
//Better and faster way to concatenate. Print out the results
printf ("Integer %d appears %d times (%.2f%).", a, mycount, c); //%.2f = float with 2 decimal places
cout << endl; //For new line
}
}
return 0;
}
Last edited by lkallas; Dec 15th, 2014 at 08:13 AM.
-
Dec 15th, 2014, 08:53 AM
#2
Re: How to put this code into separate classes in separate files
As the code has no classes and no functions why would you want to separate it into different files?
I would be concentrating on improving the code you have posted. eg
Code:
myfile.open(fileName.c_str(), ios::app);
myfile << randomNumber << endl;
myfile.close();
Why keep opening and closing the file in the loop? Why not open once before the loop and close after the loop?
Code:
fp.open(fileName.c_str(), ios::in | ios::binary);
Why open the file in binary mode when it was written as text mode?
Why display unsorted vector one way and display sorted vector another?
Why do you iterate (via count()) over the numbers vector for each number to count the integer occurrences in the vector? You need only iterate the vector once.
All advice is offered in good faith only. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
Dec 15th, 2014, 09:41 AM
#3
Thread Starter
Lively Member
Re: How to put this code into separate classes in separate files
Thank you 2kaud!
I see your point!
Did some changes to the code.
But still don't understand the part:
Originally Posted by 2kaud
Why do you iterate (via count()) over the numbers vector for each number to count the integer occurrences in the vector? You need only iterate the vector once.
How should I rewrite the integer occurrence count part? Seems like I am doing some overthinking here.
Initial problem was how to create separate classes and how put these classes into separate files. It's more like for educational purpose.
-
Dec 15th, 2014, 11:25 AM
#4
Re: How to put this code into separate classes in separate files
Well, part of that education is knowing when to hold them and know when to fold them.
In this case, know when to class 'em know when not to... To be fair, that code would be best served by multiple subs/functions, but I don't think there is any point for multiple classes, even if for educational purposes. All it would likely do is infuriate you and turn you off from OOB, and you'll start coding everything all in one class all the time. I'm not saying don't learn how to do it, but it goes beyond knowing how, you also need to also learn to know when.
-tg
-
Dec 15th, 2014, 03:41 PM
#5
Re: How to put this code into separate classes in separate files
How should I rewrite the integer occurrence count part? Seems like I am doing some overthinking here.
One way could be
Code:
#include <iostream>
#include <iterator>
#include <iomanip>
#include <fstream>
#include <string>
#include <ctime>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
const string extension = ".txt"; //Set file extension
int main()
{
int quantity; //The amount of random integers to create.
int min; //Smallest random number.
int max; //Largest random number.
string file; //File name without extension
cout << "Enter number of random integers to be created: ";
cin >> quantity;
cout << quantity << " random integers to be created!\n";
while ((cout << "Smallest allowed integer: ") && (cin >> min) && (cout << "Largest allowed integer: ") && (cin >> max) && (max < min))
cout << "Largest allowed integer cannot be less than smallest, try again!\n";
cout << "Save as: ";
cin >> file;
fstream myfile((file + extension).c_str(), fstream::in | fstream::out | fstream::trunc);
if (!myfile.is_open()) {
cout << "Cannot open file\n";
return 1;
}
srand(time(NULL));
for (int a = 0; a < quantity; a++)
myfile << min + (rand() % (int)(max - min + 1)) << endl;
vector<int> numbers;
int number;
myfile.seekg(0, myfile.beg);
numbers.reserve(quantity);
while (myfile >> number)
numbers.push_back(number);
myfile.close();
cout << "\nUnsorted array of integers:\n";
copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "\n" << "Sorted array of integers: " << "\n";
sort(numbers.begin(), numbers.end());
copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
cout << endl;
int size = numbers.size();
cout << "\nTotal of " << size <<" integers.\n\nSummary:\n\n";
map<int, int> msum;
for (const auto& cit : numbers)
msum[cit]++;
for (const auto& cmit : msum)
cout << "Integer " << cmit.first << " appears " << cmit.second << " times (" << fixed << setprecision(2) << ((float)cmit.second / (float)size) * 100.0 << "%)" << endl;
return 0;
}
This only iterates the vector of numbers once and the summary map once - so in worst case you have two iterations of quantity (where each random number generated is unique) ie 2 * quantity - but the average case is likely to be less as some numbers generated will be the same. In the original code the number of iterations was (max - min) * quantity. Where quantity is large and there is big difference between min and max this can be a significant processing reduction.
All advice is offered in good faith only. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
Dec 16th, 2014, 04:39 AM
#6
Thread Starter
Lively Member
Re: How to put this code into separate classes in separate files
Thank you techgnome and 2kaud!
Learned few new things from 2kaud's version of this code. This code is also easier to read.
This explains why developers say that it's always a good thing when your code is reviewed by others.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|