LNK2019 & LNK1120 C++ error. Program won't compile - Homework - c++

The program won't compile in Visual Studio Community, I have no idea why. I've looked into the function and can't seem to find an answer. Any help would be appreciated as this is for my module at university. I'm a little new to C++ but have some experience in other languages. I just can't seem to find how to get the program to run. I get the below error codes when compiling:
main.cpp: In function ‘void runGame(std::__cxx11::string*, std::__cxx11::string*, int)’:
main.cpp:115:53: error: cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
to ‘std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}’
for argument ‘1’ to ‘std::__cxx11::string answersGiven(std::__cxx11::string*, std::__cxx11::string*, int, int)’
answersGiven(correctAns[0], wrongAns[0], max, max2);
Here is the Code:
#include<iostream>
#include<string>
using namespace std;
int inputCheck(string menu, int limit); // Validates User Input for topic and difficulty selection.
void runGame(string questions[], string answers[], int level); // Function runs game based on questions.
string modifyQuestion(string q, int mod); // Function modifies question based on difficulty level.
string answersGiven(string correct[], string wrong[], int maxC, int maxW);
int main() {
string questions[3][4] = { // 2D array storing answers. Each row stores a Country.
{ "England", "Wales", "France", "Germany" }, // Stores Europe Questions.
{ "Brazil", "Peru", "Argentina", "Columbia" }, // Stores Additional Questions.
{ "Q1", "Q2", "Q3", "Q4" } // Stores South American Questions.
};
string answers[3][4] = { // 2D array storing answers. Each row stores a city.
{"London", "Cardiff", "Paris", "Berlin"}, // Europe Answers.
{"Brasila", "Lima", "Buenos Aires", "Bogota"}, // South America Answers.
{ "A1", "A2", "A3", "A4" } // Stores additional answers.
};
string topics[3] = { "Capital Cities", "" };
char replay; // Variable to check if the user wants to continue playing.
do {
cout << "Please choose one topic for the quiz:\n";
int choice = inputCheck("1: Europe\n2: South America\n3: Testing", 3); // Gets topic choice via validation function.
cout << "\nNow Select a Difficulty:\n";
int difficulty = inputCheck("1: Easy\n2: Medium\n3: Hard", 3); // Gets difficulty choice via validation function.
choice--;
// run the game
runGame(questions[choice], answers[choice], difficulty);
// Checks if user wants to replay game.
cout << "Do you want to play again? Press (Y) to replay: ";
cin >> replay; // Grabs input from user.
replay = toupper(replay); // Sets data to upper case.
} while (replay == 'Y');
return 0;
}
int inputCheck(string menu, int limit) {
cout << menu << endl; // Presents menu of options.
int num; // Variable to store user's input.
cin >> num; // gets user's input.
while (cin.fail() || num < 1 || num > limit) {
cout << "Invalid Input..." << endl; // Outputs error message.
cout << menu << endl; // Presents menu again.
cin.clear(); // Clearsinput error glag.
cin.ignore(1000, '\n'); // Ignores previous inputted data.
cin >> num; // grabs input again.
}
return num;
}
void runGame(string questions[], string answers[], int level) {
string correctAns[] = {};
string wrongAns[] = {};
cin.ignore(1000, '\n'); // Ignore any trailing enter keys in input stream.
int lives = 3; // Stores the amount of users lives.
string answer; // Stores user's answer.
int count = 0; // Keeps track of the current question.
int score = 0; // Keeps track of user's score.
while (lives > 0 && count < 4) {
string question = questions[count]; // Gets current question from array.
// Modifying question if medium or hard difficulty selected.
if (level == 2) {
// Medium
question = modifyQuestion(question, 6);
}
else if (level == 3) {
// Hard
question = modifyQuestion(question, 2);
}
// Asking Question.
cout << "What is the capital city of " << question << endl; // Asks user the question.
getline(cin, answer); // Gets answer from user, includes answers that are more than one word.
answer[0] = toupper(answer[0]); // Converts first character to upper case.
int max = 0;
int max2 = 0;
if (answer == answers[count]) { // Checks user's answer against current answer.
cout << "Well Done! You've got one right" << endl; // Correct answer message.
count++; // Adds one to question counter.
score++; // Adds one to score.
correctAns[count] = answer;
max++;
}
else {
lives--; // Deducts one from lives.
cout << "Oops, Not quite right... You have " << lives << " lives remaining."; // Outputs incorrect message.
wrongAns[count] = answer;
max2++;
}
answersGiven(correctAns[0], wrongAns[0], max, max2);
}
if (lives == 0 && score == 0) { // Checks if user didnt get anything correct.
cout << "Wow.. 0 / 4. Thats not good." << endl;
}
else {
cout << "You got " << score << " Correct and had " << lives << " lives remaining" << endl;
}
cout << "\nThese are the questions you got wrong:\n";
}
string modifyQuestion(string q, int mod) {
for (int i = 0; i < q.length(); i++) {
if (i % mod == 0) { // If counter is divisible by the mod value.
q[i] = '*'; // Change current letter to an aterix.
}
}
return q; // return modified string back to the function.
}
string answersGiven(string correct[], string wrong[], int maxC, int maxW) {
for (int i = 0; i < maxC; i++) {
cout << correct[i] << " - Correct" << endl;
}
for (int i = 0; i < maxW; i++) {
cout << wrong[i] << " - Incorrect" << endl;
}
}

Related

Parallel Arrays in C++

Trying to create a program that takes a coffee flavor add-in and checks if it's valid using an array.
If valid it uses the array index to gather price information.
I managed to write the code below, but it only works for 1 iteration.
How can alter it so a user can enter: Cream and cinnamon and output the total of each add-in as well as the total price of the cup of coffee? The cup of coffee starts with a base price of $2.00
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Declare variables.
string addIn; // Add-in ordered
const int NUM_ITEMS = 5; // Named constant
// Initialized array of add-ins
string addIns[] = { "Cream", "Cinnamon", "Chocolate", "Amaretto", "Whiskey" };
// Initialized array of add-in prices
double addInPrices[] = { .89, .25, .59, 1.50, 1.75 };
bool foundIt = false; // Flag variable
int x; // Loop control variable
double orderTotal = 2.00; // All orders start with a 2.00 charge
string QUIT = "XXX";
// Get user input
cout << "Enter coffee add-in or XXX to quit: ";
cin >> addIn;
// Write the rest of the program here.
for (x = 0; x < NUM_ITEMS && foundIt == false && addIn != QUIT; x++) {
if (addIn == addIns[x]) {
foundIt = true;
x--;
}
}
if (foundIt == true) {
cout << addIns[x] << " $" << addInPrices[x] <<endl;
cout << "$" << orderTotal + addInPrices[x] <<endl;
}
else {
cout << "Sorry, we do not carry that." <<endl;
cout << "Order total is $ " << orderTotal <<endl;
}
return 0;
}
Don't use parallel arrays - you will mess up maintaining them.
Better options:
Create a struct for your add-ins:
struct Addin {
std::string name;
double price;
}
and use an array (or better yet an std::vector) of those structs.
Another option is to use a map:
std::map<std::string, double> addIns = {
{"Cream", .89},
{"Cinnamon", .25},
// etc.
};
Then you won't need a loop, just a lookup
auto item = addIns.find(addIn);
if(item != addIns.end() {
// do your math here
}
Your program is written to get a single output. For multiple outputs there have to be loops and the not found condition also has to be re-written.
try this
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Declare variables.
const int NUM_ITEMS = 5; // Named constant
string addIn[NUM_ITEMS]; // Add-in ordered
// Initialized array of add-ins
string addIns[] = { "Cream", "Cinnamon", "Chocolate", "Amaretto", "Whiskey" };
// Initialized array of add-in prices
double addInPrices[] = { .89, .25, .59, 1.50, 1.75 };
//bool foundIt = false; // Flag variable
int x, i, j; // Loop control variable
double orderTotal = 2.00; // All orders start with a 2.00 charge
string QUIT = "XXX";
// Get user input
cout << "Enter coffee add-ins followed by XXX to quit: ";
for(i=0; i<NUM_ITEMS; i++) {
cin >> addIn[i];
if(addIn[i] == QUIT) {
i++;
break;
}
}
int foundIt[i];
// Write the rest of the program here.
for(j=0; j<i; j++) {
foundIt[j] = -1;
for(x = 0; x<NUM_ITEMS && foundIt[j] == -1 && addIn[j] != QUIT; x++) {
if (addIn[j] == addIns[x]) {
foundIt[j] = x;
}
}
}
for(j=0; j<i-1; j++) {
cout << addIn[j];
if(foundIt[j] != -1) {
cout << " $" << addInPrices[foundIt[j]] << endl;
orderTotal = orderTotal + addInPrices[foundIt[j]];
}
else {
cout << " - Sorry, we do not carry that." <<endl;
}
}
cout << "$" << orderTotal <<endl;
return 0;
}
Sample Outputs
Enter coffee add-ins followed by XXX to quit: Cream Cinnamon XXX
Cream $0.89
Cinnamon $0.25
$3.14
Enter coffee add-ins followed by XXX to quit: Cream Onion XXX
Cream $0.89
Onion - Sorry, we do not carry that.
$2.89
What I did was made addIn array of srings with NUM_ITEMS size instead of variable. Also, foundIt was made an integer array to keep track of indexes where the items are found in addIns array and -1 if not found.
To only access the items that user has entered in addIn, your QUIT has been made the termination condition in that array.
The structure you are looking for is a while or do/while loop.
To be able to enter "empty" lines use std::getline from.
The structure of your program will then look something like this :
As you can see I have a habit of changing my boolean expressions into functions (predicates). This makes code more readable and predicates reusable in other bits of code.
#include <iostream>
#include <string>
bool is_quit(const std::string& input)
{
return input.length() > 0;
}
bool is_valid_input(const std::string& input)
{
return true; // your own check
}
int main()
{
bool quit = false;
std::string input;
do
{
std::cout << "give input : ";
std::getline(std::cin, input);
quit = is_quit(input);
if (is_valid_input(input) && !quit)
{
std::cout << "ok" << std::endl;
}
} while (!quit);
return 0;
}

Visual Studio shows warning C6330: 'char' passed as _Param_(1) when 'unsigned char' is required in call to 'isdigit'. when I try to build

This is only a small part from my code. What I'm trying to do is writing at the end of the file (add record) which in this case is "books.txt" that already has 40 records. But when I debug, it would still prompt the user to enter isbn code but after entering, (process 3296) exited with code 3. came out. Which part am I doing wrong? The counter() function is to count how many records I already have in my file. And I'm also using array of struct to store my records.
int add_record(DATA book[])
{
int count = counter();
system("CLS");
cout << "\t\t\t\t\t\t\t\t : :Add Book Record: :\n\n";
bool cont;
ofstream outfile("books.txt", ios::app);
if (outfile.is_open() && !outfile.eof())
{
do
{
cont = true;
cout << "ISBN Code: ";
cin.getline(book[++count].isbn_code, 14, '\n');
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
int length = strlen(book[++count].isbn_code);
for (int i = 0; i <= length; i++)
{
if (!isdigit(book[++count].isbn_code[i]))
{
cont = false;
cout << "Your input is invalid. Enter again.\n";
break;
}
}
} while (cont == false);
do
{
cont = true;
cout << "Author: ";
cin.getline(book[++count].author, 50, '\n');
int length = strlen(book[++count].author);
for (int i = 0; i <= length; i++)
{
if (isdigit(book[++count].author[i]))
{
cont = false;
cout << "Your input is invalid. Enter again.\n";
break;
}
}
} while (cont == false);
outfile << book[++count].isbn_code << "," << book[++count].author ;
outfile.close();
}
else
cout << "File is not open\n";
return 0;
}
Yes, the error message is completely correct. This is a rare case where using a cast is the correct thing to do
if (isdigit(static_cast<unsigned char>(book[++count].author[i])))
Reference, https://en.cppreference.com/w/cpp/string/byte/isdigit
But this has nothing to do with your crash which is caused by other errors. For instance
cin.getline(book[++count].isbn_code, 14, '\n');
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
int length = strlen(book[++count].isbn_code);
You definitely don't want to increment count twice. I would guess the correct code is
cin.getline(book[count].isbn_code, 14, '\n');
int length = strlen(book[count].isbn_code);
and to increment count once later in your loop.
Remember ++count is not the same as count + 1. The first increments the count variable, that is it changes the value of the count variable, but count + 1 just adds one to count and does not change the value of the count variable.
This is also wrong
for (int i = 0; i <= length; i++)
In C++ string indexes start at zero and go upto the length of the string minus one, so the correct code is
for (int i = 0; i < length; i++)
Also not part of your question but X can be a legal character in an ISBN.

c++: for not working as intended [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
My question is when I run the code,and call for the list,so I press 3,nothing happens and it just skips over the code in for(). Why does this occur and how can I fix it?
Simple code would be welcome.I am now to this.
The first two int before the main checks if the student is qualified for the school,or not.i tested those and they are working great.
The struct describes a student.He/She has a name(nev),marks (bacmagy,bacrom,bacmat,bacvalasz).A boolean value(langexam) is present,to represent is the student has a language exam or not.
bsiker is true,if the formula in calculateBac turns out to be true.
atmente is true,if bsiker and langexam are both true.
The listing would spit out the name,bsiker and atmente.
#include <iostream>
using namespace std;
int atmegye(bool elso, bool masodik){
if (elso && masodik)
return true;
else
return false;
}
int calculateBac(double magy, double mat, double rom, double val){
double osszeg = magy + mat + rom + val;
osszeg = osszeg / 4;
if (magy < 5 || mat < 5 || rom < 5 || val < 5 || osszeg < 6)
return false;
else
return true;
}
int main(){
struct diak{
char nev[32];
bool langexam, atmente, bsiker;
double bacmagy, bacrom, bacmat, bacvalasz, bac;
};
diak v[150];
bool cap = false;
int opcio;
int j, n = 0;
int i = 0;
do{
cout << "\n Welcome. \n 1-new studient \n 2-Change a studient's details \n 3-List \n 4-Exit \n";
cin >> opcio;
switch (opcio){
case 4:{
return 0;
}
case 1:{
cout << "Please give the name of the student: ";
cin >> v[i].nev;
cout << "Hungarian mark: ";
cin >> v[i].bacmagy;
cout << "Romanian mark: ";
cin >> v[i].bacrom;
cout << "Maths mark: ";
cin >> v[i].bacmat;
cout << "Optional mark: ";
cin >> v[i].bacvalasz;
cout << " Do you have a language exam? Please respond with 1 or 0: ";
cin >> v[i].langexam;
v[i].bsiker = calculateBac(v[i].bacmagy, v[i].bacrom, v[i].bacmat, v[i].bacvalasz);
v[i].atmente = atmegye(v[i].bsiker, v[i].langexam);
i = i + 1;
i = n;
cout << n;
break;
}
case 3: {
for(i = 0; i < n; i++)
cout << v[i].nev << " " << v[i].bsiker << " " << endl;
break;
}
}
}while (opcio != 5);
}
This line is wrong:
i = n;
it should be:
n = i;
Your code is just undoing the i = i + 1; line that precedes it.
n is initialized as 0 and never set to any other value. Therefore your for loop is not supposed to run any iteration
The problem is in the for loop's conditional. You initialized the value of n to 0, and that value never seems to change. The variable i is also initialized to 0 inside the for loop. When the user chooses option 3, the for loop conditional ( 0 < 0) is evaluated which is false, so the for loop is skipped every time. So, to fix this problem, you need to update the value of n somewhere in your code, or you need to change your conditional statement. Hope this helps!
I know this probably won't help for your assignment, but here's a (one of many) way to handle this is a more c++-like manner, and without using OOP.
The standard library and the c++ type system give us plenty of useful tools to avoid writing bugs in the first place (that's really nice!), and find the one that are left at compile-time (saves a ton of time!). That's what the biggest difference between c and c++ is, and it is a very important one.
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
// fixed-size record to save in data file, for example.
struct diak{
char nev[32];
bool langexam, atmente, bsiker;
double bacmagy, bacrom, bacmat, bacvalasz, bac;
};
void atmegye(diak& student)
{
student.atmente = student.bsiker && student.langexam;
}
void calculateBac(diak& student) // computes grades average, checks if passed.
{
double osszeg = student.bacmagy + student.bacmat + student.bacrom + student.bacvalasz;
student.bac = osszeg / 4.0;
student.bsiker = student.bacmagy >= 5
&& student.bacrom >= 5
&& student.bacmat >= 5
&& student.bacvalasz >= 5
&& student.bac >= 5; // this last test unnecessary, but rules are rules.
}
void AddNewStudent(std::ostream& os, std::istream& is, std::vector<diak>& students)
{
diak new_student;
std::string temp;
while(temp.empty())
{
os << "Student name: ";
is >> temp; // using a temp buffer avoids out of bounds errors
}
if (temp.length() >= sizeof(new_student.nev))
temp.resize(sizeof(new_student.nev) - 1);
strcpy(new_student.nev, temp.c_str());
// input values below SHOULD be validated for range (0-100)
// or whatever makes sense for your school.
os << "Hungarian mark: "; is >> new_student.bacmagy;
os << "Romanian mark: "; is >> new_student.bacrom;
os << "Maths mark: "; is >> new_student.bacmat;
os << "Optional mark: "; is >> new_student.bacvalasz;
// example validation. Validating user input is the worst!
// above ^^^ grades ^^^ can use a common function for validation.
for(;;)
{
os << " Do you have a language exam? Please respond with 1 or 0:";
is >> temp;
if (temp == "0")
{
new_student.langexam = false;
break;
}
if (temp == "1")
{
new_student.langexam = true;
break;
}
// not a valid entry, try again!
}
calculateBac(new_student);
atmegye(new_student);
students.push_back(new_student);
}
void EditSudent(std::ostream& os, std::istream& is, std::vector<diak>& students)
{
// query which student then edit using streams 'os' and 'is' for i/o.
}
// could also be used to write to file...
void PrintStudents(std::ostream& os, const std::vector<diak>& students)
{
// maybe by printing a student number you could reuse this
// function from EditStudent()...
//
// At the same time, it is only 2 lines of code. You decide.
for(size_t i = 0; i < students.size(); i++)
os << students[i].nev << " " << students[i].bsiker << "\n";
os.flush();
}
int main()
{
std::vector<diak> students; // could also be an std::list<>
while(true) // 1 less line of code than do {...} while, and easier to read.
{
int opcio = 0;
std::cout << "\n Welcome."
"\n 1-new studient"
"\n 2-Change a studient's details"
"\n 3-List "
"\n 4-Exit \n";
std::cin >> opcio;
switch (opcio)
{
case '1':
AddNewStudent(std::cout, std::cin, students);
break;
case 2:
EditSudent(std::cout, std::cin, students); // << queries student and edit that
break;
case 3:
PrintStudents(std::cout, students);
break;
case 4:
return 0;
}
}
}
Note how the tasks are very well delimited into their own function, this also helps finding bugs faster, as it makes the code easier to read and reason about (the famous divide and conquer strategy).
Having the students array (or list) as a single entity simplifies its management, no extra variable to keep up to date, etc...
In a more serious application, the input validation would be best done using a template, and would give the user an escape character so he could cancel adding the new student at any time.

code falling through on an if statement [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
When I add the second if to test for car size M to calculateTotalCarCharge then try to test the condition of c, I'm getting an answer for m (77.28 & 167.44) when I really want (68.73 & 148.92), its almost like the code is somehow falling through to the next condition
Test conditions
Type - Days - Amount
C - 3 - 68.73
M - 3 - 77.28
C - 7 - 148.92
M - 7 - 167.44
#include <iostream> //for I/O
#include <iomanip> //for formatting output
#include <cmath> //for math
using namespace std;
//prototypes
char validateCarChoice();
void displayProgramDescription();
int validateNumEntry(string prompt);
double calculateTotalCarCharge (char carSize, int daysRented);
//global constants
const char COMPACT = 'C';
const char MID = 'M';
const char FULL = 'F';
const char SUV = 'S';
const double COMPACT_DAILY_CHARGE = 22.91;
const double MID_DAILY_CHARGE = 25.76;
const double FULL_DAILY_CHARGE = 28.87;
const double SUV_DAILY_CHARGE = 98.88;
// --------------------------------------------------------------------------
// Description:
// Input parameter:
// Returns:
// ---------------------------------------------------------------------------
int main()
{
//local constants
const string ENTER_DAYS_RENTED = "Enter the number of days rented: ";
const string ENTER_MILES_DRIVEN = "Enter number of miles driven: ";
//local variables
char userCarTypeChosen;
char carSize;
int daysRented;
double milesDriven;
double carCharge;
//call function to display program description
displayProgramDescription();
//calls function to validate the car choice input by user
userCarTypeChosen = validateCarChoice();
//if car type chosen is suv (S) then only prompt will be to enter days
//rented, if not prompt both days rented and miles driven.
if (userCarTypeChosen == 'S')
{
daysRented = validateNumEntry(ENTER_DAYS_RENTED);
}
else
{
daysRented = validateNumEntry(ENTER_DAYS_RENTED);
milesDriven = validateNumEntry(ENTER_MILES_DRIVEN);
}
carCharge = calculateTotalCarCharge(carSize, daysRented);
//to be removed
cout << carCharge;
return 0;
}
// --------------------------------------------------------------------------
// Description: displayProgramDescription - displays program description
// Input parameter: N/A
// Returns: N/A
// ---------------------------------------------------------------------------
void displayProgramDescription()
{
//local constant
const string PROGRAM_DESCRIPTION = "This program will calculate a car rental"
" bill for Rent2U.";
//displays program description
cout << PROGRAM_DESCRIPTION << endl;
}
// --------------------------------------------------------------------------
// Description: validateCarChoice - displays menu of car options and daily cost.
// Then error checks that a valid choice was given
// Input parameter: N/A
// Returns: letter of car chosen
// ---------------------------------------------------------------------------
char validateCarChoice ()
{
//local constants
const string ENTER_CAR_LETTER = "Enter letter for car size rented: ";
const string ERROR_CAR_INPUT = "Re-enter letter for car size rented: ";
//local variable
char carSize;
//displays car size options
cout << "Car sizes:" << endl << endl;
cout << setw(5) << "C - Compact size at $ 22.91 per day" << endl;
cout << setw(5) << "M - Mid size at $ 25.76 per day" << endl;
cout << setw(5) << "F - Full size at $ 28.76 per day" << endl;
cout << setw(5) << "S - SUV at $ 98.88 per day" << endl << endl;
//prompt for user input
cout << ENTER_CAR_LETTER;
cin >> carSize;
carSize = toupper(carSize);
//validation of car type chosen
while (carSize !='C' && carSize !='M' && carSize !='F' && carSize !='S')
{
cout << ERROR_CAR_INPUT;
cin >> carSize;
carSize = toupper(carSize);
}
return carSize;
}
// --------------------------------------------------------------------------
// Description: validateNumEntry - validates that the user entry is at least 1
// Input parameter: prompt- prompts user to enter number
// Returns: the user inputed number
// ---------------------------------------------------------------------------
int validateNumEntry (string prompt)
{
//local constant
const string ERROR = "Error - entry must be at least 1.";
//local variable
double num;
cout << prompt;
cin >> num;
while (num < 1)
{
cout << ERROR << endl;
cout << prompt;
cin >> num;
}
return num;
}
// --------------------------------------------------------------------------
// Description:
// Input parameter:
// Returns:
// ---------------------------------------------------------------------------
double calculateTotalCarCharge (char carSize, int daysRented)
{
//local constant
const int WEEK = 7;
const double LOWER_WEEK_RATE = 6.5;
//local variable
double totalCarCharge;
int wholeWeek;
int extraDays;
if (carSize = 'C')
{
if (daysRented < WEEK)
{
totalCarCharge = (COMPACT_DAILY_CHARGE * daysRented);
}
else
{
wholeWeek = (daysRented / WEEK);
extraDays = (daysRented % WEEK);
totalCarCharge = ((wholeWeek * LOWER_WEEK_RATE *
COMPACT_DAILY_CHARGE) + (extraDays * COMPACT_DAILY_CHARGE));
}
}
//once i add this if condition, if I try and test C I get the calculations
//for M
if (carSize = 'M')
{
if (daysRented < WEEK)
{
totalCarCharge = (MID_DAILY_CHARGE * daysRented);
}
else
{
wholeWeek = (daysRented / WEEK);
extraDays = (daysRented % WEEK);
totalCarCharge = ((wholeWeek * LOWER_WEEK_RATE * MID_DAILY_CHARGE)
+ (extraDays * MID_DAILY_CHARGE));
}
}
return totalCarCharge;
}
For checking condition you have to use:
if (carSize == 'M')
and
if (carSize == 'C').
Because when you use the statement:
if (carSize = 'M') will just assign value carSize to 'M'
and will execute code inside the if statement.
This condition is same for if (carSize = 'C') too.
OR use switch statement:
switch (carSize)
{
case 'C':
if (daysRented < WEEK)
...
break;
case 'M':
// ...
}
As pointed out in the comments, you are assigning in your if statement in (carSize = 'C') and (carSize = 'M'). Out of interest, why not opt for a switch on the char here? It seems the branches are mutually exclusive, and you aren't mutating carSize in the branches? This might help avoid this kind issue in future:
switch (carSize)
{
case 'C':
if (daysRented < WEEK)
...
break;
case 'M':
// ...
}
Edit
There is a second bug in your code, in that you are assigning:
userCarTypeChosen = validateCarChoice();
But then you are passing the uninitialized variable carSize to the calculateTotalCarCharge function:
carCharge = calculateTotalCarCharge(carSize, daysRented);
You should change the assignment to carSize
carSize = validateCarChoice();
and then remove the userCarTypeChosen variable entirely.
In these comparisons to literals, a good idea can be to reverse the operands, which will throw a compiler error if you use single equal instead of double equal.
if (var == 'C') // compiles, runs correctly
if (var = 'C') // compiles, runs incorrectly, results in stackoverflow question
if ('C' == var) // compiles, runs correctly
if ('C' = var) // does not compile, fix this problem immediately

I'm getting a weird error for a program that seems like it should "just work."

I present to you all a program I'm working on for my college programming course. I still have a little ways to go before it completely meets my assignment's requirements, but I've gotten a basic draft of the program error-free (supposedly) and it appears to run… but then it suddenly kicks me into Xcode's debugger and gives me:
Thread 1: EXC_BAD_ACCESS(code=2, address=0x7fff95c1e5f5)
Here's the command line output, up until it kicks me out:
-----------------------
Quarterly_sales_taxator
-----------------------
How many company divisions will we be dealing with? 2
Am I correct in assuming that there are 4 sales quarters? yes
Please enter the sales Company Division #1 brought in for Sales Quarter #1 20
(lldb)
Here's my code:
//
// quarterly_sales_taxator.cpp
// Ch. 7 program #7
//
// Created by John Doe on 11/27/12.
//
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cctype>
using namespace std;
void read_company_divisions_and_sales_quarters(double **, int, int);
//void write_company_divisions_and_sales_quarters_to_array(double **, int, int); // This will be used later on to read data from a file.
void display_quarterly_sales_array(double **, int, int);
string temp; // A global temporary placeholder variable; I use this several times.
int main()
{
int COMPANY_DIVISIONS,
SALES_QUARTERS = 4;
double **quarterly_sales_form;
cout << "\n\n-----------------------\nQuarterly_sales_taxator\n-----------------------\n\n";
cout << "\nHow many company divisions will we be dealing with? ";
getline(cin, temp);
stringstream(temp)>>COMPANY_DIVISIONS;
while (COMPANY_DIVISIONS < 1 || isdigit(COMPANY_DIVISIONS == false))
{
cout << "\n\n------"
<< "\nError:"
<< "\n------"
<< "\n\nYou have entered an invalid choice."
<< "\nPlease type a number greater than zero. ";
getline(cin, temp);
stringstream(temp)>>COMPANY_DIVISIONS;
}
cout << "\n\nAm I correct in assuming that there are 4 sales quarters? ";
getline(cin, temp);
// Convert to uppercase.
for (int count = 0; count < temp.length(); count ++)
{
temp[count] = toupper(temp[count]);
}
if (temp == "NO" || temp == "NOPE" || temp == "INCORRECT" || temp == "YOU ARE NOT" || temp == "YOU ARE INCORRECT" || temp == "NEGATIVE" || temp == "NEGATORY")
{
cout << "\nOk, then how many sales quarters are we dealing with? ";
getline(cin, temp);
stringstream(temp)>>SALES_QUARTERS;
}
cout << endl << endl;
// This sets up the 2d array.
quarterly_sales_form = new double *[COMPANY_DIVISIONS];
for (int count = 0; count < COMPANY_DIVISIONS; count ++)
{ quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS]; }
read_company_divisions_and_sales_quarters(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);
// write_company_divisions_and_sales_quarters_to_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS); // I'll add this feature later.
cout << "\n\nHere's what you entered:\n\n";
display_quarterly_sales_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);
// Since we used a series of pointers, we need to free the allocated space back up.
for (int count = 0; count < COMPANY_DIVISIONS; count ++)
{ delete[] quarterly_sales_form[COMPANY_DIVISIONS]; }
delete[] quarterly_sales_form;
return 0;
}
/*############################################
# read_company_divisions_and_sales_quarters #
############################################*/
void read_company_divisions_and_sales_quarters(double **array, int DIVISIONS, int QUARTERS)
{
for (int count = 0; count < QUARTERS; count++)
{
for (int index = 0; index < DIVISIONS; index++)
{
cout << "\nPlease enter the sales Company Division #" << count+1 << " brought in for Sales Quarter #" << index+1 << " ";
getline(cin, temp);
stringstream(temp) >> array[count][index];
}
}
}
/*################################
# display_quarterly_sales_array #
#################################*/
void display_quarterly_sales_array(double **array, int DIVISIONS, int QUARTERS)
{
for (int count = 0; count < DIVISIONS; count++)
{
cout << "\nCompany division #" << count+1 << ":\n";
for (int index = 0; index < QUARTERS; index++)
{ cout << array[count][index] << ", "; }
}
}
Can some kind soul please tell me what I'm doing wrong?
{ quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS]; }
In this line, COMPANY_DIVISIONS should be count.
In addition to what Dan Hulme said, it seems this line
stringstream(temp) >> array[count][index];
should really be
std::istringstream(temp) >> std::skipws >> array[index][count];
In addition to using std::istringstream rather than std::stringstream and making sure that an lvalue is at hand, which isn't strictly needed until the type read becomes more interesting, this also reverses the indices: index runs over COMPANY_DIVISIONS and count over SALES_QUARTERS.
The real question is, of course: Who hands out assignments like this? Pointer manipulations and allocations are best left to low-level library writers. This is C++ not C: we can and should use abstractions. Getting this code exception safe is a major challenge and there is no point in teaching people how to write broken (e.g. exception unsafe) code.