Passing and updating a structural array - c++

So I'm having some trouble with my program. It doesn't seem to fill the array properly. It dosen't seem to populate pass element 0, even though I'm increasing i. When I debug and go back, i remains zero. Should I be doing something different? I feel like I'm passing or updating the array improperly. Can't really use any STL libraries. Thank you in advance for any help.
struct Client
{
string name;
string zip;
double balance;
};
Client bAccounts [30]; //structural array in main()
int addClnt(Client(&bAccounts)[30], int); //prototype
int addClnt(Client(&bAccounts)[30], int clientCount) //function to add
elements
{
cout << "Enter Account Name:" << endl;
cin >> bAccounts[i].name;
cout << "Enter Account Zip:" << endl;
cin >> bAccounts[i].zip;
cout << "Enter Account Balance:" << endl;
cin >> bAccounts[i].balance;
cout << "Enter Last Transaction" << endl;
cin >> bAccounts[i].lastTrans;
clientCount++; //to return number of clients added
i++; //to populate different element of array on next call of function.
return clientCount + 1;
}
So I added + 1 to return clientCount and then set i = clientCount. However, clientCount remains at zero and dosen't update.

The reason the array doesn't have any values after the first one is because you never reach passed the first element. You increment i at the end of the function, but at the top of your addClnt function, i is set back to 0 . This will just keep resulting on overwriting the old previous data
EDIT:
#include <iostream>
//use pass by reference (&)
void add_client(int& index_loc){
//do whatever
//this changes the actual value passed into the function
index_loc++;
}
int main(){
int loc = 0;
add_client(loc);
add_client(loc);
add_client(loc);
//outputs 3
std::cout << "current #: " << loc << "\n";
}

clientCount is only getting incremented in that functions scope. When that function goes to it's return statement, all variables and all the work it did has completely died.
You are passing clientCount by value and not by reference, so clientCount will always be 0, and incrementing it inside that local function won't actually change clientCount's value outside of the function.
What you need to do is pass it by reference.
EDIT: The chosen answer does not explain why his solution works. The answer provided is incorrect.
The reason why the code works because again, you pass by reference and not by value.

Related

Return value unchanged by function

After calling function the amount_of_people, the variable n remains unchanged. I verified this by outputting the variable after the function call. Do I need a pointer n to function as argument?
int main(){
srand(time(NULL));
bool Appworks = true;
size_t n;
do {
amount_of_people(n); // Entering amount of people HERE! STUCKED HERE.
if (n >= 1) {
DataBase *first = new DataBase[n]; // Creating dynamic structure-array
inputData(first, n);
output(first, n); // Output of entered data
freeUp_memory(first); // Clearing dynamic-alocated memory engaged by early-created pointer
}
else cout << "Error! Wrong amount of people!" << endl;
} while (Appworks);
system("PAUSE");
return 0;
}
Function declaring:
unsigned amount_of_people(int n) {
cout << "Enter how many people u want to enter" << endl;
cin >> n;
return n;
}
I would appreciate any help and explanation(!)
Thanks for your attention.
amount_of_people(n)
does not use the value returned from amount_of_people. n is of no use here because according to the function declaration
unsigned amount_of_people(int n);
n is passed by value. When a parameter is passed by value, the function operates on a copy of the source variable. Changing the copy has no effect on the original. May I suggest instead,
std::size_t amount_of_people() // parameter gone, return type changed to match n in caller
{
std::size_t n; // parameter moved to here and type changed to match return type
std::cout << "Enter how many people u want to enter" << std::endl;
std::cin >> n;
return n;
}
This is then used like
const std::size_t n = amount_of_people();
Side note: Rather than
DataBase *first = new DataBase[n];
strongly consider ensuring that DataBase correctly observes the Rule of Three, Five, or Zero and using
std::vector<DataBase> databases;
rather than a raw allocation. It knows it's size and looks after all of the memory management for you. Documentation for std::vector.
RE "Do I need a pointer to function as argument", either a pointer or a reference.
unsigned amount_of_people(int n) as you wrote it takes an integer n by value, assigns it using cin >> n, and then returns it. Either change your function to
void amount_of_people(unsigned int& n) {
std::cout << "Enter how many people u want to enter" << endl;
std::cin >> n;
}
and call it:
amount_of_people(n);
which takes n by reference, or write
unsigned int amount_of_people() {
unsigned int n;
std::cout << "Enter how many people u want to enter" << endl;
std::cin >> n;
return n;
}
and call it:
n = amount_of_people();
Both styles have uses; the first is, I think, more common in cases where the function has side effects, and so it "outputs" its results into the ref-passed parameters ("out parameters"), while you opt to return from the function a variable indicating whether an error occurred during its execution. The second style is a little more common for pure functions, where the result is always computed successfully based on the inputs with no possibility of error.
Also, make up your mind whether you want the variable to be a size_t or an int.

How to understand C++ function/data structs?

'strToDouble' was not declared in this scope Lab1-3.cpp /Lab1-3/src line 65 C/C++ Problem
The first problem, as #SoronelHaetir pointed out, is that you were trying to assign title to variable which can only hold one character. Instead, you should use char array, char pointer, or even string object to contain your multi-letter value. In my code example below, I used char array with fixed size of 25, to store the title. Beware that you can store only up to 24 characters in it, because char arrays need special character which will denote the end of char array. Otherwise it would end up writing junk after your desired value. That special character is null-terminating character which is written like '\0'.
Using return; statement in your void displayBid(Info itemOne); function was completely unnecesary. While you can use return; to stop function from executing, you placed it at the end of function which was just about to end itself in normal way, but you forced it with no reason. Besides, you do not need any return; statements for functions which return void – nothing.
Then, fund and bidAmount are representing money value, which may or may not be of integer value, so you should consider float or double data types to store money value.
Next thing is your function Info getBid();. First, I have to say that naming may be a bit confusing. If you read the name of that function without seeing its actual code, how would you understand what it may do? For me, it sounded like it is about to get me information about a bid, while actually it is setting it up. Second, you could simplify code for entering values, in the way I did it in my code example. The way you tried to use different techniques for getting values from user input was a bit wrong. getline is member function which is used with istream objects. Your istream object is cin. In order to access that member function you shall write it as cin.getline(to be discussed);. That function only works with characters. Its first parameter accepts pointer to the first character (address of the first character) in sequence of characters.
Second parameter is of integer data type and specifies how much characters you want to be extracted from your input and stored in an argument which is in place of the first parameter. Beware not to write, for example, 25, because in char array you have to leave one place for '\0' character, which is automatically placed where it needs to be. getline member function has also default delimiter '\n', which denotes new line. It means that you can enter less characters than function can extract, because extraction will stop as soon as it reads that delimiter value from user input. Although, if you want your specific delimiter, getline member function has its overloaded version which third parameter is one where you enter desired delimiter as an argument. (Overloaded functions are basically functions with the same name, but different parameters. They provide same functionality with different implementation.)
Even if you had set up values for a bid, you never returned it from function. You correctly said that its return value is Info, but you did not return it. Actually, you again exited just before its normal exit. Instead, you should have written return itemOne; In my code example, I passed the variable created in int main(); function by reference, which means it is not a copy as usually, so I do not have to return it and assign to another variable of the same type to appropriately apply desired changes.
Finally, in the int main(); function, you could just declare int choice, without initializing it and use do-while loop in the way I did it. Also, switch statement provides defining what will happen if none of the cases are true, in the way that after all cases you write default:, and below it whatever you want to happen. In your code example, your function will continue executing even if user enters anything but 1, 2 except for 9 defined to stop its execution. In my code example, whatever user enters besides 1 and 2, including zero, function will exit. Well, except for new line.
And, let us discuss again the naming. Your data structure name has to directly imply what it is. Info does not do that. That name would actually be more appropriate for your void displayBid(Info itemOne); function to be called. In my code example, I renamed it to Bid.
#include <iostream>
using namespace std;
struct Bid
{
char title[25];
int vehicleID;
double fund;
double bidAmount;
};
void GetBid(Bid item)
{
cout << "Title: " << item.title << endl;
cout << "Fund: " << item.fund << endl;
cout << "Vehicle: " << item.vehicleID << endl;
cout << "Bid Amount: " << item.bidAmount << endl;
}
void SetBid(Bid & item)
{
cout << "Enter title: ";
cin >> item.title;
cout << "Enter fund: ";
cin >> item.fund;
cout << "Enter vehicle ID: ";
cin >> item.vehicleID;
cout << "Enter amount: ";
cin >> item.bidAmount;
}
int main()
{
Bid item;
int choice;
do {
cout << "Menu:" << endl;
cout << " 1. Enter Bid" << endl;
cout << " 2. Display Bid" << endl;
cout << " 0. Exit" << endl;
cout << "Enter choice: ";
cin >> choice;
switch (choice)
{
case 1:
SetBid(item);
break;
case 2:
GetBid(item);
break;
default:
choice = 0;
cout << "Goodbye." << endl;
break;
}
} while (choice != 0);
return 0;
}
The first (and biggest) problem is:
char title;
This allows you to store only a single character rather than an entire name (prefer std::string to char arrays).

My bool function keeps returning true and im not sure why

Im doing an excercise sheet to get an understanding of functions and I am currently working on the following question.
Write function prototypes for each of the following:
A function HasValue that may be passed a reference to an array, the size of the array and a
search value. The function should return true if the search value exists in the array
In my code I have sent the contents of the array, the array size and the value to be searched in the array to the bool function.
In the function I compared the value to each element of the array using a for loop.
I then created a variable count in the function that will be incremented if the value matches any element in the array.
I then used an if else statment to return true if count is greater than 0 and false if count is equal to 0. The problem is however that the function is only returning true thus the output will always be "this number appears in the array"
Logically these steps seem correct to me but obviously there is a flaw somewhere that I cant see. I presume its just I do not have a decent understanding of Bool functions yet but if someone could explain where and why I'm going wrong it would be greatly appreciated in my learning process to understanding functions and c++.
#include <iostream>
#include <iomanip>
#include "stdafx.h"
using namespace std;
bool HasValue(int Array[], int size, int Value);
int main()
{
int value;
int Array[10]{ 3,5,6,8,9,1,2,14,12,43 };
cout << "enter value you wish to search for in array " << endl;
cin >> value;
HasValue(Array, 10 , value);
if (true)
cout << "This number appears in the array " << endl;
else
cout << "This number does not appear in the array " << endl;
return 0;
}
bool HasValue(int Array[], int size, int Value)
{
int count = 0;
for (int i = 0; i < size; i++)
{
if (Value == Array[i])
{
count++;
}
}
if (count > 0)
{
return true;
}
else
return false;
}
You test code is the problem
HasValue(Array, 10 , value);
if (true)
cout << "This number appears in the array " << endl;
else
cout << "This number does not appear in the array " << endl;
This ignores the return value of HasValue and always prints "This number appears in the array".
HasValue(Array, 10 , value);
This line of code executes the function but ignores the returned value. When a function returns a value, you need to assign it to a variable:
bool result = HasValue(Array, 10 , value);
Then if (true) does not have any reference to the returned value. The true inside the if will cause the first cout to always print. You will never see the output from the else. But once you have the return value in a variable, you can use it in the if:
if(result)
You can reduce this all to one line of code, if you want:
if(HasValue(Array, 10 , value))
Now the if statement will directly test the return value from HasValue(). In this particular case, combining the code into a single line seems reasonable. You must be careful doing this, though. When you combine too much into a single line, the code becomes more difficult to debug. You will need to find a balance between readability and convenience as you continue learning how to program.

Subscripted value is not an array, pointer or vector, C++

So, I'm getting the above error (in the title) but for some reason it's only throwing this error on the second loop. Notice the first and second loop I have using the customer variable works absolutely fine, no errors thrown or anything. But on that last loop, the output[customer][charge] array, there is a red line under output[customer] that says "Subscripted value is not an array, pointer or vector". I am using xcode, Mavericks OSX. All of my arrays are defined elsewhere, and have worked perfectly the whole length of the program until now. There are some other operations going on in the program, but they have nothing to do with this loop, so I just posted the code that was giving the error. Again I'll say, the charges[customer][month][charge] loop works fine, but the output[customer][output] is not working.
P.S. You probably will think the logic behind keeping all this data in numerically indexed arrays is dumb, but it is for a school project. So don't lecture me about how this program is logically inconsistent or whatever. Thanks!
string headings[3][7];
string chargeLabels[3] = {"Electricity :","Water: ","Gas: "};
string outputLabels[5] = {"Subtotal: ","Discount: ","Subtotal: ","Tax: ","Total: "};
double charges[3][3][3];
double output[3][5];
for(int customer=0; customer<3; customer++)
{
for(int heading=0; heading<5; heading++)
{
cout << headings[customer][heading];
}
for(int month=0; month<3; month++)
{
cout << chargeLabels[month];
for(int charge=0; charge<3; charge++)
{
cout << charges[customer][month][charge] << ", ";
}
cout << endl;
}
for(int output=0; output<5; output++)
{
cout << outputLabels[output];
//error is below this comment
cout << output[customer][output] << endl;
}
}
Inside the for statement:
for(int output=0; output<5; output++)
{
You declared another variable int output which shadows the double output[3][5] with the same name outside the for statement.
Here's your problem:
double output[3][5];
for(int output=0; output<5; output++)
You're reusing output as a variable name twice.
So when you try to access it here:
cout << output[customer][output] << endl;
You're accessing the local output, which is just an int.

Passing an array by reference using pointers in C++

In some new territory working with pointers and references, I am attempting to pass an array by reference into a function using a pointer, however I keep getting errors no matter what I try, I am sure the problem is very simple to fix but I just cant seem to wrap my head around it, can anyone see the mistake im making? any help will go a long way thanks
#include<iostream>
#include<cmath>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <new>
using namespace std;
//Inline function
inline double getFahrenheit(double theCelsius)
{
//Convert the celcius to farenheit
return (theCelsius + 32) * 5 / 9;
}
void outputWeather(double *temperaturesArray, const string WEEK_DAY_NAMES[], const double MAX_NUMBER)
{
//this is a counter that will increment through the days and various
int counter;
//reset the counter to 0 so we can use it again
counter = 0;
//print a header
cout << "THIS WEEKS TEMPERATURE REPORT " << endl;
//print a divider
cout << "=============================" << endl;
//while the counter is less than 7 repeat again
while(counter < MAX_NUMBER)
{
//print out the temperatures by day
cout << WEEK_DAY_NAMES[counter] << " " << temperaturesArray[counter] << "\370C " << getFahrenheit(temperaturesArray[counter]) <<"\370F "<< endl;
//increase the counter by 1
counter +=1;
}
}
//Function that will determine whether or not the value the user entered was numeric and within the range
double checkValidation(string weekDay)
{
//Create a variable to store a valid number
double validNumber;
//This will hold the value for the lowest
const double MIN_NUMBER = 1;
//This will hold the value for the highest temperature
const double MAX_NUMBER = 365;
//This will hold the value for the valid number that the user will eventually enter
validNumber = 0.0;
//This will alert the user to enter a temperature for that day of the week
cout << "Please enter the temperature for " << weekDay << endl;
//This will take in teh value the user entered for teh temperature
cin >> validNumber;
//If the text the user entered was not numeric start again
if(cin.fail())
{
//C++ built in methods for clearing the cin
cin.clear();
fflush(stdin);
//alert the user what they typed was wrong
cout << "invalid input. please try again and enter a numeric value" << endl;
//pass in the weekeday and start over
checkValidation(weekDay);
}
else
{
//if teh number falls outside the range
if(validNumber < MIN_NUMBER || validNumber > MAX_NUMBER)
{
//Alert the user that it was outside the range
cout << "invalid input. please try again and enter a value between -90 and 60" << endl;
//pass in the weekday and try again
checkValidation(weekDay);
}
}
//return the valid number
return validNumber;
}
int main()
{
//this is a counter that will increment through the days and various
int counter;
//a constant to hold the variable for the number of days
const int MAX_COUNTER = 7;
//an array that will hold all the days of the week
const string WEEK_DAY_NAMES[] =
{
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
//this will hold all of teh temperatures
double temperaturesArray[MAX_COUNTER];
//start the counter off at 0
counter = 0;
//begin telling the user to enter temperatures by printing a header
cout << "Please enter the temperature for every day of the week " << endl;
//while the counter is less than 7 we will repeat
while(counter < MAX_COUNTER)
{
//add temperature to the array
temperaturesArray[counter] = checkValidation(WEEK_DAY_NAMES[counter]);
//add 1 to the counter
counter +=1;
}
double * arrayPointer = new double[MAX_COUNTER];
arrayPointer = &temperaturesArray;
outputWeather(arrayPointer, WEEK_DAY_NAMES, MAX_COUNTER);
system("PAUSE");
return 0;
}
In C++, the size of an array is encoded into its type.
There is no general "array of doubles" type. But there is an "array of 7 doubles" type, and an "array of 13 doubles" type, and so on.
So to pass an array as an array, and not simply as a pointer, to a function, you need to encode the precise type in the function's signature.
It won't be "a function which takes an array", but "a function which takes an array of size 7".
The way to do that is as follows:
void f(double (&arr)[7]);
Or of course, you can template it, if the array size is not fixed:
template <size_t N>
void f(double (&arr)[N]);
But really, what you're trying to do shouldn't be done using raw arrays at all.
Use the standard library vector.
Briefly, replacing line
arrayPointer = &temperaturesArray;
with
arrayPointer = temperaturesArray;
makes the code to compile.
Notice that arrayPointer is of type double* and temperaturesArray is of type double[MAX_COUNTER] (with MAX_COUNTER = 7). Hence, you can assign arrayPointer to the address of a double but you cannot assign arrayPointer to the address of a double[MAX_COUNTER]. That's what the original code attempted to do and thus, it failed to compile.
On the other hand, each element of a double[MAX_COUNTER] is a double. In particular, the first element is a double and you can assign its address to arrayPointer:
arrayPointer = &temperaturesArray[0];
The fix above is just a synctatic sugar for this line. Indeed, when you assign an object of type "array of type T" (e.g. double[MAX_COUNTER]) to a "pointer of type T", then the compiler performs the so called array-to-pointer conversion which means that is assigns the address of the first array element to the pointer.
Now a little remark on your code (with the provided fix), specifically, the following lines:
double * arrayPointer = new double[MAX_COUNTER];
arrayPointer = temperaturesArray;
The first line above allocates heap memory to store an array of MAX_COUNTER objects of type double. Then the address of the first element of this array is assigned to arrayPointer.
Then, the following line reassigns arrayPointer to the address of the first element of temperaturesArray. Therefore, the address of the first element of the heap allocated array is lost and you can no longer delete it. Remeber that every call to new must be matched by a call to delete (otherwise you have a memory leak). In this particular case, however, the best thing to do isn't call delete. Actually, you should eliminate the call to new since the heap memory is never used. More precisely, you can remove the first line above.