How to prevent frequency table to count ''empty boxes'' in c++ - c++

I wrote the below code (for homework) that is counting letters and numbers and generates a frequency table.
My question is: how to stop the frequency generation when the letter or number does not exist?
With the code I wrote, the program is counting every letter that are being fed to it but is also publishing a line for every possible letter/number in the ASCII code.
I hope I asked my question right and I appreciate any help or advice!
#include <iostream>
#include <string>
using namespace std;
int countingLetters(string someWords);
int countingNumbers(string someWords);
int frequency(string someWords, double totalChar);
int main() {
string someWords;
cout << "Write a some words: " << endl;
getline(cin, someWords);
cout << "You wrote:" << someWords << '\n';
cout << "Your sentence has " << someWords.length() << " characters." << '\n';
double totalChar = someWords.length();
cout << "Your sentence has " << countingLetters(someWords) << " letters." << '\n';
cout << "Your sentence has " << countingNumbers(someWords) << " numbers." << '\n';
cout << "Frequency of signs and letters :" << endl;
frequency(someWords, totalChar);
return 0;
}
int countingLetters(string someWords) {
int count = 0;
for (int i = 0; i < someWords.length(); i++) {
if (someWords[i] >= 'a' && someWords[i] <= 'z')
count++;
}
return count;
}
int countingNumbers(string someWords) {
int count = 0;
for (int i = 0; i < someWords.length(); i++) {
if (isdigit(someWords[i]) != 0)
count++;
}
return count;
}
int frequency(string someWords, double totalChar) {
cout << " Letter" << '\t' << "Antal" << '\t' << "Procent" << endl;
int frequency[255]={0};
for (int i = 0; i < someWords.length(); i++) {
char c = someWords[i];
if (isdigit(c) != 0)
frequency[c]++;
if (isalpha(c) != 0)
frequency[c]++;
}
for (int i = 0; i < sizeof(frequency); i++) {
if(frequency[i]>0)
cout << '\t' << static_cast<char>(i) << '\t' << frequency[i] << '\t' << frequency[i]/totalChar << endl;
}
return 0;
}

sizeof(frequency) is the size of the frequency array in bytes. You want the number of elements which is the size in bytes if the array divided by the size in bytes of one array element:
This is the number of elements of the frequency array:
sizeof(frequency) / sizeof(frequency[0])
But as you are using C++ you shouln't use raw arrays but std::array:
#include <array>
...
int frequency(string someWords, int totalChar) {
cout << " Letter" << '\t' << "Antal" << '\t' << "Procent" << endl;
std::array<int, 255> frequency{0};
for (int i = 0; i < someWords.length(); i++) {
char c = someWords[i];
if (isdigit(c) != 0)
frequency[c]++;
if (isalpha(c) != 0)
frequency[c]++;
}
int x = frequency.max_size();
for (int i = 0; i < frequency.max_size(); i++) {
if (frequency[i]>0)
cout << '\t' << static_cast<char>(i) << '\t' << frequency[i] << '\t' << frequency[i] / totalChar << endl;
}
return 0;
}
There is still room for improvement.

Related

Nested For - Loops to create multiplication table C++

I've been trying to overcome this problem for a few hours now and I seem to have one approach to the situation. It seems that the use of selection statements worked in creating the table necessary. Although there are formatting issues.
I'd like to know if there was a way to create the same table
using only nested for-loops as mentioned by our professor.
Are the selection statements necessary or can we implement a system of nested for loops to acquire the same results?
The image below is the required table:
But the image below is what I have:
Below is my code:
for (int i = 0; i <= numChoice; ++i)
{
if (i == 0)
{
for (int k = 1; k <= numChoice; ++k)
{
cout << " " << k;
}
cout << "\n";
}
else
{
cout << i << " | ";
for (int j = 1; j <= numChoice; ++j)
{
if (j*i <= 9)
{
cout << " " << j*i << "|";
}
else if (j*i > 9 && j*i <= 100)
{
cout << " " << j*i << "|";
}
else if (j*i > 99 && j*i <= 999)
{
cout << " " << j*i << "|";
}
}
cout << "\n";
for (int k = 0; k <= numChoice; ++k)
{
if (k == 0)
{
cout << "-|";
}
else
{
cout << "----|";
}
}
cout << "\n";
}
}
The following code uses no if else constructs. The formatting can be got by using setw, used for setting the width of integers.Following code produces perfect output.
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int i,j;
cout<<" "<<1;//5 space chars
for(i = 2;i <= 10;++i)
cout<<" "<<i;//4 space chars
cout<<endl;
cout<<" ----|";
for(i = 2;i <= 10;++i)
cout<<"----|";
cout<<endl;
for(i = 1;i <= 10;++i)
{
cout<<setw(2)<<i<<"|";
for(j = 1;j <= 10;++j)
cout<<setw(4)<<j*i<<"|";
cout<<endl;
cout<<" -|----";
for(j = 2;j <= 9;++j)
cout<<"|----";
cout<<"|----|";
cout<<endl;
}
return 0;
}
#FranticCode. I'm also in the same class as you and was having problems with this homework assignment as well. I still don't understand it, but I figured out how to manipulate Sumeet's code to give us correct format. The ONLY thing I am having a problem with now is adding an empty space AFTER the first multiplication table and before the menu redisplay. I'll share what I have and maybe you can figure it out. Still going to ask the professor to review chapter 5 because I would like to learn it rather than just submit the homework.
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
char userSelection;
int numForTable;
int col;
int row;
do
{
cout << "MENU" << endl
<< "a) Generate Multiplication Table" << endl
<< "q) Quit the program" << endl
<< "Please make a selection: ";
cin >> userSelection;
if (userSelection == 'a')
{
cout << "Please enter a number for your multiplication table: " << endl;
cin >> numForTable;
while (numForTable < 1 || numForTable > 10)
{
cout << "Please enter a number between 1 & 10." << endl;
cin >> numForTable;
}
cout << "\n"
<< "MULTIPLICATION TABLE: " << numForTable << "'s" << endl
<< "\n"
<< " " << 1;
for (col = 2; col <= numForTable; ++col)
cout << " " << col;
cout << endl;
cout << " ----|";
for (col = 2; col <= numForTable; ++col)
cout << "----|";
cout << endl;
for (col = 1; col <= numForTable; ++col)
{
cout << setw(2) << col << "|";
for (row = 1; row <= numForTable; ++row)
cout << setw(4) << col * row << "|";
cout << endl;
cout << " -|----";
for (row = 2; row <= numForTable - 1; ++row)
cout << "|----";
cout << "|----|";
cout << endl;
}
}
else if (userSelection != 'q')
{
cout << "Invalid Selection\n" << endl;
}
else if (userSelection == 'q')
{
cout << " You have chosen to quit the program. Thank you for using!" << endl;
}
}
while (userSelection != 'q');
//system("PAUSE");
return 0;
}
got curious to see if i could add the lines as easy as i claimed, it took a bit of fiddling, but here's the result (updated code below to also have lines).
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int counter;
int counter2;
int amount;
cout << " |-----------------------------------------------------------|" << endl; // first line of table.
for(counter=1;counter<11;counter++){ // the 2 for lines create our 2 dimensional table
for(counter2=1;counter2<11;counter2++){
cout << " | " << setw(3) << counter*counter2; // setw(3) is a function of <iomanip>,
//setting minimum width to 3 for numbers.
}
cout << " |" << endl; // this here is being added to the end of each line and starts a new line.
cout << " |-----------------------------------------------------------|" << endl; // this is being inserted between each line, and starts a new line.
}
return 0;
}
Use the following construct:
for (int i=0; i<=numChoice; i++) // display first row of numbers
cout <<"\t" << i << "\t";
cout << "\n";
for (int i=0; i <=numChoice; i++) {
cout << i << "\t";
for (int j=0; j <=numChoice; j++)
cout << i*j << "\t";
cout << "\n";
}

Unhandled exception at 0x012B1CA9

I am new to C++ and am trying to build a simple program that with the users input to proceed will generate a random left or right. I had the program working correctly until I added in the array to try and store each item as I have to output them as soon and the user would like to exit the loop. The program seems to compile fine but at run time I receive "Unhandled exception at 0x012B1CA9" Any help would be greatly appreciated.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int userSelection = 1;
const int MAX = '100';
int randNum(0);
int one (0);
int two (0);
int total(0);
int sel[MAX];
do
{
cout << "Press 1 to pick a side or 0 to quit: ";
cin >> userSelection;
for (int i = 1; i < MAX; i++)
{
srand(time(NULL));
sel[i] = 1 + (rand() % 2);
if (sel[i] == 1)
{
cout << "<<<--- Left" << endl;
one++;
total++;
}
else
{
cout << "Right --->>>" << endl;
two++;
total++;
}
}
} while (userSelection == 1);
cout << "Replaying Selections" << endl;
for (int j = 0; j < MAX; j++)
{
cout << sel[j] << endl;
}
cout << "Printing Statistics" << endl;
double total1 = ((one / total)*100);
double total2 = ((two / total)*100);
cout << "Left: " << one << "-" << "(" << total1 << "%)" << endl;
cout << "Right: " << two << "-" << "(" << total2 << "%)" << endl;
system("pause");
return 0;
};
You have a multi-character constant here... and the behavior doesn't go as expected...
Change this line
const int MAX = '100';
to
const int MAX = 100;
Note the removed single quotes.
And secondly, I will advice you to remove the Seed of the C random generator from the for loop because, you'll likely get the same values from the rand() if you always call it immediately after seeding...
But preferable use the algorithm from C++'s random header
Here is a corrected version of your original code....
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int userSelection = 1;
const int MAX = 100; // <---changed
int randNum(0);
int one (0);
int two (0);
int total(0);
int sel[MAX];
do
{
cout << "Press 1 to pick a side or 0 to quit: ";
cin >> userSelection;
srand(time(NULL)); //< moved to here
for (int i = 0; i < MAX; i++) // <-- modified starting index
{
sel[i] = 1 + (rand() % 2);
if (sel[i] == 1)
{
cout << "<<<--- Left" << endl;
one++;
total++;
}
else
{
cout << "Right --->>>" << endl;
two++;
total++;
}
}
} while (userSelection == 1);
cout << "Replaying Selections" << endl;
for (int j = 0; j < MAX; j++)
{
cout << sel[j] << endl;
}
cout << "Printing Statistics" << endl;
double total1 = ((one / total)*100);
double total2 = ((two / total)*100);
cout << "Left: " << one << "-" << "(" << total1 << "%)" << endl;
cout << "Right: " << two << "-" << "(" << total2 << "%)" << endl;
system("pause");
return 0;
};
I think that it is basically good idea to read more about C data types and declaration. Your error:
const int MAX = '100' should be const int MAX = 100 without any quotes. C++ does implicit conversion from character literals to int.

Access Violation Violation Location With Low Numbers

I'm working on an assignment for school. The code is supposed to read form a file and create an array, then sort the values of the array to output certain info. It works just fine as long as I have 3+ lines of info in the file. If not, I get the following error:
First-chance exception at 0x01305876 in Homework11.exe: 0xC0000005: Access violation reading location 0xcd71b288.
Unhandled exception at 0x01305876 in Homework11.exe: 0xC0000005: Access violation reading location 0xcd71b288.
I can't figure out why, any help would be appreciated. Here's the code:
#include <iostream> //calls the information needed
#include <iomanip>
#include <algorithm>
#include <fstream>
#include <string>
using namespace std; //sets all unmarked commands to std::
const int ARRSIZE = 1000;
struct Student
{
string firstName;
string lastName;
string id, temp;
double gpa;
};
int readArray(ifstream& ifile, Student arr[]);
void swapElements(Student arr[], int i, int j);
void sortArray(Student arr[], int numberInTheArray);
int main()
{ // Declares the needed variables
double sought, min, max;
int i, ival, returnvar, count = 0, mincount, maxcount;
string filename;
ifstream ifile;
Student arr[ARRSIZE];
cout << "Input File Name: ";//requesting the file name
cin >> filename;
ifile.open(filename.c_str());//opening the file
if (!ifile)//checking if it opened or not
{
cout << endl << "That file does not exist!" << endl;//informing the user it did
return 1;//not open and returning 1
}
cout << "Which number do you want to return? ";//requesting the desired number
cin >> ival;
i = ival - 1;
cout << endl;
returnvar = readArray(ifile, arr);
min = arr[0].gpa;
max = arr[0].gpa;
sought = arr[0].gpa;
while (count < returnvar)
{
if (arr[count].gpa < min)
{
min = arr[count].gpa;
mincount = count;
}
if (arr[count].gpa > max)
{
max = arr[count].gpa;
maxcount = count;
}
if (count == i)
{
sought = arr[count].gpa;
}
count++;
}
if (count == 0)
{
cout << "The file is empty!" << endl;
return 1;
}
cout << "Before Sort:" << endl;
cout << " Min GPA is " << min << " for " << arr[mincount].lastName << "." << endl;
cout << " Max GPA is " << max << " for " << arr[maxcount].lastName << "." << endl;
if (returnvar < ARRSIZE)
{
cout << " WARNING: Only " << returnvar << " numbers were read into the array!" << endl;
}
if (i >= returnvar)
{
cout << " There aren't that many numbers in the array!" << endl << endl;
}
else if (i > ARRSIZE)
{
cout << " " << i << " is bigger than " << ARRSIZE << "!" << endl << endl;
}
else if (i < returnvar)
{
cout << " Value " << ival << " is " << sought << " for " << arr[i].lastName << "." << endl << endl;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sortArray(arr, returnvar);
count = 0;
while (count < returnvar)
{
if (arr[count].gpa < min)
{
min = arr[count].gpa;
mincount = count;
}
if (arr[count].gpa > max)
{
max = arr[count].gpa;
maxcount = count;
}
if (count == i)
{
sought = arr[count].gpa;
}
count++;
}
cout << "After Sort:" << endl;
cout << " Array[0] GPA is " << min << " for " << arr[0].lastName << "." << endl;
cout << " Array[" << (returnvar - 1) << "] GPA is " << max << " for " << arr[(returnvar - 1)].lastName << "." << endl;
if (returnvar < ARRSIZE)
{
cout << " WARNING: Only " << returnvar << " numbers were read into the array!" << endl;
}
if (i >= returnvar)
{
cout << " There aren't that many numbers in the array!" << endl << endl;
}
else if (i > ARRSIZE)
{
cout << " " << i << " is bigger than " << ARRSIZE << "!" << endl << endl;
}
else if (i < returnvar)
{
cout << " Value " << ival << " is " << sought << " for " << arr[i].lastName << "." << endl << endl;
}
return 0;
}
int readArray(ifstream& ifile, Student arr[])
{
int counter = 0;
while ((ifile) && (counter <= ARRSIZE))
{
ifile >> arr[counter].firstName;
ifile >> arr[counter].lastName;
ifile >> arr[counter].id;
ifile >> arr[counter].gpa;
counter++;
}
return (counter - 1);
}
void sortArray(Student arr[], int numberInTheArray)
{
for (int i = 0 ; i < numberInTheArray - 1; i++)
{
for (int j = 0 ; j < numberInTheArray - 1; j++)
{
if ( arr[j].gpa > arr[j + 1].gpa)
{
swapElements(arr, j, j+1);
}
}
}
}
void swapElements(Student arr[], int i, int j)
{
Student temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
Please ignore the insanity and comments. Like I said, for an entry level course.
Try replacing counter <= ARRSIZE with counter < ARRSIZE (a rule of thumb in C is: never use <= in operations related to container sizes).
EDIT: also in your main(), you must check that i < ARRSIZE (equivalently, return error if i >= ARRSIZE). At present you seem to accept the case i == ARRSIZE, which is also wrong. And finally, readArray should return counter (that is, one more than the last written index).

A variable length bitset in C++ [duplicate]

This question already has answers here:
Define bitset size at initialization?
(7 answers)
Closed 5 years ago.
I have a working 4 bit linear feedback shift register, using 3 bitsets of length 4: inpSeq, operSeq and bit. I want to make the program accept a variable length bit sequence, so those previous bitsets should be of variable length somehow. The user may enter a sequence ofr inpSeq and the program sets the three bitsets to be of the same length as that sequence provided by the user. Any ideas for how to achieve this? Sample code if I may ask!
Here is the code:
#include <iostream> //Standard library.
#include <bitset> //Library for 10 handling.
#include <vector> //Variable size array.
#include <algorithm> //We use sorting from it.
using namespace std;
int main()
{
int y = 0;
int turnCount = 0;
int count1 = 0, count0 = 0;
bitset <4> inpSeq;
int polyLoc;
bitset <4> operSeq;
bitset <4> bit;
vector <int> xorArray;
vector <int> keyReg;
cout << "Enter a 4-bit sequence: \n";
cin >> inpSeq;
cout << "Enter polynomial:";
cin >> polyLoc;
while(polyLoc>0)
{
xorArray.push_back(polyLoc%10);
polyLoc/=10;
}
cout << "xorArray is: ";
for ( unsigned int i = 0; i < xorArray.size(); i++)
{
cout << xorArray[i] << " ";
}
sort(xorArray.rbegin(), xorArray.rend());
cout << "\n";
operSeq = inpSeq;
keyReg.push_back(inpSeq[0]);
int x = xorArray[0];
cout << "x is: " << x << "\n";
for ( unsigned int i = 0; i < xorArray.size(); i++)
{
cout << xorArray[i] << "\n";
}
cout << "bit 3 of initial " << bit[3] << "\n";
do {
for (unsigned int r = 1; r < xorArray.size(); r++)
{
bit[3] = operSeq[x];
cout << "bit 3 from prev: " << bit[3] << "\n";
y = xorArray[r];
cout << "opseq[y] is: " << operSeq[y] << "\n";
bit[3] = bit[3] ^ operSeq[y];
cout << "bit[3] after xor: " << bit[3] << "\n";
}
operSeq >>= 1;
cout <<"operSeq after shift: " << operSeq << "\n";
operSeq[3] = bit[3];
cout <<"opserSeq bit 4 after = bit[3]: " << operSeq[3] << "\n";
cout <<"new operSeq: " << operSeq << "\n";
keyReg.push_back(operSeq[0]);
turnCount ++;
cout << "--\n";
}
while ((operSeq != inpSeq) && (turnCount < 20));
cout << "Generated key is: ";
for (unsigned int k = 0; k < keyReg.size(); k++)
{
cout << keyReg[k];
}
cout << "\n";
cout << "Bit 1 positions: ";
for ( unsigned int g = 0; g < xorArray.size(); g++)
{
cout << xorArray[g];
}
cout << "\n";
cout << "Key length is: " << keyReg.size();
cout << "\n";
for ( unsigned int i = 0; i < keyReg.size(); i++)
{
if (keyReg[i]==1)
{
count1++;
}
else {
count0++;
}
}
cout << "Number of 0's: " << count0 << "\n";
cout << "Number of 1's: " << count1 << "\n";
if ( keyReg.size()%2 ==0)
{
cout << "key length is even. \n";
if (count1==count0)
{
cout << "Key is perfect! \n";
}
else {
cout << "Key is not perfect! \n";
}
}
else
{
cout << "key length is odd. \n";
if ((count1==count0+1) || (count0==count1+1))
{
cout << "Key is perfect! \n";
}
else {
cout << "Key is not perfect! \n";
}
}
cin.get();
}
std::vector has an optimization for std::vector<bool>, and the size of a vector can be set at runtime.

Loop with an array to read integers from file, sort them according to range. C++

Right now Im trying to write a program that can take an input file that has a bunch of integers, and then show the amount of numbers in certain ranges. For example:
If the input file has 20, 30, 40, 50, 60. And the ranges are 1-20, 21-40, 41-60
The output would be
1-20: 1
21-40: 2
41-60: 3
etc.
Im new to programming, so Im just having a little problem with my code, I know im close. Im using arrays to store them, but I wasnt sure how to make an array that adapts to how many integers there are in a file. So this is what I got so far. (Just for this exercise, Im trying to make the max amount the array will store 100 integers).
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int ranges(int);
int main()
{
ifstream indata;
ofstream outdata;
indata.open("scores1.txt");
outdata.open("scoresoutput.txt");
if(!indata)
{
cout << "Unable to open file" << endl;
return 1;
}
int range1=0;
int range2=0;
int range3=0;
int range4=0;
int range5=0;
int range6=0;
int range7=0;
int range8=0;
const int max=100;
int score[max];
while(indata)
{
for(int i=0; i < max ; i++)
{
indata >> score[i];
indata.ignore(1);
if(0 <= score[i] <= 24)
{
range1++;
}
else if(25 <= score[i] <= 49)
{
range2++;
}
else if(50 <= score[i] <=74)
{
range3++;
}
else if(75<= score[i] <= 99)
{
range4++;
}
else if(100 <= score[i] <= 124)
{
range5++;
}
else if(125 <= score[i] <= 149)
{
range6++;
}
else if(150 <= score[i] <= 174)
{
range7++;
}
else if(175 <= score[i]<= 200)
{
range8++;
}
}
}
outdata << "Range" << setw(10) << "Number of Students" << endl <<
"0-24" << setw(10) << range1 << endl<<
"25-49" << setw(10) << range2 << endl <<
"50-74" << setw(10) << range3 << endl <<
"75-99" << setw(10) << range4 << endl <<
"100-124" << setw(10) << range5 << endl <<
"125-149" << setw(10) << range6 << endl <<
"150-174" << setw(10) << range7 << endl <<
"175-200" << setw(10) << range8 << endl;
return 0;
}
Right now, the output just displays 0-24 100. Any easier way to do this than what I am doing now?
Array is your good friend. Try to use an array to manage the counts:
int range_count[8];
for (int i = 0; i < 8; ++i) {
range_count[i] = 0;
}
and in the for-loop inside your while-loop:
for(int i = 0; i < max ; ++i) {
indata >> score[i];
indata.ignore(1);
if (score[i] >= 0 && score[i] <= 200) {
range_count[score[i] / 25]++; // since your range intervals is a constant 25.
}
}
and finally, in the output:
outdata << "Range" << setw(10) << "Number of Students" << endl;
for (int i = 0; i < 8; ++i) {
i * 25 << "-" << i * 25 + 24 << setw(10) << range_count[i] << endl;
}