The variable needs an initializer c++? - c++

How do I initialize convert.gram? Whenever I define "gram" in the class decleration the program responds appropriatly. Im trying to put gram in the constructor but its not working. Also am I structuring everything right? Thanks for the help!
Code:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <windows.h>
#include "math.h"
using namespace std;
struct grams{
grams();
float converter(float pounds);
float gram;
float pounds;
float answer;
};
float grams::converter(float pounds){
answer = pounds * gram;
return answer;
}
grams::grams(){
float convert.gram = 453.592;
}
int main(){
float PtC;
grams convert;
cout<<"Pound to Gram Converter \n";
cout<<"How Many Pounds Do You Want to Convert? \n";
cin>>PtC;
float converter = convert.converter(PtC);
cout<<"Answer = "<<converter<<endl;
return 0;
}
Error:
C:/Users/lisa/Desktop/codelight c++/time_of_for_loop/for_loop_time/for_loop_time/main.cpp:31:13: error: expected initializer before '.' token

What you need to do is just set gram; convert is a instance of grams so its field will be set properly.
grams::grams(){
gram = 453.592;
}
But the more conventional and performant way to initialize class members is to use a member initializer list, like so:
grams::grams() : gram(453.592) {
}
Also, a bit of advice: Because you are using gram as a constant, it would make more sense to set it as a constant instead of a member. You can set it as a static member (and name it better)
struct grams {
static const float GRAMS_PER_POUND = 453.592;
...
You also aren't using the member pound at all; you should consider removing it. There also doesn't make much sense to store answer because you aren't using it via convert after the converter function completes.

Related

Can I use `distance` as my class member variable name?

It would be ok to define a class like this (ignore its implmentation):
class MyEngine {
private:
int* params;
int param_len;
public:
void set_params(int* _params, int _len);
float get_result(); // relies on `distance` member
float distance; // people can modify this
};
However, if using vector, assume it implicitly includes <iterator> which contains std::distance, how do compiler distinguish std::distance and distance member? (Or will it cause un-expected crash when run?). Say, the function get_result() relies distance member value.
#include <vector>
using namespace std;
class MyEngine {
private:
vector<int> params;
public:
void set_params(int* _params, int _len);
float get_result(); // relies on `distance` member
float distance; // people can modify this
};
update
As people mentioned, using namespace std is bad practice; however, there are still people writing code with using namespace std, and if we are collaborate with them, using their code, is there any concreate example that demonstrate the badness of using namespace std, expecially severe run error? This, would be my real purpose.
There is an answer, saying distinguish the two distance by type. Let's just try this snippet:
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iterator>
using namespace std;
class MyEngine {
private:
vector<int> params;
float* distance; // people can modify this
int len;
public:
void setup();
};
void MyEngine::setup()
{
len = 100;
distance = (float*)malloc(sizeof(float)*len);
for(int i=0; i<len; i++) {
distance[0] = len - i;
params.push_back(len-i);
}
int num = distance(params.begin(), params.end());
printf("distance is: %d\n", num);
}
int main(){
MyEngine engine;
int len = 10;
engine.setup();
return 0;
}
Which, would cause compile error saying:
main.cpp:25:23: error: called object type 'float *' is not a function or function pointer
int num = distance(params.begin(), params.end());
~~~~~~~~^
1 error generated.
Demonstrates that it can't distinguish the two distance from their types.
Well, one is MyEngine::distance, and the other is std::distance. They're different names. This is the whole point of scopes.
There is only a problem if you use the unqualified name distance and leave the compiler to figure it out, but if that's not going to work then it'll be because the type of the one chosen doesn't match your usage, so your program won't compile.
If you ever did put things in std then the name can clash in potentially undiagnosable ways, which can cause crashes, and has undefined behaviour per the standard.
The function distance has a different type than the member distance, so the compiler figures that out by the type.
You can even have a function distance(...). As long as parameters are different, they have different type and the compiler figures that out.
Also note that you should not use using namespace std because that also irritates the human reader.
In your updated example, the compiler is indeed confused. You can specify that you want to use the distance function in this case by changing it to int num = std::distance(...);

CanĀ“t use an union element inside a nested structure as argument for scanf() to store desired value

I have a problem about to use scanf with an union element as an argument which superior union is part of a nested structure.
#include <stdio.h>
int main()
{
typedef union { float chair; int bed; } HABITATION;
typedef struct { HABITATION room; int number; } HOUSE;
scanf("%d",&HOUSE.room.bed);
}
The error message from the compiler is :
"Error: expected expression before ) >>ROOF<<".
What have i done wrong?
INFO:
I currently use C but i am also interested for the same operation and answer in/ for C++.
I dont know C, but in C++ your code should be equivalent to:
#include <stdio.h>
union HABITATION { float chair; int bed; };
struct HOUSE { HABITATION room; int number; };
int main()
{
scanf("%d",&HOUSE.room.bed);
}
Maybe now it is obvious that you merely defined two types, but you never create an instance of anything in this code. HOUSE is a type not an instance.
In c++ you would do
#include <iostream>
int main()
{
HOUSE h;
std::cin >> h.room.bed;
}
And probably not use all CAPITAL names. Some use them for globals, I am more on the side of banning them completely. Names should speak for themself, no need to shout. House is clear enough if you use first letter capital for classes and all small letters for instances (eg house). Thats also what Stroustrup suggests in his guideline.

Having trouble dynamically allocating an array with a created class in C++

I've actually managed to successfully do a dynamically allocated array with a normal data type, but it was a while ago (like, six chapters!) And I can't figure out why I can't set the array dynamically here - I know it's giving me an int error, but I can't use the class type because the class type doesn't deal with numbers like that. At this point I'm pretty confused. Here's my code including headers:
#include <iostream>
#include "milTime.h"
#include "Time.h"
using namespace std;
int main()
{
milTime *theta;
bool amOrPm;
int milHr, milSc,milM,times;
cout<<"How many times would you like to convert?";
cin>>times;
theta = new milTime;
*theta = times;
And here's my error:
Error 1 error C2440: '=' : cannot convert from 'int' to 'milTime
*' c:\users\heather\documents\visual studio 2012\projects\military time\military time\source.cpp 17 1 Military Time
Any help would be greatly appreciated, as I'm completely done except for that. Me and my bright ideas to let it be dynamically allocated!
Here's the milTime class that was requested:
#ifndef MILTIME
#define MILTIME
#include <iostream>
#include "Time.h"
class milTime : public Time
{
protected:
int milHours;
int milMins;
int milSeconds;
public:
void setTime(int h)
{
milHours = h;
}
void setMin(int m)
{
milMins=m;
}
void setSec(int s)
{
milSeconds=s;
}
int getmilHours()
{return milHours;}
int getmilMins()
{return milMins;}
int getmilSeconds()
{return milSeconds;}
bool timeConverter(int mTime, int mMins, int mSecs)
{
bool aOrPm;
min = mMins;
if(mTime<12)
{
hour = mTime;
aOrPm = false;
//AM will be false.
}
else if (mTime>12 && mTime<=24)
{
hour = mTime%12+1;
aOrPm = true;
}
sec = mSecs;
return aOrPm;
}
};
#endif
there are already answers why your code doesn't work
just in case you wanted to allocate an array of milTime, you will need to do it like this:
theta = new milTime[times];
this will create times of milTime objects
anyway, you should be using std::vector instead of dynamic allocations, this is much safer
What is the definition of milTime?
You are trying to assign an int, which is an inbuilt integer type, into your own type milTime. Which won't work unless your type has an assignment operator which takes an int.
Does your type have a constructor that takes an int? as in that case you would want something more like:
theta = new milTime(times);
theta is a pointer to miltime but times is an int hence *theta = times; fails.
Here's your problem:
*theta = times;
theta is a class of milTime, times is an int.
You'll probably need to create a setter method in milTime, like this:
theta.setTime( times )
I can't see your milTime class though, can you post it as well?
Well it seems that in this line:
*theta = times;
You try to assign an int to a milTime.
you can fix this by either doing a static cast:
*theta = static_cast<milTime>(times);
Or oldschool cast:
*theta = (milTime) times;
But prefarbly you can add a constructor to milTime (in miltime.h):
milTime(int i) : someInnerDataWhichIsAnInt(i) {}
The last one is preferable as casts are a sign of a bad structure.
To use the last one do this:
theta = new milTime(times);
Or is it because you need an array? Prefaably use:
std::vector<milTimes> theta() // You need to remove prior definition of `theta`.

Error when changing a vector value in a class

I am attempting to change a value in a vector which is a variable in a class using a function of a class. When I compile, i get the following errors pointing to the "check[c] = cval;" line:
error C3867: 'acc::check': function call missing argument list; use '&acc::check' to create a pointer to member
error C2109: subscript requires array or pointer type
Note: I have already initialized C to be 0 elsewhere in the program. It might be throwing an error because I am giving the address a variable instead of an integer, but when I substitute the variable with an integer, I still get the same errors.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
class acc
{
public:
void add_Cval(double cval);
private:
vector<double> check(); //vector of all checks
int c; //loop marker for cvals
};
void acc::add_Cval(double cval)
{
check[c] = cval;
c++;
}
vector<double> check(); isn't what you think it is. You just declared a function named check that returns a vector<double>. Get rid of the parenthesis like so vector<double> check;.
Also, your vector<double> is empty, you need to give it some space if you want to do check[c] = cval; (or use check.push_back(cval); instead), allocate the space in the constructor (use "initialization lists" as that is what they are for):
Example:
acc(int vecsize) : check(vecsize), c(0) {}
You might also want to make sure check[c] is a valid position in the vector before assigning anything to it.
check is a method, not a data member, so you need to invoke it - check().
void acc::add_Cval(double cval)
{
check()[c] = cval;
c++;
}
or make it a data member:
class acc
{
public:
void add_Cval(double cval);
private:
vector<double> check; //vector of all checks
int c; //loop marker for cvals
};
The compiler is looking for a function called check() that returns a vector of type double.
private:
vector<double> check(); // A private function that returns a vector of type <double>
Needs to be:
private:
vector<double> check; // A private data member

How can I generate random int numbers within a set range (without duplicates!) within a class constructor?

I am self-learning C++ from a text book and I have a problem to solve, outlined below.
I have the following class structure:
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
class classroom{
char name[25];
int student_id;
float grades[10];
float average;
int num_tests;
float letter_grade;
public:
void enter_name_id(void);
void enter_grade(void);
void average_grades(void);
void letter_grades(void);
void output_name_id_grade(void);
classroom();
};
And I have the following Constructor for the above class:
classroom::classroom(){
int i;
srand((unsigned)time(0));
int random_integer=0;
random_integer = (rand()%5) + (rand()%5);
num_tests=0;
average=0.0;
for(i=0;i<10;i++){
grades[i]=0.0;
}
for(i=0;i<27;i++){
name[i]='-';
}
cout<<"\n*****************Finished*****************";
}
There will be 3 students of this class structure declared in the main:
int main()
{
classroom students[3];
//and so...
}
I need to generate a unique student ID for each student in the constructor within a range of values, say, 0 to 10.
I have copied the following code snippet into the constructor. It generates my random number for me within the desired range:
srand((unsigned)time(0));
int random_integer=0;
random_integer = (rand()%5) + (rand()%5);
The problem is that I need to get rid of any duplicates within the range of random numbers that are generated.
Why does the number need to be random? Can't you just use a static int that gets incremented every time you need to generate a new student number?
Simply have a vector with all possible student ids. in your case 0..Range.
do a random_shuffle and pick the first three ids and assign them
I have added a working solution.
//Only have one instance of this class.
class IdMgr
{
std::vector<int> mIds;
int mCurrentId;
public:
IdMgr( int Max )
{
for ( int i = 0 ; i <= Max; ++i )
mIds.push_back( i );
std::random_shuffle( mIds.begin() , mIds.end() );
mCurrentId = 0;
}
//Call this function from your class constructor
int GetNextId()
{
return mIds[ mCurrentId++];
}
};
One way to do this is to use what is called a static member variable. Usually, each object gets its own copy of the member variables. In your code, each student will have his own copy of name[25], student_id, etc. But what you want, is something that will be shared between each instance of the class (each of the elements in classroom students[3] are instances of the classroom class.)
Here are some notes on static member variables. Note that they present a solution to a very similar problem -- they assign unique IDs to each class instance. The only difference between what they present here and what you ask for is that you ask for it to be randomized, instead of consecutive.
So instead of a static member variable keeping track of one number (the last one assigned), you will want your static member variable to keep track of all of the previously assigned ids. A std.vector or simple int array should work.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace std;
class classroom{
char name[25];
int student_id;
float grades[10];
float average;
int num_tests;
float letter_grade;
static vector<int> used;
public:
void enter_name_id(void);
void enter_grade(void);
void average_grades(void);
void letter_grades(void);
void output_name_id_grade(void);
classroom();
};
vector<int> classroom::used = vector<int>();
classroom::classroom(){
int i;
int random_integer=0;
bool rand_ok;
do
{
// Generate Random Integer
random_integer = (rand()%5) + (rand()%5);
//cout << "Generated: " << random_integer << endl;
rand_ok = true;
for(i=0; i<used.size(); i++)
{
if(used[i] == random_integer){ rand_ok = false; break; }
}
} while (rand_ok == false);
// If we get here, random_integer is not in the used vector
// therefore accept and store as student_id
student_id = random_integer;
// ... and update used vector
used.push_back(student_id);
num_tests=0;
average=0.0;
for(i=0;i<10;i++){
grades[i]=0.0;
}
for(i=0;i<27;i++){
name[i]='-';
}
cout<<"*****************Finished*****************\n";
}
int main()
{
// You should only seed the RNG once
srand((unsigned)time(0));
classroom students[3];
}
The above code is one way you might do it, by storing the used student ids in a vector, and then every time you create a new student, ensure the randomly generated id doesn't match an already assigned ID.
One other note, you should only seed the random number generator once (especially if your seed is the time). Since you were seeding it 3 times in such a short time, the random numbers being produced were the same.
For all those that want to know the solution to my problem of creating a unique id for each instance of a class, here it is:
class classroom{
char name[25];
int student_id;
float grades[10];
float average;
int num_tests;
float letter_grade;
**static int next_student_id;**
public:
void enter_name_id(void);
void enter_grade(void);
void average_grades(void);
void letter_grades(void);
void output_name_id_grade(void);
classroom();
};
**int classroom::next_student_id=1;**
Notice, the new member: static int next_student_id has been created and used in the constructor, it has also been initialized outside of the class structure.
In the constructor I simply used the following code:
student_id=next_student_id++;
This code produced unique consecutive numbers for each instance of the Class classroom structure;
Please note I am aware that Class classroom is not an ideal name as it conflicts with the name of class, but I used this as I copied the basic naming from a text book question!
I have concluded that Alan's answer above helped me the most and provided me with the most simple solution.And so Alan therefore gets a tick from me.
I would like to thank Jedwards also, your answer if pursued could of also been an alternative solution... but as it turns out, using a static int was the key and generating random numbers and creating vectors was not necessary.
And thank you also parapura rajkumar and other contributors