I'm kind of inexperienced with C++, and I'm converting a program that I wrote in C to C++. I have a RollDice function that takes numbers that I read in from a text file and uses them to generate the number. This is the function in C:
void rollDice(Move *move, GameState *game_state) {
int diceNum1 = 0;
int diceNum2 = 0;
int randomNumber1 = 0;
int randomNumber2 = 0;
randomNumber1 = game_state->randomNums[game_state->current_roll]; //gets the random number from the array randomNum (which holds the numbers from the text file), at index "current_roll"
game_state->current_roll++; //increments so the next random number will be the next number in the array
diceNum1 = 1 + (randomNumber1 % (1 + 6 - 1));
randomNumber2 = game_state->randomNums[game_state->current_roll];
game_state->current_roll++;
diceNum2 = 1 + (randomNumber2 % (1 + 6 - 1));
move->dice_sum = diceNum1 + diceNum2;
printf("You rolled a %d!\n", move->dice_sum);
}
This works just how I want it to when I run it. Now, when converting my program to C++ I had to change things around. My parameters are now pass by reference and I made a vector to store the list of random numbers from the text file:
void rollDice(Move& move, GameState& game_state) {
std:: vector<int> randomNums = game_state.getRandomNums();
int current_roll = game_state.getCurrentRoll();
int diceNum1 = 0;
int diceNum2 = 0;
int randomNumber1 = 0;
int randomNumber2 = 0;
randomNumber1 = randomNums.at(current_roll);
current_roll++;
diceNum1 = 1 + (randomNumber1 % (1 + 6 - 1));
randomNumber2 = randomNums.at(current_roll);
current_roll++; //this line is grayed out and says "this value is never used"
diceNum2 = 1 + (randomNumber2 % (1 + 6 - 1));
move.dice_sum = diceNum1 + diceNum2;
std:: cout << "You rolled a " << move.dice_sum << "!\n";
}
My code is telling me that the second time I increment current_roll it is unused. This didn't happen for my C code, so why is it happening here and how can I fix it? I'm completely lost.
It's never used because you write to the variable, but never read from it. Having a variable that you never read is effectively meaningless.
Presumably your game_state.getCurrentRoll function returns an integer, when you store this, you store the value (rather than a reference to the value), thus incrementing it doesn't increment the current roll inside the game_state, instead you should add a function to your game_state called makeRoll for example which increments the game_states internal current_roll value.
This is different from your C code which increments the current_roll value directly using game_state->current_roll++ (alternatively you could make game_state.current_roll public and increment it the same way as in your C code).
From your comment I assume you have some class:
class GameState {
private:
int current_roll;
...
public:
int getCurrentRoll() {
return current_roll;
}
...
}
All you'd need to do is add another function to your class to increment the current_roll:
class GameState {
private:
int current_roll;
...
public:
int getCurrentRoll() {
return current_roll;
}
void makeRoll() {
current_roll++;
}
...
}
Then you can call it as normal.
Regarding your new issue in the comments regarding the error:
parameter type mismatch: Using 'unsigned long' for signed values of type 'int'.
This is because the signature of at is std::vector::at( size_type pos ); That is, it expects a value of type size_type which is an unsigned integer type, rather than int as you're using which is signed. This post may be helpful.
Related
Here is my code I have looked up what to do multiple times and still haven't figured out what to do.
It keeps giving me this error: C++ expression must be an lvalue or a function designator with the part of the code :
avg_score = (float)*&get_average_score(score_1, score_2, score_3);`
how can i fix the error?
the original error was cannot convert a void to a float
avg_score = get_average_score(score_1, score_2, score_3);
how can i fix the error?`
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <ctime>
using namespace std;
void print_scores(int score_1, int score_2, int score_3);
void get_average_score(int score_1, int score_2, int score_3);
int main()
{
srand(time(NULL));
int score_1, score_2, score_3;
float avg_score;
score_1 = rand() % 21 + 20;
while (score_1 % 2 == 0)
{
score_1 = rand() % 21 + 20;
}
score_2 = rand() % 21 + 20;
score_3 = rand() % 21 + 20;
print_scores(score_1, score_2, score_3);
avg_score = (float)*&get_average_score(score_1, score_2, score_3);
cout << fixed << setprecision(1);
cout << "Average score = " << avg_score <<
endl;
return 0;
}
void print_scores(int score_1, int score_2, int score_3)
{
cout << "score 1 = " << score_1 << endl << "score 2 = " << score_2 << endl
<< "score 3 = " << score_3 << endl;
}
void get_average_score(int score_1, int score_2, int score_3)
{
(float)(score_1 + score_2 + score_3) / (float)3;
}
Your first mistake lies in the fact that you are trying to get a function that does not return a value to return a value. You've tried to reference a pointer *& which is not how you should be handling this as
1) you've tried to reference a pointer but instead you've done it on a function
2) you want a value, not a pointer so its the wrong approach.
If you need to use pointers (because thats the task at hand) then what you need to do is pass a reference to avg_score into your function.
void get_average_score(float * avg_score, int score_1, int score_2, int score_3)
{
*avg_score = (score_1 + score_2 + score_3) / 3.0;
}
and call it in main with:
get_average_score(&avg_score, score_1, score_2, score_3);
and dont forget to update the header declaration:
void get_average_score(float * avg_score, int score_1, int score_2, int score_3);
If you don't have to use pointers the easiest fix is to actually return a value.
Declare the function as type float :
float get_average_score(int score_1, int score_2, int score_3);
and edit the get_average_score function to be:
float get_average_score(int score_1, int score_2, int score_3)
{
return (score_1 + score_2 + score_3) / 3.0;
}
and get rid of (float)*& from main.
This means your function will return a float value that will be stored in avg_score on return.
Also note, by changing the denominator to 3.0 instead of 3 you don't need to don't need to type cast the result as a float.
Your coding style does come off as a little basic (which is ok, everyone has to start somewhere) but you have room for improvement, so take the time to learn now rather than struggling later (trust me it makes life easy in the long run).
Rather than making a function that will only work when you are averaging 3 numbers why not make a more modular function that would work for as many numbers as you want!
Try learning how to use vectors! If you're coming from C its kinda like an array but can be dynamically allocated i.e. any size you want.
Have a look around the net for some tutorials on what vectors are and how to use them.
I won't write out the code for this because you should learn how to do it your self (trust me you'll understand it better) but basically using a vector of int's std::vector<int> you can iterate through them all and add each element together and then at the end divide by the total number of elements (the number of iterations you do) to get your average!
**obviously theres a limit but thats a limit of your computer... *
i am a beginner in c++ ..so please help me get this right.
trying to read from the collection, in one version of implementation I have tried ,there was some bippings from the console, another test.. displays numbers so its probably the pointer to the string...
the code is as follows
DataCollection.h
typedef struct _DataC
{
char* buffer;
UINT Id;
} DataC;
void GetDataC( int ArrSize, DataC** DArr );
DataCollection.cpp
#include "DataCollection.h"
void GetDataC( int ArrSize, DataC** DArr )
{
int count = 0;
int strSize = 10;
*DArr = (DataC*)CoTaskMemAlloc( ArrSize * sizeof(DataC));
DataC* CurData = *DArr;
char TestS[] = "SomeText00";
for ( int count = 0; count < ArrSize; count++,CurData++ )
{
TestS[strSize-1] = count + '0';
CurData->Id = count;
CurData->buffer = (char*)malloc(sizeof(char)*strSize);
strcpy(CurData->buffer, TestS);
}
}
test the collection:
int main(void)
{
StpWatch Stw;long ResSw;
DataC* TestDataArr;// maybe use DataC TestDataArr[] instead...
GetDataC(100000, &TestDataArr);
}
how can i read the collection within a loop ?
for...
std::cout<<TestDataArr[count].buffer<<std::endl;
or ?
std::cout<<TestDataArr->buffer<<std::endl;
What is the correct implementation to read each element in a loop?
thanks for your time.
DataC* TestDataArr and DataC TestDataArr[] are the same thing. That said, when you try to reference TestDataArr you may do one of two things:
TestDataArr[index].buffer
or
(TestDataArr + index)->buffer
Because TestDataArr is a pointer you must deference it before you may use any of its members, this is what index does. Using the first method, as an array index, the pointer is dereferenced at index in the array and you then may use . to access members of the object. The second method, index advances the pointer to the memory location but does not dereference the pointer, so you must use -> to then access its members.
So to print the buffer in a loop, you could use either:
std::cout << TestDataArr[count].buffer << std::endl;
or
std::cout << (TestDataArr + count)->buffer << std::endl;
The blipping you mention is probably because of TestS[strSize-1] = count + '0'; where count + '0' creates a character outside of the ASCII range. Some of these characters will cause console beeps.
The problem is in TestS[strSize-1] = count + '0';. When you pass ArrSize == 100 0000 then in the for loop the count + '0' value at a some moment exceeds the range of char and you get a char value in the range [0-31] (non-printable characters). At least use
TestS[strSize-1] = '0' + count % (126 - '0');
The last char of TestS will be changed in the range [48-126] (ASCII printable characters).
I am supposed to get the following code to display something along the lines of: "The sum of 1 to 10 is 55." (The larger number can be any number that was just the example I got.) I was given this code to use.
#include <iostream>
using namespace std;
// Compute the sum of all of the numbers from 1 to n where n
// is a natural number
// use the formula: n(n+1)/2
void compute_sum(int limit) // compute_sum function
{
int sum_to_limit;
sum_to_limit = limit * (limit + 1) / 2;
}
int main()
{
int sum = 0;
int maxNumber;
// get the maxNumber for the function call
cout << "Enter a whole number greater than 0" << endl;
cin >> maxNumber;
// call compute sum
compute_sum(maxNumber); // Call to compute_sum function
// display the sum calculated by the compute_sum function
cout << "The sum of 1 to " << maxNumber;
cout << " is " << sum << endl;
return 0;
}
I do not understand how funcctions work at all and do not have any idea how I would go about getting this to work. The only thing I know about this (and this is from the teacher) is that the change required is not major. "Note: If you are making major changes to the main and compute_sum funtions you are probably
doing way too much work." I have tried changing the function to an int function with a return but I could not get it to work properly (most likely due to not knowing how functions work). So can someone please help me?
The part you're missing is the return type of the function, and then to actually return that value from the function.
At the moment you have
void compute_sum(int limit) // compute_sum function
{
int sum_to_limit;
sum_to_limit = limit * (limit + 1) / 2;
}
A function prototype in C looks pretty much like this
<return type> <name> (<parameters>)
{
// your logic here
return <your_own_variable> // Note: You can omit this if the return type is void (it means the function doesn't return anything)
}
You want to modify your function so you are returning the integer value you're calculating inside of it
int compute_sum(int limit) // compute_sum function
{
int sum_to_limit;
sum_to_limit = limit * (limit + 1) / 2;
return sum_to_limit;
}
So what happens is after main runs, when the the point of execution hits
compute_sum(maxNumber);
The program flow jumps to that function and executes the code inside of it. When the function finishes, it returns the value back to where it was originally called from. So you also need to add this to store the value returned
int result = compute_sum(maxNumber);
and then make sure to output that value to the user.
You can also make the computer_sum function a little more terse my not storing a temporary variable, you can just do this
int compute_sum(int limit) // compute_sum function
{
return limit * (limit + 1) / 2;
}
I hope that helps. There's a lot more going on behind the scenes but that's the basic idea. Good luck! :)
So I wanted to write code which solves this problem: "Collecting Beepers"
And I did:
int rec(int current, int beers)
{
if(beers == (1 << (numOfBeers + 1)) - 1) return cost(beerX[0], beerY[0], beerX[current], beerY[current]);
int optimal = 100000;
for(int i = 1; i <= numOfBeers; ++i)
{
if(((1 << i) & beers) == 0)
{
int newBeersSet = (1 << i) | beers;
int c = cost(beerX[current], beerY[current], beerX[i], beerY[i]);
int current = c + rec(i, newBeersSet);
optimal = min(optimal, current);
}
}
return optimal;
}
The strange thing is, that when I replace the part
int c = cost(beerX[current], beerY[current], beerX[i], beerY[i]);
int current = c + rec(i, newBeersSet);
with
int current = cost(beerX[current], beerY[current], beerX[i], beerY[i]) + rec(i, newBeersSet);
the logic is absolutely the same and yet my program crashes on the same (the one given in the problem desciption) input and the online judge gives wrong answer as a result from the program execution while with the original code it gives Accepted. Any ideas what could possibly be wrong?
That is propably because your variable "current" is overriden. Try:
int current2 = cost(beerX[current], beerY[current], beerX[i], beerY[i]) + rec(i, newBeersSet);
optimal = min(optimal, current2);
In this line you are using an uninitialized variable:
int current = cost(beerX[current], // ...
This declares a new variable current and then, before the variable has had a value assigned, uses it as index to beerX.
You probably meant:
int new_current = cost(beerX[current], // ...
which uses the existing current variable which was declared in the parameter list for the rec function.
Alright so i have two identical string methods...
string CreateCust() {
string nameArray[] ={"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
int d = rand() % (8 - 1 + 1) + 1;
string e = nameArray[d];
return e;
}
string CreateFood() {
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = rand() % (3 - 1 + 1) + 1;
string f = nameArray[d];
return f;
}
however no matter what i do it the guts of CreateFood it will always crash. i created a test chassis for it and it always fails at the cMeal = CreateFood();
Customer Cnow;
cout << "test1" << endl;
cMeal = Cnow.CreateFood();
cout << "test1" << endl;
cCustomer = Cnow.CreateCust();
cout << "test1" << endl;
i even switched CreateCust with CreateFood and it still fails at the CreateFood Function...
NOTE: if i make createFood a int method it does work...
Also guys even if i changed CreateFood to just COUT a message and nothing more it still crashed...
Take out the + 1 on both of them, you access arrays starting from 0:
int d = rand() % (8 - 1 + 1); // 0-7, not 1-8
int d = rand() % (3 - 1 + 1); // 0-2, not 1-3
Otherwise you're accessing a non-existent element, and this is undefined behavior. (That means it could appear to work, like in CreateCust, crash like in CreateFood, do nothing, or do anything.)
I'm not sure what the purpose of subtracting 1 then adding 1 is. In any case, now is the perfect time to learn: Don't Repeat Yourself. Even if you do something just twice, make a function out of it, it'll be less cryptic and more concise:
int random(int min, int max)
{
return rand() % ((b - a) + 1) + a;
}
This is a simple function that returns a random number between a and b, inclusive. (Means it can include both a and b in the results.) Now your code reads:
// I'll leave CreateCust up to you
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
int d = random(0, 2); // either 0, 1, or 2, randomly
string f = nameArray[d];
return f;
}
And you'll see even just one function makes it much easier to read; your goal is to make your code easy to read by humans. Also, this is much more concise:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return nameArray[random(0, 2)];
}
Another bad thing to do is hardcode magic numbers into your program. For example, why 3 or 8? It can be deduced those are array sizes, but that doesn't stand on its own. What you might want is something like:
string CreateFood(void)
{
const size_t ArraySize = 3; // 3 elements, 0-2
string nameArray[ArraySize] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ Ensure it matches
return nameArray[random(0, ArraySize - 1)];
}
Now the range for the number number makes sense up front.
The rest may be a bit advanced (which you won't understand until you get to templates), but shows how we might go on:
template <typename T, size_t N>
char (&countof_detail(T (&)[N]))[N];
#define countof(pX) sizeof(countof_detail(pX))
This nifty tool will give you the number of elements in an array. The code might turn into this
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
// ^ no explicit size
return nameArray[random(0, countof(nameArray) - 1)];
}
We got rid of any numbers altogether, you can just manipulate the array as you please. Lastly, we're repeating ourselves again: getting a random element from an array. We should make a function for that:
template <typename T, size_t N>
T& random_element(T (&pArray)[N])
{
return pArray[random(0, N - 1)];
}
This returns a random element from any array. Your function would then simply be:
string CreateFood(void)
{
string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return random_element(nameArray);
}
Note in this refactoring (refactoring is taking code and factoring it into new, simpler parts) it reads much better: To get a food, we have an array of foods and we pick one at random.
Keep this kind of stuff in mind while you work, and as you learn C++ you can make better code. Anytime you repeat a task that isn't trivial, make it a function. Suddenly that task is trivial, because you don't care about how the function works (that's in the function), just what the function does (that's the function name).
The crash is happening because you are accessing an invalid index. This is because array indexes start from 0 and not 1, so you don't want to add a 1 to the rvalue of the modulus operator.
Here is a neat trick that you can use to make your code a little more maintainable:
template <class T>
T getRandElem( const T[] arr )
{
return arr[ rand() % ( sizeof(arr) / sizeof((arr)[0]) ) ];
}
string CreateCust(){
static string nameArray[] = {"Tom","Timo","Sally","Kelly","Bob","Thomas","Samantha","Maria"};
return getRandElem<string>( nameArray );
}
string CreateFood(){
static string nameArray[] = {"spagetti", "ChickenSoup", "Menudo"};
return getRandElem<string>( nameArray );
}
Look here:
int d = rand() % (8 - 1 + 1) + 1;
This will return a number between 1 and 8 inclusive. What you need is this:
int d = rand() % 8;
You're going outside the bounds of the array. The array object begins at 0.
I don't understand why you have
int d = rand() % (8 - 1 + 1) + 1;
Why not just use
int d = rand() % 8;
I think modern c++ compilers will still let you use an old C trick for static arrays:
string CreateFood()
{
char* nameArray = {"spagetti", "ChickenSoup", "Menudo"};
// note the trick to get the compiler to count the array elements for you:
int d = rand() % (sizeof(nameArray) / sizeof(nameArray[0]));
return std::string( nameArray[d] );
}