C++ Vector troubles - c++

Heres a function of my program, which keeps crashing. The purpose of the function is the search through the vectors and display what they rank and the frequency, which is read into thier respective vectors. Im guessing its my while loop but im not sure.
The vectors are correctly read in.
void searchNames(vector<string> girlsname,vector<int> girlsfeq,vector<string> boysname,vector<int> boysfeq){
string name1;
string name;
int SIZE = girlsname.size();
int SIZE2 = boysname.size();
while(name1 != "quit"){
int i=0;
int frank=find(girlsname.begin(), girlsname.end(), name1) - girlsname.begin();
int mrank=find(boysname.begin(), boysname.end(), name1) - boysname.begin();
name1.clear();
name.clear();
cout << "Please enter a name: ";
cin >> name1;
cout << endl;
while(i< SIZE && name1 !=girlsname[i++]){
frank++;
}
name.clear();
i=0;
while(i< SIZE2 && name1 !=boysname[i++]){
mrank++;
}
cout << left << setw(15) << "Name" << right << setw(10) << "Girl Rank" << right << setw(10) << "Frequency" << right << setw(10) << "Boy Rank"<< right << setw(10) << "Frequency" << endl;
if(frank != SIZE && mrank != SIZE2){
cout << left << setw(15) << name1 << right << setw(10) << frank << right << setw(10) << girlsfeq[frank] << right << setw(10) << mrank << right << setw(10) << boysfeq[mrank] << endl;
}
}

First, in any of your loops, you don't change the value of i, so they are potentially infinite.
Second, if I understand what you're trying to do, you have paired vectors and you search for an index on which the name is in the first vector and then use it to get the value from second vector. You can use std::find function for that:
int frank = find(girlsname.begin(), girlsname.end(), name1) - girlsname.begin();
Now, you can access the girlsfreq[frank] value. If the name is not present in the vector, the frank equals size of the vector, which you have to check for. Don't forget to add include:
#include <algorithm>

I am not able to reproduce your crash. Instead, I am able to reproduce an infinite loop. Taking a closer look to your while loops, it becomes evident: the value of i is never changing. If it cannot find a name match, it will keep incrementing the value of frank. So, a fix to this problem would be:
while(i < SIZE && name1 != name) {
name = girlsname[i];
frank++;
i++;
}
But it can be improved: you don't need that assignment. Also, you can use the advantage of the postfix increment:
while(i < SIZE && name1 != girlsname[i++]){
frank++;
}
Doing this, you also remove the necessity of name and name1.

Related

My program compiles and runs but does not do any of the 6 options in the switch statements and I cannot figure out why

http://pastebin.com/Em641fNe
I believe the problem is in the binarySearch function, but I'm not entirely sure. First, I pick choice 1 and input values. Then, I pick choice 4 just to check it's there and that both the binary and the display function work, but it automatically displays the message: "That name does not exist in the array."
Also, the Test Case Input is:
1
GoogleNexus7
GN7862
17
89.99
1
IPhone6
725365
5
349.99
1
MacbookAir
268748
12
599.00
5
6
void displayInfo(Product inventory[], int numProduct)
{
int i;
string name;
cout << "Enter product name of product to find: ";
cin >> ws;
getline(cin, name);
i = binarySearch(inventory, MAX_INVENTORY, name);
if (i < 0)
cout << "That name does not exist in the array.\n";
else
{
cout << "Product Name: " << name << endl;
cout << "Locator: " << inventory[i].locator << endl;
cout << "Quantity: " << inventory[i].quantity << endl;
cout << fixed << showpoint << setprecision(2);
cout << "Price: " << inventory[i].price << endl;
}
}
int binarySearch(Product inventory[], int size, string name)
{
int first = 0, // First array element
last = size - 1, // Last array element
middle, // Mid point of search
position = -1; // Position of search value
bool found = false;
// Flag
while (!found && first <= last)
{
middle = (first + last) / 2; // Calculate mid point
if (inventory[middle].name == name) // If value is found at mid
{
found = true;
position = middle;
}
else if (inventory[middle].name > name) // If value is in lower half
last = middle - 1;
else
first = middle + 1; // If value is in upper half
}
return position;
}
(My program is a bit lengthy, but please, please, please, bear with me. I've worked as hard as I possibly can by myself and simply cannot. Haven't slept :/...Thank you in advance for helping)
Just some things I could find when checking the code:
You are passing numProduct to your add function by value and not by reference. Use refernces where the value might change inside the function.
You are not updating the name of your inventory entry in your add function.
Also in you shouldn't pass MAX_INVENTORY to your displayInven but numProduct.

How do I swap a pre defined array element using an index?

I'm trying to swap two array elements that are initialized strings (see code below), I thought i knew how to do it but the way I tried doesn't seem to be working. We're not allowed to use the function "swap" that I've seen on many other forum sights with a similar question as mine. Therefore I've used a temporary index variable to swap them but that doesn't seem to be working. Not sure how to fix it and make it work, so my question is how do I do it.
I'm pretty new to programming so the answer may not be as evident to me yet. I've been staring at this for a while and still can't see it, I also tried asking on reddit but they didn't give me a very concise or helpful answer. If you could help me out as to why it wont swap the elements that would be great and if you see any other bugs or improvements I could make please let me know, your feedback is greatly appreciated, thank you!
Code:
#include <iostream>
using namespace std;
void printArray(string names[]) {
for (int i = 0; i < 7; i++) {
cout << names[i] << " ";
}
}
int main() {
int x = 0, a, b;
string answer, name1, name2;
string index;
string names[7] = {"John", "Dave", "Jim", "Amanda", "Kelsey", "Don", "Jennifer"};
printArray(names);
while (x < 1) {
cout << endl << "Do you want to swap students? " << endl;
cin >> answer;
if (answer == "Yes" || answer == "yes") {
cout << "Who would you like to swap?" << endl;
cin >> name1;
for(a = 0; a < 7; a++) {
if (names[a] == name1) {
cout << "Yes, " << name1 << " is in the line." << endl;
}
}
cout << "Who would you like to swap " << name1 << " for?" << endl;
cin >> name2;
for(b = 0; b < 7; b++) {
if (names[b] == name2) {
cout << "Yes, " << name2 << " is in the line!!" << endl;
index = names[a];
names[a] = names[b];
names[b] = index;
printArray(names);
}
}
} else {
cout << endl << "Thanks, please behave now, students!" << endl;
x++;
}
}
return 0;
}
More context:
Print out the current class line-up (i.e., the current contents of the array, in order).
Present the user with a prompt asking if they would like to swap 2 students.
If they say yes, proceed to step 3.
Ask the user for the names of the two students to be swapped.
If the two students are both in the array, swap their positions in the array. If either student is not in the class, print an error message on the console, e.g. "Sorry, you have to pick 2 students who are in the line!".
No matter the outcome of step 4, return to step 1.
While searching for name1 ,the loop runs till 7 no matter if its found or not which messes with your swapping task:
index = names[a]; //a=7
names[a] = names[b]; //a=7
names[b] = index;.
Use break:
if (names[a] == name1) {
cout << "Yes, " << name1 << " is in the line." << endl;
break;
}
The value of a is always 7 while swapping is being done! So it is not working.

What container to use when I need to know both the max value and who has achieved it?

I'm trying to work through the beginner exercises from a website.
"Requires:
variables, data types, and numerical operators
basic input/output
logic (if statements, switch statements)
loops (for, while, do-while)
arrays
Write a program that asks the user to enter the number of pancakes eaten for breakfast by 10 different people (Person 1, Person 2, ..., Person 10)
Once the data has been entered the program must analyze the data and output which person ate the most pancakes for breakfast."
I'm unsure on how to get the program to call out the person which enters the most number of pancakes eaten? Surely this would need to be done with a key and value, but the requirements state 'arrays' but not 'maps'?
Below is the code I have come up with, but this only outputs the maximum number of pancakes eaten, so not really answering the question!
Thanks so much for any help!
* I've only used 5 people to quicken the process before I know exactly how to do it *
#include <iostream>
using namespace std;
int main()
{
cout << "how many pancakes did you eat for breakfast?" << endl;
int person1, person2, person3, person4, person5;
cout << "Person 1: ";
cin >> person1;
cout << "Person 2: ";
cin >> person2;
cout << "Person 3: ";
cin >> person3;
cout << "Person 4: ";
cin >> person4;
cout << "Person 5: ";
cin >> person5;
int array[5] = {person1, person2, person3, person4, person5};
int temp = 0;
for (int i = 0; i<5; i++)
{
if (array[i] > temp)
{
temp = array[i];
}
}
cout << "The most pancakes eaten was " << temp << "by " << endl;
}
Surely this would need to be done with a key and value
This is not the only way of doing it. Another way is to use an indexed collection with no key, and make an assumption that position k corresponds to a key k that can be computed from a position alone. For example, if you have an array of ten items corresponding to ten people numbered 1 through 10, then the data for a person number k could be stored in the array at position k-1. No keys are required in this situation.
This long explanation means that if you store the best i in addition to best tmp, you'll have your answer after the loop:
int temp = 0;
int res = -1;
for (int i = 0; i<5; i++) {
if (array[i] > temp) {
temp = array[i];
res = i;
}
}
cout << "The most pancakes eaten was " << temp << "by " << (res+1) << endl;
Note the res+1 is printed, not res. This is because arrays are zero-based, while counting is one-based.
This could be further shortened using a common idiom of using the initial element as the current best, and starting your iterations from 1:
int res = 0;
for (int i = 1 ; i<5 ; i++) {
if (array[i] > array[res]) {
res = i;
}
}
cout << "The most pancakes eaten was " << array[res] << "by " << (res+1) << endl;
What if you kept track of the maximum amount of pancakes eaten as you took input?
#include <iostream>
using namespace std;
// To execute C++, please define "int main()"
int main() {
int numPeople = 5;
int maxPancakes = -1;
int maxPerson = -1;
int currentPancakes = -1;
for (int i = 1; i < numPeople; i++) {
cout << "Person " << i << ": ";
cin >> currentPancakes;
if (currentPancakes > max) {
max = currentPancakes;
maxPerson = i;
}
}
cout << "Person " << maxPerson << " ate the most pancakes: " << maxPancakes;
return 0;
}
Note: my c++ is pretty rusty, I haven't tested this solution. Just an idea ;)
Using Map for this question will be an overkill. Array is more than enough. You don't even need to iterate through the array to check who ate the most. The operation for getting the max is actually O(0) because we can update who ate the most as you are entering the values.
int main(){
const int NUM_PEOPLE = 10;
int cakesEaten[10] = {0};
int maxEaten = 0;
int personId = 0;
cout << "How many pancakes eaten by:" << endl;
for(int x=0; x<NUM_PEOPLE; x++){
cout << "person " << (x+1) << ":";
cin >> cakesEaten[x];
if (cakesEaten[x] > maxEaten){
maxEaten = cakesEaten[x];
personId = x;
}
}
cout << "The most pancakes was eaten by person " << personID << endl;
}
You don't need any storage at all.
As the numbers are entered, compare them and store who has the current max, and its value
Starting with fake values is not needed if you use the first person's value as the start value, this way negative values, could be included if entered. That may be nonsensical here, but in general, its a better practice.
Also note if we want people to start at 1, then it makes more sense to start it at 1, then start at 0 and try to remember to always add 1.
This is also very easy to expand to more people, just change total_people
int main() {
const int total_people=5;
cout << "how many pancakes did you eat for breakfast?" << endl;
int what;
cout << "Person 1: ";
cin >> what;
int who=1;
int max_value=what;
for (int person = 2; person <= total_people; ++person) {
cout << "Person " << person << ": ";
cin >> what;
if (what > max_value) {
max_value=what;
who=i;
}
}
cout << "The most pancakes eaten was " << max_value << "by " << who << endl;
}

Reading and diaplaying a character array from a file in c++

I'm trying to write a program where a name and number of votes are read from a file. However I can't get the char array to read properly from the file.
void Output(char candidateLastName[][10], long votesRecieved[])
{
ifstream Electionr("Election.dat");
int loop = 0;
cout << left << setw(10) << "Candidate" << setw(5) << "Votes" << endl;
Electionr >> candidateLastName[0][10];
Electionr >> votesRecieved[0];
cout << setw(10) << candidateLastName[0] << setw(5)
<< votesRecieved[0] << endl;
for(int loop = 1; loop < 5; loop++)
{
Electionr >> candidateLastName[0][10];
Electionr >> votesRecieved[loop];
cout << setw(10) << candidateLastName << setw(5)
<< votesRecieved[loop] << endl;
}
Electionr.close();
}
While the numbers from the file read properly, the characters will not.
Electionr >> candidateLastName[0][10];
This is reading in a single character. Ignore for a moment that it's reading into the wrong location (the first character of the string at index 1)... I suspect that you want to do something like:
Electionr >> candidateLastName[0];
Also, I presume in your loop you want to use the loop variable instead of 0 to index the array. In that case, why did you not start your loop at zero and avoid duplicating that code?
for(int loop = 0; loop < 5; loop++)
{
memset( &candidateLastName[loop], 0, 10 );
Electionr >> candidateLastName[loop];
Electionr >> votesRecieved[loop];
cout << setw(10) << candidateLastName[loop] << setw(5)
<< votesRecieved[loop] << endl;
}
(I've also made a minor fix to the cout call above)
Be aware that you may need to explicitly null-terminate your strings (I forced that in my modified loop, but only if you happen to read 9 characters or less - otherwise you will overflow and have problems). I'm not sure if this is handled when reading into character arrays with the >> operator. I never do it for something like this. I use std::string instead.
Your first read should be:
Electionr >> candidateLastName[0];
And within your loop, you want:
Electionr >> candidateLastName[loop];
But, you are assuming each name will be at most 9 characters long (plus one for the null termination).
It would be safer to make your name array and array of std::string.
void Output(std::string candidateLastName[], long votesRecieved[])
First off you've got an out of bounds index on the array. Also, you're always writing to the first element. Also you shouldn't use raw arrays like that. IF you're going to use a fix sized array, at least use a std::array. But in this case std::string is most appropriate.
Anyway, it's hard to tell what you actually want, but here's my best guess at how to rewrite the code.
std::map<std::string, unsigned long> Output()
{
std::map<std::string, unsigned long> data;
ifstream Electionr("Election.dat");
cout << left << setw(10) << "Candidate" << setw(5) << "Votes" << endl;
while(Electionr.good()){
std::string name;
unsigned long votes = 0;
getline(Electionr, name, ' ');
Electionr >> votes;
data[name] = votes;
cout << setw(10) << name << setw(5)
<< votes << endl;
}
return data;
}

Sudoku game design problems C++

I have (yet another) question about chars. Thanks to those who helped me with this before. I'm trying to do mainly 4 things at this point in the program. That is:
Build a 2D array 9x9 and fill it with underscores.
Ask for a row/column and then the number that the user wishes to go into that row/column as many times as the user wants.
Replace the specified blanks with the specified numbers.
Output the entire 9x9 char array on an ASCII art Sudoku board.
(Solving will come later.)
My problem is that when I enter the row/column and the number that I want to go into that row/column the dash that was originally in that spot disappears, but the number I entered does not appear in its place.
Here is the code so far:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main () {
//Builds 9x9 char array.
char dash[9][9];
for (int array=0; array<9; array++) {
for (int array2=0; array2<9; array2++) {
dash[array][array2]='_';
}
}
cout << "Input the row #, then the column #, then the number that you wish to fill that spot." << endl;
cout << "Remember that a Sudoku board is 9x9." << endl;
cout << "When you wish to finish input and solve, type all 0's and press enter." << endl;
int rowb;
char row[99];
int columnb;
char column[99];
int numb;
char num[99];
//Inputs the row/column and number to go into specified row/column.
int control=0;
while (rowb!=0){
control++;
cout << "Row: ";
cin >> rowb;
cout << "Column: ";
cin >> columnb;
cout << "Number: ";
cin >> numb;
row[control]=rowb-1;
column[control]=columnb-1;
num[control]=numb;
}
int length;
length=strlen(row);
//Replaces the _'s in the specified rows/columns and replaces them with the integer the user specified. This is where I think I'm having the problem.
for (control=0; control<length; control++) {
dash[row[control]][column[control]]=num[control];
}
//Builds the Sudoko board and outputs the full 9x9 array.
cout << "╔═══════════╦═══════════╦═══════════╗" << endl;
for (int count=0; count<3; count++) {
for (int count2=0; count2<3; count2++) {
cout << "║_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "║" << endl;
}
cout << "╠═══════════╬═══════════╬═══════════╣" << endl;
for (int count=3; count<6; count++) {
for (int count2=0; count2<3; count2++) {
cout << "║_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "║" << endl;
}
cout << "╠═══════════╬═══════════╬═══════════╣" << endl;
for (int count=6; count<9; count++) {
for (int count2=0; count2<3; count2++) {
cout << "║_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "║" << endl;
}
cout << "╚═══════════╩═══════════╩═══════════╝" << endl;
return 0;
}
There is a problem assignment of the number entered in the loop.
//Replaces the _'s in the specified rows/columns and replaces them with the integer the user specified. This is where I think I'm having the problem.
for (control=0; control<length; control++) {
dash[row[control]][column[control]]=num[control]; //<<<--- Assignment issue.
}
You are assigning an integer value in a character array & thus when you display you will get the corresponding char for the ascii value & not the integer. Try changing the assignment as follows:
//Replaces the _'s in the specified rows/columns and replaces them with the integer the user specified. This is where I think I'm having the problem.
for (control=0; control<length; control++) {
dash[row[control]][column[control]]=num[control] + '0'; // Convert to ascii value of the integer, but will fail if not b/w 0 & 9.
}
Checking if the number entered in is between 1 & 9 is also advised if you choose to use the above observation.
Please add checks for the row & column entered as enter values which are not b/w 1 & 9 will lead to undefined behaviour due to accessing out of bound array elements if the values entered are not b/w 1 & 9.
Also as mentioned by Benjamin Lindley please update strlen code.
Hope this helps!
length=strlen(row);
This is undefined behavior, because row[0] was never initialized, and you never null terminate the string.
char row[99];
...
int control=0;
while (rowb!=0){
control++;
...
row[control]=rowb-1;
...
Notice that the first time through the loop, control is 1. So, you're setting the value of row[1], but not row[0]. Move the increment to the end of the loop. There may be some other problems, but this is the primary one responsible for the behavior you're seeing.
Also, for strlen to work, you need to null terminate the string.
And finally, you're making the same mistake you've made in this question and this question. Why aren't you seeming to get that? Chars display differently than ints. The following code will not display the number 1:
char c = 1;
std::cout << c;
Look at the answers to those other two questions.