I have a program that builds a 2D array of a theater. The user can select a seat by position and the monetary amount is changed to a 0 to indicate that the seat is taken. The other method of choosing a seat selects by price. So the user enters a price, a for loop iterates through the array and finds the first instance of that price and replaces it with a 0, then stops. Or at least that's what I tried to do. In practice, it replaced all of those values with 0. I tried using a while loop to close it out once the condition is met, but that didn't work. Here's my (relevant) code.
while (flag == true)
{
cout << "\n";
cout << "You may select tickets by seat or by price. Enter 1 to select by price, or 2 to select a seat. Enter 3 if you'd like to quit." << endl;
cin >> userSelection;
if (userSelection == 1)
{
cout << "What price would you like to search for? " << endl;
cin >> priceSelection;
while (searchFlag == true)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 10; j++)
{
if (Theater [i][j] == priceSelection)
{
Theater [i][j] = 0;
searchFlag = false;
}
}
}
for (int i = 0; i < 9; i++) // This for loop is going to output our array so the user can see pricing.
{
for (int j = 0; j < 10; j++)
{
cout << Theater [i][j] << " ";
}
cout << "\n";
}
}
}
I'm not sure what really needs to change so that it'll stop after the first price is found and changed. Also, I don't mind to copy/paste the rest of my code if that's necessary.
Just some advice for the future,
Don't hardcode your loop termination conditions i.e. (i < 9). Have a current length of the array, or number of seats. That way you ever add more, this will still work.
Also even though you set search flag to false in your if statement, you will still continue through every for loop. So you will iterate through every seat, every time. If the price at the of the current seat never matches the user inputted price, you will go into an infinite loop. Try changing your inner for loop to
for (int j = 0; j < someCurrentLengthOfArray && searchFlag; j++)
That way you will check if the price matches and if you head an unspecified end of the array.
As was mentioned in one of the comments, why is this a 2D array?
Your while loop is outside the for loop, so all the replaces finish before you get back to the while loop. If you use #Dieter Lücking suggestion and just use a 1D array you can do this with one while loop
int i =0;
while (searchFlag == true)
{
// ..check for seats
if (seatFound)
{
searchFlag = false;
}
i++;
}
For 2D arrays you can still use the while loop method, it will just take two of them.
change your for loops:
for (int i = 0; i < 9 && searchFlag; i++)
{
for (int j = 0; j < 10 && searchFlag; j++)
{
if (Theater [i][j] == priceSelection)
{
Theater [i][j] = 0;
searchFlag = false;
}
}
}
The way they are now, they'll keep iterating through, until the end, no matter what. If you do as I showed above, they will break when searchFlag is set to true, and pull back out into the outer while loop, which will also then break.
Related
I am creating an idea bank to hold ideas inputted from a keyboard or from a txt file.
the idea follows the following pattern
ID:
Proposer:
keywords:
content:
i am then implementing an indexing algorithm for the idea bank using reverted index using the following struct
struct Index {
string key;
vector<int> idList;
};
where key represents a keyword in an idea and idList represent the ID for the idea.
I am then storing the index in an AVL tree.
here is my code to to create the inverted index.
void IdeaBank::AVLTreeIndexing(){
vector<string> kwords_vec;
vector<int> relevantIDs;
int foundIdIn;
string kword;
Index input;
for (int loop = 0; loop < newIdea.size(); loop++){
kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++){
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++){
if (newIdea[j].foundWordInBoth(kwords_vec[i])){
input.key = kwords_vec[i];
input.idList.push_back(newIdea[j].getID());
tree.AVL_Insert(input);
relevantIDs.push_back(input.idList[j]);
}// end of lookfor
}
}// end of kwords.size loop
}
}
my logic behind the above function is the following:
1) go through all the ideas and get the keyword
2) check if an idea contains the keyword
3) store the word as a key in my struct and store the ID in my vector in the struct
4) insert the struct into my avl tree
i am then trying to create a search function to print all the ideas that contain the word in their keyword. and this is where i believe i am having problems.
here is the code
void IdeaBank::searchQueryFromBank(string word){
Index index;
vector <int> test;
if (tree.AVL_Retrieve(word, index)){
cout << "found in tree"<<endl;
cout << "Relevant idea ID's for "
<< word << ":" << endl;
for (int i = 0; i < index.idList.size(); i++){
cout << index.idList[i] << endl;
test.push_back(index.idList[i]);
}
}
else
{
cout << "No relevant ideas found for " << word << endl;
}
cout << endl;
cout << "displaying the following Ideas"<<endl;
for (int i=0;i<test.size();i++)
{
displayIdeaByID(test[i]);
}
}
the problem i am having:
my ID list vector is being populated with numbers that dont contain the keyword.
for example say i have the two following ideas
ID: 1
Proposer: bob
keywords: computer,laptop
content: computer with built in microphone
ID: 2
Proposer: bob
keywords: smartphone
content: smartphone with built in microphone
if i was to search for the keyword "smartphone"
my result would print the following ID's
ID 0...
ID 0...
ID 1...
in my indexing function, the function foundWordInBoth is defined as
bool Idea::foundWordInBoth(string word){
if (find(keyword.begin(), keyword.end(), word) != keyword.end()){
return true;
}
size_t pos;
pos = content.find(word);
if (pos != string::npos)
{
return true;
}
return false;
the above function checks to see if a word is found in either the keyword or in the contents of the idea.
overall, i am unsure why it is printing out Ideas that do not contain a certain keyword
I would guess that the problem is here
void IdeaBank::AVLTreeIndexing(){
vector<string> kwords_vec;
vector<int> relevantIDs;
int foundIdIn;
string kword;
Index input;
for (int loop = 0; loop < newIdea.size(); loop++){
kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++){
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++){
if (newIdea[j].foundWordInBoth(kwords_vec[i])){
input.key = kwords_vec[i];
input.idList.push_back(newIdea[j].getID());
tree.AVL_Insert(input);
relevantIDs.push_back(input.idList[j]);
}// end of lookfor
}
}// end of kwords.size loop
}
}
You only declare one Index object, which you then push back IDs to for the entire execution of the function. So the list of IDs just builds and builds.
I'm finding the logic a little hard to follow because you only ever seem to have one ID for each key but clearly you need to move the declaration of input to some narrower scope.
Maybe it should look something like this (but really I'm guessing)
void IdeaBank::AVLTreeIndexing() {
for (int loop = 0; loop < newIdea.size(); loop++) {
vector<string> kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++) {
Index input;
input.key = kwords_vec[i];
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++) {
if (newIdea[j].foundWordInBoth(kwords_vec[i])) {
input.idList.push_back(newIdea[j].getID());
}// end of lookfor
}
tree.AVL_Insert(input);
}// end of kwords.size loop
}
}
In general get used to declaring variables where you need them, instead of declaring them all at the beginning of a function.
so I made a simple loop that finds out if an array has the elements with the values of 0 and 1.
if the loop indeed finds 0 or 1 inside of the array, it will say "YES", otherwise "NO".
yes, the program works just fine, but at the end of the program it prints out "YES" or "NO" as many times as i put cin>>dim to.
for example if dim which means (dimension[of the array]) is 5 it's going to print either "YESYESYESYESYES" or "NONONONONO"
I have to use return 0 in order to make it print it out like once, but I feel like this is not the right way to do it. Please help me with this. thanks!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, dim, v[100];
cin>>dim;
for(i=0;i<dim;i++)
cin>>v[i];
for(i=0;i<dim;i++)
if(v[i]==0 || v[i]==1){
cout<<"YES"; return 0;}
else{
cout<<"NO"; return 0;}
return 0;
}
The break statement can be used to break out of loops. The example from cppreference:
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 5; k++) { //only this loop is affected by break
if (k == 2) break;
std::cout << j << k << " ";
}
}
As the comment suggests, break only breaks the innermost loop.
In your code you always exit from the loop on the very first iteration, hence you do not need the loop in the first place. This will have the same output as your code:
int main() {
int i, dim, v[100];
cin >> dim;
for(i=0; i < dim; i++)
cin >> v[i];
if(v[0] == 0 || v[0] == 1) {
cout << "YES";
} else {
cout << "NO";
}
}
After reading the question again...
I made a simple loop that finds out if an array has the elements with the values of 0 and 1
If you exit the loop after checking the first element then you only check the first element. If you want to see if an array contains only 1 or 0 or it contains at least one element which is 0 or 1 (not 100% clear which one you want), then you rather need this:
bool only_zero_or_one = true;
bool one_zero_or_one = false;
for (int i = 0; i < dim; ++i) {
zero_or_one = ( v[i] == 0 | v[i] == 1);
only_zero_or_one = zero_or_one && only_zero_or_one;
one_zero_or_one = zero_or_one || one_zero_or_one;
}
Only for one_zero_or_one you can break the loop once zero_or_one == true.
Moreover, you should rather use a std::vector. In your code, if the user enters a dim which is greater than 100 you write beyond the bounds of v. This can be avoided easily:
size_t dim;
std::cin >> dim;
// construct vector with dim elements
std::vector v(dim);
// read elements
for (size_t i=0; i < v.size(); ++i) std::cin >> v[i];
// .. or use range based for loop
for (auto& e : v) std::cin >> e;
but I feel like this is not the right way to do it
Returning is an entirely right way to break out from a loop.
Another right way is the break statement, which jumps to after the loop.
Even better, you can actually check if v[i]==0 or 1 inside the input for loop immediately after taking input and set a flag to true. Depending on requirement, you can either break or wait until the entire input is read and then come out and check for flag==true and then print "YES" and print "NO" if flag==false.
This will save you running the loop again to check for 0 or 1.
I am still a beginner in C++, so I'm sorry if the question is simple.
I am trying to build a program that asks you to input names and register them to an array. Then, I need to call a function to check if there are any duplicate names. If there are any, it asks the user to input another name.
The problem I'm having is that the function is called whether or not there are duplicates, and always replaces the first name that was entered.
int checking(string stringArray[5]) {
int i, z ;
for (i = 0; i < 5; i++) {
for (z = 0; z < 5; z++) {
if (z != i) { // Makes sure don't check number against itself
if (stringArray[z] == stringArray[i]) {
return i;
}
else {
return 0;
int main(){
for (i = 0; i < 5; i++) {
cin >> stringArray[i];
}
j = checking(stringArray);
if (j == 0) {
cout << "Please re-enter name " << ". Duplicate names are not allowed"
<<'\n';
cin >> stringArray[j];
}
Some observations (ignoring the syntax errors, I assume these are not present in your actual code):
z doesn't need to start at 0 every time, it can start at i + 1 because you dont need to check pairs you have already checked (makes it simpler and runs faster)
you don't want to return in your loop, it will prevent you from checking past the first repeated name. Instead move your reenter statement into the loop.
generally you dont want to use literals (5) in a loop, instead use a variable to store the length of the array and compare to that (this is just a general programming rule, it won't change how the code runs)
Your final checking() function should look closer to:
void checking(string stringArray[5]) {
int i, z ;
// consider replacing 5 with a variable
for (i = 0; i < 5; i++) {
for (z = i+1; z < 5; z++) {
if (stringArray[z] == stringArray[i]) {
cout << "Please re-enter name " <<
". Duplicate names are not allowed" <<'\n';
cin >> stringArray[z];
/* restart the loop user may have entered a */
/* second duplicate from previous entries */
i = 0;
z=i+1;
}
}
}
}
I have been working on an assignment question for days and cannot seem to get the correct output (I've tried so many things!) The question is:
Write a program that uses two nested for loops and the modulus operator (%) to detect and print the prime numbers from 1 to 10,000.
I have been doing from 1 to 10 as a small test to ensure its working. I am getting 2,3,5,7,9 as my output, so I know something is wrong. When I increase the number from 10 to 20 it is printing 2 plus all odd numbers. I am including my code below. Thanks!!
int main() {
for (int i=2; i <=10; i++){
for (int j=2; j<=i; j++){
if (i%j==0 && j!=i) {
break;
}
else {
cout<< i <<endl;
break;
}
}
}
}
In addition to Sumit Jindal's answer inner for loop can be done by this way as well:
for(int j=2; j*j<=i ; j++)
If we think about every (x,y) ordered pair that satisfies x*y = i, maximum value of x can be square root of i.
The problem lies in the if-else branch. Your inner loop will be run exactly once because it will break out of the inner loop as a result of your if else branch.
When you first enter the inner loop the value of j is 2. Your condition will test if variable i is divisible by 2. If it is it breaks. Other wise (your else branch) will print the value of i and breaks out.
Hence printing odd numbers.
Break out of the inner loop and check whether j equals i in outer loop. You have to make j available for outer loop.
Your print statement is within the inner loop, and it should not be - it's only a prime if you run all the way through the inner loop without finding a divisor.
As a second point, you only need to check for divisors up to the square root of i, not all the way up to i.
You are breaking the inner loop after the first iteration itself, which is checking if the number(ie i) is different from j and is divisible by 2 or not (since j=2 for the first iteration)
I am getting 2,3,5,7,9 as my output
This is because every odd number fails the if and is printed in else condition
A minor correction in your code, adding a flag. Also you don't need to run the inner loop i times, infact only i/2 times is sufficient. This is simple mathematics, but will save significant number of CPU cycles (~5000 iterations lesser in your case)
#include <iostream>
int main()
{
int n = 10;
for(int i=2; i<=n; i++){
bool isPrime = true;
for(int j=2; j<=i/2; j++){
if(i!=j && i%j==0){
isPrime = false;
break;
}
}
if(isPrime)
std::cout << i << " ";
}
return 0;
}
Another version, if you don't mind output in reverse order.
int n = 10;
for (int i = n; i > 1; --i)
{
int factorCount = 0;
for (int j = 2; j <= n; ++j)
{
if (i % j == 0)
factorCount++;
if (factorCount > 1)
break;
}
if (factorCount == 1)
cout << i << endl;
}
int main() {
for (int i = 2; i <= 100; i++) {
for (int j = 2; j < i; j++) {
if (i%j == 0)
break;
if (j==i-1) // means has never run previous if blog
cout << i << endl;
}
}
return 0;
}
I am attempting to fill an array backwards from 20 to 0 but whenever I print it out it still prints out forwards. For instance I want to put in 1,2,3,4,5 and have it come out as 5,4,3,2,1.
I have attempted to do a for loop that counts backwards from 20 to 0 but when i print it it is still coming out incorrect. Any help?
int temp;
for (int i = 20; i > 0; i--)
{
cout << "Please enter the next number. Use a -1 to indicate you are done: ";
cin >> temp;
while(temp > 9 || temp < -2)
{
cout << "You may only put numbers in 0 - 9 or -1 to exit. Please enter another number: ";
cin >> temp;
}
arr1[i] = temp;
cout << arr1[i];
}
for (int i = 21; i > 0; i--)
{
cout << arr1[i];
What's the size of your array?
Assume that the size is 21 (indexes from 0 to 20).
First of all please note that your first loop will never populate the array at index 0 (something like this arr1[0] = temp will never be executed inside your first loop).
If you want to avoid this behavior you should write your first for loop like this:
for (int i = 20; i >= 0; i--){...}.
The second for loop has some issues:
You are traversing the array backwards while you want to do the opposite.
The loop starts from an index out of bound (21).
The loop may print some undefined values (You should remember the index of the last added value).
I suggest you to use other data structures like a Stack but if you want to use an array you can edit your code as follows:
int i;
for (i = 20; i >= 0; i--){...}
for (i; i <= 20; ++i) { cout << arr1[i]; }
If you don't want to declare int i; outside of the loop you can do something like that:
int lastAdded;
for (int i = 20; i >= 0; i--){
...
lastAdded = i;
}
for (int i = lastAdded; i <= 20; i++) { cout << arr1[i]; }
Edit: Note that neither your code nor mine stops asking for a new value after the insertion of a -1.
If you want to achieve this behavior you should use a while loop instead of the first for loop and check for the exit condition.