as recommended I've been working through the book 'Jumping into c++'. I'm currently on problem 7 of chapter 5 and although I have produced the code that appears to do what is asked of me I was hoping someone might be able to take a look and tell me if I've implemented any 'bad' practice (Ideally I don't want to be picking up bad habits already).
Secondly, it also says 'try making a bar graph that shows the results properly scaled to fit on your screen no matter how many results were entered'. Again, the code below produces a horizontal bar graph but I'm not convinced that if I had say 10000 entries (I guess I could verify this by adding an additional for loop) that it would scale according. How would one go about applying this? (such that it always properly scales regardless of how many entries).
I should probably point out at this point that I have not covered topics such as arrays, pointers and classes as of yet in case anyone was curious as to why I didn't just create a class called 'vote' or something.
One final thing... I don't have a 'return 0' in my code, is this a problem? I find it slightly confusing as to what exactly the point of having return 0 is. I know that it's to do with making sure your code is running properly but it seems sort of redundant?
Thanks in advance!
#include <iostream>
using namespace std;
int main()
{
int option;
int option_1 = 0;
int option_2 = 0;
int option_3 = 0;
cout << "Which is your favourite sport?" << endl;
cout << "Tennis.. 1" << endl;
cout << "Football.. 2" << endl;
cout << "Cricket.. 3" << endl;
cin >> option;
while(option != 0)
{
if(option == 1)
{
option_1++;
}
else if(option ==2)
{
option_2++;
}
else if(option ==3)
{
option_3++;
}
else if(option > 3 || option < 0)
{
cout << "Not a valid entry, please enter again" << endl;
}
else if(option ==0)
{
break;
}
cout << "Which is your favourite sport?" << endl;
cout << "Tennis.. 1" << endl;
cout << "Football.. 2" << endl;
cout << "Cricket.. 3" << endl;
cin >> option;
}
cout << "Option 1 (" << option_1 << "): ";
for(int i = 0; i < option_1; i++)
{
cout << "*";
}
cout << "" << endl;
cout << "Option 2 (" << option_2 << "): ";
for(int i = 0; i < option_2; i++)
{
cout << "*";
}
cout << "" << endl;
cout << "Option 3 (" << option_3 << "): ";
for(int i = 0; i < option_3; i++)
{
cout << "*";
}
}
About the return 0 in main : it's optional in C++.
About your code:
You have a ton of if / else if blocks, you should replace them with a switch. A switch statement is more compact, readable, and may be a little bit faster at runtime. It's not important at this point, but it's pretty good practice to know where to put a switch and where to use regular if.
You have one big function, it's really bad. You should break your code into small, reusable pieces. That's something called DRY (Don't repeat Yourself): if you are copy-pasting code, you're doing something wrong. For example, your sport list appears 2 times in your code, you should move it in a separate function.
You wrote cout << "" << endl;, I think you don't really understand how std::cout work. std::cout is an object representing the standard output of your program. You can use operator<< to pass values to this standard output. std::endl is one of these values you can pass, strings are, too. So you can just write cout << endl;, no need for an empty string.
Please learn how to use arrays, either raw ones or std::array. This is a pretty good example of a program which can be refactored using arrays.
Here is a more readable, cleaner version of your code:
#include <iostream>
int prompt_option()
{
int option;
while (true)
{
std::cout << "Which is your favourite sport?" << std::endl;
std::cout << "Tennis.. 1" << std::endl;
std::cout << "Football.. 2" << std::endl;
std::cout << "Cricket.. 3" << std::endl;
std::cin >> option;
if (option >= 0 && option <= 3)
return option;
else
std::cout << "Not a valid entry, please enter again" << std::endl;
}
}
void display_option(int number, int value)
{
std::cout << "Option " << number << " (" << value << "): ";
while (value--)
std::cout << '*';
std::cout << std::endl;
}
int main()
{
int option;
int values[3] = {0};
while (true)
{
option = prompt_option();
if (option)
values[option - 1]++;
else
break;
}
for (int i = 0; i < 3; i++)
display_option(i + 1, values[i]);
}
You have too much if else, it messy.
check out the code bellow, muc shorter, cleaner and efficent.
I hope it helps.
#include <iostream>
using namespace std;
int main()
{
int choice;
int soccer=0, NFL=0 ,formula1=0;
while(choice != 0){
cout<<"Please choose one of the following for the poll"<<endl;
cout<<"press 1 for soccer, press 2 for NFL, press 3 for formula 1"<<endl;
cout<<"Press 0 to exit"<<endl;
cin>>choice;
if(choice==1){
soccer++;
}
else if(choice==2){
NFL++;
}
else if(choice == 3){
formula1++;
}
else{
cout<<"Invalid entry, try again"<<endl;
}
cout<<"soccer chosen "<<soccer<<" times.";
for(int i=0; i<soccer; i++){
cout<<"*";
}
cout<<endl;
cout<<"NFL chosen "<<NFL<<" times.";
for(int j=0; j<NFL; j++){
cout<<"*";
}
cout<<endl;
cout<<"formula1 chosen "<<formula1<<" times.";
for(int c=0; c<formula1; c++){
cout<<"*";
}
cout<<endl;
}
return 0;
}
Related
I'm working on a program that I've seen other people do online except I'm trying to use functions to complete it to make it somewhat more challenging for me to help me better understand pointers and vectors. The problem I'm having in xcode is I keep getting this error..
Expected ';' after top level declarator
right here on my code,
void showMenu(menuItemType (&menu_List)[8])[], vector<int> numbers) //<<< Error
{
cout << fixed << setprecision(2);
...
Where I am trying to use vector numbers in my function. Basically I want the numbers from the function passed back so that I can use them in another function I have not created yet. I've googled this error and it seems like no one can give a straight answer on how to fix this problem. Is anyone familiar with how to correct this? By no means is this code finished I'm just trying to get information regarding vectors as a parameter because from what I'm seeing syntax wise on other sites it looks to be correct. Thanks for your feedback.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
#include <iterator>
using namespace std;
struct menuItemType{
string menuItem;
double menuPrice;
};
void getData(menuItemType (&mlist)[8]);
void showMenu(menuItemType (&menu_List)[8], vector<int> numbers);
int main() {
vector<int> temp;
menuItemType menuList[8];
getData(menuList);
showMenu(menuList,temp);
/*
cout << menuList[0].menuItem << " " << menuList[0].menuPrice << endl;
cout << menuList[1].menuItem << " " << menuList[1].menuPrice << endl;
*/
return 0;
}
void getData(menuItemType (&mlist)[8]){
string Str;
ifstream infile;
infile.open("cafe135.txt");
if(infile.is_open())
{
for (int i = 0; i < 8; ++i){
infile >> mlist[i].menuItem >> mlist[i].menuPrice;
}
}
else cout << "Unable to open file";
}
void showMenu(menuItemType (&menu_List)[8])[], vector<int> numbers)
{
cout << fixed << setprecision(2);
string choice;
cout << "Would you like to view the menu? [Y] or [N]: ";
cin >> choice;
cout << endl;
int x = 3;
int count = 1;
while (choice != "Y" && choice != "N" && choice != "y" && choice != "n")
{
if (count == 4){
return;
}
cout << "Error! Please try again ["
<< x
<< "] selections remaining: ";
cin >> choice;
cout << endl;
x--;
count++;
}
if (choice == "N" || choice == "n"){
return;
}
else
{
cout << "___________ Breakfast Menu ___________" << endl;
for (int i = 0; i < sizeof(menu_List)/sizeof(menu_List[0]); ++i)
{
cout << "Item "
<< (i+1)
<< ": "
<< menu_List[i].menuItem
<< " "
<< menu_List[i].menuPrice
<< endl;
}
cout << endl;
string itemSelection = " ";
//int str_length = 0;
cout << "Select your item numbers separated"
<< " by spaces (e.g. 1 3 5) Select 0 to cancel order: ";
cin.ignore();
getline(cin, itemSelection);
if (itemSelection == "0")
{
return;
}
vector<int> vectorItemSelection;
stringstream text_stream(itemSelection);
string item;
while (getline(text_stream, item, ' '))
{
vectorItemSelection.push_back(stoi(item));
}
int n = vectorItemSelection.size();
int arr[n];
for (int i = 0; i < n; i++)
{
arr[i] = vectorItemSelection[i];
}
}
}
Compare how menu_List is declared in this line
void showMenu(menuItemType (&menu_List)[8], vector<int> numbers);
and this line
void showMenu(menuItemType (&menu_List)[8])[], vector<int> numbers)
The first one is correct.
But I have to agree with the comments above, you are mixing up a lot of different things here. Just use vectors, 99% of the time it's the right thing to do anyway. and it's easier to learn one thing at a time.
Prefer to write your code like this
void getData(vector<menuItemType>&);
void showMenu(vector<menuItemType>&, vector<int> numbers);
int main() {
vector<int> temp;
vector<menuItemType> menuList(8);
...
See? Just use vectors everywhere.
I have decided to make an anagram solver for my dad. I am quite new to programming, but i figured I can still make it. My finished product works, but it is really slow, for instance it took about 15+ mins to find all combinations of 8 characters. I am looking for ways to optimize it / make it faster.
Working with MinGW c++ compier, on Clion 2019.3.4, cpu: i7 9700k, and RAM: 16GB/3200mhz.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
//Menu for interacting with user, not really important
void menu() {
cout << "=========================" << endl;
cout << "======== !WOW! ==========" << endl;
cout << "=========================" << endl;
cout << "1 ... INSERT" << endl;
cout << "2 ... PRINT" << endl;
cout << "3 ... LIMIT WORD LENTGH" << endl;
cout << "4 ... NEW GAME" << endl;
cout << "0 ... EXIT" << endl;
cout << "=========================" << endl;
cout << "Select: ";
}
//Function to find all possible combinations from letters of a given string
void get(vector<string> &vec, string str, string res) {
vec.push_back(res);
for (int i = 0; i < str.length(); i++)
get(vec, string(str).erase(i, 1), res + str[i]);
}
//Only for testing purposes
void printVec(vector<string> vec) {
for (int i = 0; i < vec.size(); i++) {
cout << vec[i] << " ";
}
}
//Function to check if a given word exists in given .txt file
bool checkWord(vector<string> &vec2, string filename, string search) {
string line;
ifstream myFile;
myFile.open(filename);
if (myFile.is_open()) {
while (!myFile.eof()) {
getline(myFile, line);
if (line == search) {
vec2.push_back(line);
return true;
}
}
myFile.close();
} else
cout << "Unable to open this file." << endl;
return false;
}
int main() {
int selection;
bool running = true;
string stringOfChars;
vector<string> vec;
vector<string> vec2;
do {
menu();
cin >> selection;
switch (selection) {
case 1:
cout << "Insert letters one after another: ";
cin >> stringOfChars;
get(vec, stringOfChars, ""); //fill first vector(vec) with all possible combinations.
break;
case 2:
for (int i = 0; i < vec.size(); i++) {
if (checkWord(vec2, "C:/file.txt", vec[i])) { //For each word in vector(vec) check if exists in file.txt, if it does, send it in vector(vec2) and return true
//Reason for vec2's existence is that later I want to implement functions to manipulate with possible solutions (like remove words i have already guessed, or as shown in case 3, to limit the word length)
cout << vec[i] << endl; //If return value == true cout the word
}
}
break;
case 3:
int numOfLetters;
cout << "Word has a known number of letters: ";
cin >> numOfLetters;
for (int i = 0; i < vec2.size(); i++) { /*vec2 is now filled with all the answers, we can limit the output if we know the length of the word */
if (vec2[i].length() == numOfLetters) {
cout << vec2[i] << endl;
}
}
break;
case 4:
vec.clear();
vec2.clear();
break;
case 0:
running = false;
break;
default:
cout << "Wrong selection!" << endl;
break;
}
cout << endl;
} while (running);
return 0;
}
file.txt is filled with all words in my language, It's alphabetically ordered and it's 50mb in size.
aachecnska
aachenskega
aachenskem
aachenski
.
.
.
bab
baba
babah
.
.
.
Any recommendations or off topic tips would be helpful. One of my ideas is to maybe separate file.txt in smaller files, like for example putting lines that have same starting letter in their own file, so A.txt would only contain words that start with A etc... And than change the code accordingly.
this is where you need to use a profiler. on Linux, my favorite is kcachgrind
http://kcachegrind.sourceforge.net/html/Home.html
it gives you line-by-line timing information and tells you which part of the code you should optimize the most.
of course, there are many profilers available, including commercial ones.
I've started to learn how to code in C++ on my spare time, using different sites and apps that someone who has also learned C++ online provided me with. By now, I know the most basic commands. I've tried an exercise given by a program, and I'm given the information that someone is going on a vacation, and needs to know how much baggage he can bring with him. The limit to how many baggages he can carry is 45, and I have to display a different output if the baggages are below, above or the same as the limit (45 baggages). I have done some coding, and I ended up with this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
cout << "Please type your number here: ";
cin >> bag;
string yn;
int keep = 0;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
++keep;
while(keep > 0)
{
int keep = 0;
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
if(yn == "yes")
{
int bag = 0;
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
}
else
{
return 0;
}
}
}
I have developed it more than needed -as you can see-, out of my own interest in the problem. I have copied and pasted the 3 IF commands as seen above, and I believe that there is an easier way, with less code, do solve this. What I have thought of is if I could go back and execute some line of code again, either from a line and below (e.g. from line 45 and below), or specific lines of code (e.g. from line 45 to line 60).
I would appreciate it if you thought of another way to solve this problem and posted your code below.
Thank you for your reply.
We all started writing our first C++ program at some time, so allow me to give you some additional feedback:
First of all, avoid writing using namespace std;
Secondly, naming - what is bag, limit, keep and yn? Wouldn't it be much easier to read and understand if they were called bagSize, maximumPermittedBagSize, inputFromUser (you don't really need the variable keep, see below)?
Finally, here is a (roughly) refactored version your program, with duplication removed and comments added.
#include <iostream>
int main()
{
const int maximumPermittedBagSize = 45;
// Loops forever, the user exits by typing anything except 'yes' laster
while(true)
{
std::cout << "Please type your number here: " << std::endl;
//Declare (and initialize!) variables just before you need them
int bagSize = 0;
std::cin >> bagSize;
if (bagSize > maximumPermittedBagSize)
{
std::cout << "You passed the limit." << std::endl;
}
else if (bagSize == maximumPermittedBagSize )
{
std::cout << "Just enough." << std::endl;
}
else
{
std::cout << "You got space." << std::endl;
}
std::cout << "Do you want to try another number?" << std::endl;
std::string inputFromUser = "";
std::cin >> inputFromUser;
std::cout << std::endl;
//Leave the loop if the user does not answer yes
if(inputFromUser != "yes")
{
return 0;
}
}
}
You can simply run a while loop and do like this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
string yn = "yes";
while(yn == "yes")
{
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
}
else if (limit == bag)
{
cout << "Just enough." << endl;
}
else if (limit > bag)
{
cout << "You got space." << endl;
}
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
}
}
So, I'm super new to C++ and am sharing a book with a friend. I'm creating a simple guessing game, where the user imagines a number, and the computer attempts to guess it. When I debug in Visual Studio, the project does make a guess, and properly prints "how did I do?". At this point, it should get user input for the 'feedback' variable. After the prompt, however, it seems as if it will only repeat everything before the 'while' statement. Does the problem concern the feedback char variable (maybe I should've just used 'cin' and integers?), or am I just missing something really obvious?
//Game that attempts to guess a number from one to twenty.
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
auto lowbound = 1;
auto highbound = 20;
auto guess = 10;
auto gamecont = true;
char feedback[1];
cout << " Pick a number from one to twenty in you head and I'll guess it; no cheating!" << endl << endl;
cout << " If my guess is too low, just say (1). If too high, say (2). Say (3) if I've got it. It's (ENTER) to get going!" << endl << endl;
cout << " Waiting on you..." << endl << " ";
cin.get();
while(gamecont)
{
cout << " I'm thinking your number is " << guess << "." << endl << endl;
cout << " How did I do?" << endl << endl << " ";
cin.get(feedback, 1);
if (feedback[1] == 1) // The guess was too low.
{
if (guess == 10)
{
guess = 15;
}
else if (guess >= 15)
{
guess++;
}
else if (guess < 10)
{
guess++;
}
}
else if (feedback[1] == 2) // The guess was too high.
{
if (guess == 10)
{
guess = 5;
}
else if (guess <= 5)
{
guess--;
}
else if (guess > 10)
{
guess--;
}
}
else if (feedback[1] == 3) // The guess was correct.
{
gamecont = false;
}
}
return 0;
}
Sorry if this question is stupid for whatever reason, and thanks in advance for reading.
a journey of a thousand miles begins with a single step, so here´s some aid for your first step:
using namespace std;
don´t do that. std:: is crowded with identifiers you might use too, problems are guaranteed.
char feedback[1];
You´ll never have input longer than 1, so
char feedback;
is more than appropriate. (besides: arrays are 0 based so it should have been char feedback[0]; instead of char feedback[1];)
cout << " Pick a number from one to twenty in you head and I'll guess it; no cheating!" << endl << endl;
std::endl flushes the buffer, no need to do that twice. Simply use '\n':
std::cout << " Pick a number from one to twenty in you head and I'll guess it; no cheating!" << "\n\n";
you´ll get the character code of the key in feedback. '1' is not equal to 1, so
if (feedback == 1)
should be
if (feedback == '1')
Thats it. There still some work remaining to do for you, e.g. the guessing strategy is poor, but that should be a start.
//Game that attempts to guess a number from one to twenty.
#include <iostream>
int main()
{
auto lowbound = 1;
auto highbound = 20;
auto guess = 10;
auto gamecont = true;
char feedback;
std::cout << " Pick a number from one to twenty in you head and I'll guess it; no cheating!" << "\n\n";
std::cout << " If my guess is too low, just say (1). If too high, say (2). Say (3) if I've got it. It's (ENTER) to get going!" << "\n\n";
std::cout << " Waiting on you..." << "\n\n";
std::cin.get();
while(gamecont)
{
std::cout << " I'm thinking your number is " << guess << "." << "\n\n";
std::cout << " How did I do?" << "\n\n";
std::cin.ignore();
std::cin.get(feedback);
if (feedback == '1') // The guess was too low.
{
if (guess == 10)
{
guess = 15;
}
else if (guess >= 15)
{
guess++;
}
else if (guess < 10)
{
guess++;
}
}
else if (feedback == '2') // The guess was too high.
{
if (guess == 10)
{
guess = 5;
}
else if (guess <= 5)
{
guess--;
}
else if (guess > 10)
{
guess--;
}
}
else if (feedback == '3') // The guess was correct.
{
gamecont = false;
}
}
return 0;
}
I have to make my homework. It is console application which uses an array of structs that keep information about a computer(brand, year of manufactoring, weight and inventory number). So I wrote a completely working program, but I want to use a dynamic array, because I dont know how many records the user will input.
Is there way to do this. To add new records in array until the user say n/N? Any suggestions?
This is my version of program:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ComputerInfo
{
char computerMark[20], invertarNumber[6];
unsigned int year;
float weight;
};
ComputerInfo computerArray[300];
ComputerInfo AddComputers(ComputerInfo compterArray[], int counter)
{
cout << "Enter mark of the computer: ";
cin >> computerArray[counter].computerMark;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
while ((computerArray[counter].year < 1973)
|| (computerArray[counter].year > 2013))
{
cout << "INVALID YEAR!!!" << endl;
cout << "Enter year of establish: ";
cin>> computerArray[counter].year;
}
cout << "Enter computer weidth: ";
cin >> computerArray[counter].weight;
cout << "Enter computer invertar number(up to six digits): ";
cin >> computerArray[counter].invertarNumber;
return computerArray[counter];
}
void ShowRecords()
{
int counter = 0;
while (computerArray[counter].year != 0)
{
cout << "Mark: " << computerArray[counter].computerMark << endl;
cout << "Year: " << computerArray[counter].year << endl;
cout << "Weidth: " << computerArray[counter].weight << endl;
cout << "Inv. number: " << computerArray[counter].invertarNumber << endl << endl;
counter++;
}
}
void MoreThanTenYearsOld(ComputerInfo computerArray[])
{
int counter = 0;
float counterOldComputers = 0;
float computerPer = 0;
while (computerArray[counter].year == 0)
{
if (computerArray[counter].year <= 2003)
{
counterOldComputers++;
}
counter++;
}
computerPer = counterOldComputers / 3;
cout << endl;
cout << "Percantage of old computers is: " << computerPer << endl;
}
int main()
{
int counter = 0;
float computerPer = 0;
char answer = 'y';
for (int i = 0; i <= 299; i++)
{
strcpy(computerArray[i].computerMark,"");
}
while((answer == 'Y') || (answer == 'y'))
{
computerArray[counter] = AddComputers(computerArray, counter);
cout << endl;
cout << "Do you want to enter more records (Y/N): ";
cin >> answer;
cout << endl;
counter++;
}
MoreThanTenYearsOld(computerArray);
return 0;
}
Yes. Instead of your array, use
std::vector<ComputerInfo> computerArray;
and you can add as many objects as you want:
ComputerInfo c;
// read the data
computerArray.push_back(c);
now, computerArray[0] will have the info in c.
You'll need to #include <vector>.
Also, instead of char computerMark[20] you can use a std::string.
You have two options:
1) Use std::vector instead of an array. This is a very powerful tool and certainly worth learning how to use.
2) Dynamically allocate the array and resize it as you add more items. Basically this means writing your own version of std::vector. This is a good way to strengthen your programming skills. You will learn what goes into writing standard classes and functions. However, I advise using std::vector in more serious programming because it has already been thoroughly tested and debugged.