Wrong value in array which contains instances of a class (C++) - c++

I use an array to create instances of a class.
I declared them in the Header file:
Figure *soldier;
Fight *weapon;
In the cpp I use the following code to create it:
std::cout << "How many soldier? ";
std::cin >> i_soldier;
std::cout << "How many weapon? ";
std::cin >> i_weapon;
soldier= new Figure[i_soldier];
weapon = new Fight[i_weapon];
The class Figure has this constructor:
Figure::Figure()
{
position = 0;
}
When I'm running the code it compiles fine, but when I look the position at the begin, the last array entry has a wrong value; I guess it points at a value from a memory address. All the other entries have the value 0.
This is how I say which instance I want to go.
for(int i = 0; i <= i_soldier; i++)
{
soldier[i].position();
}
Does anybody know where the error can come from?

Arrays are 0-indexed, the last position of the array is i_soldier-1, change your condition to a strict <.

Related

Unexpected array behavior in basic averaging program

It seems like I always come here to ask silly questions, but here it goes. As of right now I am in my first compsci course and we are learning c++. I've had an extremely basic introduction to c before, so I had thought I'd go above and beyond my current assignment. Now I was doing this just to showboat, I felt like if I didn't practice my previous concepts they would eventually fade. Anyways, on to the problem! I was supposed to write some code that allowed the user to input their initials, and a series of exams. Now this was supposed to accomplish three things: average the exams, print out the entered exams, and print out their initials. Well, what was a simple assignment, got turned into a huge mess by yours truly.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
string uInitials;
float avgExam = 0, tExam = 0;
int aExams[10] = {'0'};
int i, nExam = 0, cExam;
cout << "Enter your three initials!";
cin >> uInitials;
do
{
cout << "Enter your exam(s) to be averaged. Enter 0 when complete!\n";
cin >> cExam;
aExams[nExam] = cExam; //I used this before nExam was incremented, in order to get nExam while it was '0' That way the first exam score would be properly saved in the first space
nExam++;
tExam += cExam; //This is just to add all the exams up to later calculate the average
}
while(cExam != 0);
avgExam = tExam/(nExam - 1); //subtracted '1' from nExams to remove the sentinel value from calculations.
cout << "The average for initials: " << uInitials << " is: " << avgExam << endl;
cout << "This average was obtained using the following scores that were entered: \n";
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
return 0;
}
The previous is my code, and the problem is that I'm getting output errors where it adds two '0's when I print out the list of entered exams. Also I feel like I made the whole do{}while() loop one huge clunky mess, so I'd like to refine that as well. If anyone could assist this poor, ignorant, beginner I would greatly appreciate it. Thank you for your time!
Some advice that i can give is for example in the 5th line there is no need
to put the 0 between ' ' and not even need to use the assign = operator.
You can initialize the array like this:
int aExams[10]{0};
Which will initialize all elements to 0,but can't be used for other value.
For example you won't have all the elements with value 1 if you write
int aExams[10]{1};
If your intention to initialize all elements in an array is with value other than 0 you can use fill_n(); function.
fill_n(aExams, 10, 1);
The first argument is the name of the array, the second is up-to which element you want to be initialized with the third argument, and the third is the value you want all elements to have.
Do not leave uninitialized variables like in line 6 with cExam and i variables. Initialize it like cExam=0; (copy-assign initialization) or cExam(0); (direct initialization). The latter calls the constructor for int built-in type.
A negative i see in your do-while loop is that you do not make sure that the user will enter under 10 exams,bad things will happen if the user tries to input 15 exams in an array that can hold only 10.
Just change the while to something more like this:
while( cExam != 0 && (nExam<10) );
You can also write the first two lines of the do-while loop outside the loop.
It is needed only once to tell the user that to stop the loop he/she needs to enter 0. There is no need to tell them this on every iteration plus that you will have a good performance benefit if you put those two lines outside the loop.
Look here how i would write the code and ask if you have any questions.
http://pastebin.com/3BFzrk5C
The problem where it prints out two 0's at the end of your code is a result of the way you wrote your for loop.
Instead of:
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
Use:
for (i = 1; i < (nExam); i++)
{
cout << aExams[i - 1] << endl; //Used a for loop to prevent redundancy
}

Accessing data inside an array via pointer error

I have 2 files in msg format. msg format is not important here.
car.msg
int speed;
int width;
cararr.msg
car mycar[];
I want to print all the information about all the cars that are present but I have no clue about the number of cars present(how big is the array) so I use the following technique to print the information.
so I do this:
cararr* ptr2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << ptr2car->mycar[i].speed <<endl;
cout << ptr2car->mycar[i].width <<endl;
}
Despite this, I am receiving errors. I do not know what did I do wrong. I have no clue what approach should I use to get this output. please Help
Also why should I take a pointer to cararr, when I can just take an instance of cararr inst2car and do something like this:
cararr inst2car;
for(int i=0;mycar[i] != '\0'; i++){
cout << inst2car.mycar[i].speed <<endl;
cout << inst2car.mycar[i].width <<endl;
}
thanks
In general you need to know exactly what's at the end of the array. You need some sort of sentinel value to use as a delimiter to indicate the end of the array.
'\0' used in c strings is an example of such delimiter.
You need to ensure the last element in the array is such delimiter and check for it in the condition.
It's hard to give you more specific answer with such generic question.
For example, if you knew the last element will have speed -1, you can use that:
for(int i=0;mycar[i].speed != -1; i++) {

Dynamic object creation

I am new to c++ programming and I have a basic issue, I want to create N objects, N is is actually a user input.
I am specific about having object names, say beam1, beam2,...,beamX.
2 quick things
Is it possible in C++ to create dynamic object as this?
if it is how do we do tht? I am pasting code for your refrence..
#include "iostream"
# include <conio.h>
using namespace std;
// Static member variable is defined outside the class..
class beam {
public:
int length;
};
int main ()
{
int i=0, no_of_spans, j;
cout<< "Design Of a Continous Beam \n1) No Of Spans : ";
cin >> no_of_spans;
for (i =0; i < no_of_spans; i++) {
j = i;
beam;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
}
cout << "\nPress any key to continue..\n";
getch ();
}
This is obviously a code with errors, its put up as an example to get the idea.
As has already been stated by others (Luchian, John, Component and Ed) you can use a std::vector and it will dynamically grow as necessary to store the number of beam objects required.
If you wish to refer to these objects later by name you could store them in a std::map, with the key of the map being the object name (e.g. beam1, beam2, beam3, ..., beamX):
std::map<std::string, beam> beams;
for (int i = 0; i < no_of_spans; i++)
{
j = i;
beam beam;
std::string beam_name("beam" + boost::lexical_cast<std::string>(i + 1));
cout << "Length of " << beam_name << " is : ";
cin >> beam.length;
beams.insert(std::make_pair(beam_name, beam));
}
--
boost::lexical_cast<> is a mechanism for converting (in this case) an int to a std::string. There other ways to achieve this (using std::ostringstream for example).
You can use a std::vector to store the objects.
You use push_back to add elements to the vector.
Something along the lines of:
std::vector<beams> beamCollection;
for (i =0; i < no_of_spans; i++) {
j = i;
beam beami;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
beamCollection.push_back(beami);
}
Yes, of course it's possible. There are several ways.
One way, the way I'd prefer if possible/practical, is to use std::vector and push_back, transform or generate_n how ever many objects you needed.
Another way is to use new to allocate an array of the object you want. This is less preferred to using a vector however, because by using new you take on the responsibility of managing the memory -- there needs to be a delete that corresponds to every new. This can be mitigated by using a smart pointer such as std::unique_ptr, but it's often best to just avoid the cactus altogether.
Yes, it is possible. Your best bet is to use an appropriate STL collection and dynamically grow it at runtime by adding / removing objects.
Short answer no - the compiler needs to know the names of variables at compile time.
You need to use an array (or vector).

Homework: Array's for C++

Write a program to input a series of 12 integers from the keyboard and store them in a one-dimensional array, x[12], then displayed them on the computer screen in reverse order.
I have a basic understanding that:
My numbers in the array will go from {0 to 11}
I am using a for loop (which I don't currently know how to do)
Now... How do I write this program?
You would do this:
loop from 0 to 11 using a for loop (for(size_t i = 0; i < 12; i++))
for each i, std::cin into the item at index i std::cin >> array[i];
To print them out you can use a while loop with i--. It will stop when i is zero and it will be backwards.
Because this is a homework question, I won't give you the full code but I hope this answer helps.
Learn about loops: while for do, while etcetera and you just might find the solution that you have been looking for
Example:
for(i = 0; i < 10; i++){
cout << i;
}
Since you know the quantity of numbers, you could insert them into the array in reverse order:
cin >> x[11]; cin >> x[10]; cin >> x[09]; //...
Next you would display the array in normal order:
cout << x[0]; cout << x[1]; cin << x[02]; //...
Since I didn't use a for loop, that's not going to help, is it?
The key concept is the 3rd parameter of the for loop, which can control the direction of a loop.
Let us investigate some examples:
for (unsigned int i = 0; i < 10; i += 2) {cout << i << endl; }
The above loop skips items because the variable is incremented by 2. That is 2 is added to index variable. This shows that loops don't always have to use ++.
So, what would happen if the index were set to the end value and then subtracted each time?
for (int i = 10; i >= 0; i -= 2) {cout << i << endl;}
This is for you to figure out.
Now, you will need to either ask questions in class, ask the professor after class or get a book that you will read and can understand easily (in addition to the one you have).

(C++) Specific values in an array

I'm not sure how to title my question, but here goes. I am testing some features, and I have hit a snag.
What I want to know is how can I set up a "for" or "if" statement to only put values in an array that meet a criteria? For example, find every divisor for a number, but only put factors in an array.
Any help would be loved, source code can be provided if needed :). Yes, I am new, so be gentle!
#include <iostream>
using namespace std;
int main(){
int n;
int counter = 1;
cout << "What number would you like to use? ";
cin >> n;
int DiviArray[n];
for (int k=0,j=1;k<n;k++,j++)
{
DiviArray[k] = n-k;
}
int k = 3;
int factn[n];
cout << "Factors of " << n << ": " << endl;
for (int i=0, j=1;i<n;i++,j++)
{
factn[i] = n/DiviArray[i];
if(factn[i]*DiviArray[i]==n)
{
cout << counter << ". " << factn[i] << " x " << DiviArray[i] << endl;
counter++;
}
}
return 0;
}
EDIT: Decided to go with vectors, not sure if I can get it to work, but thanks for the feedback guys :)
Since you don't know in advance how many values will meet the condition, you should use a std::vector.
As a benefit, it keeps track of how many elements you've already added, so push_back will always use the next available index.
This also fixes
cin >> n;
int DiviArray[n];
which isn't legal C++.
If you only want to put the values into the array that match the condition, then you should only put a number into the array when the condition is matched. To do that, the statement that puts a number into the array has to be inside the if-block for the condition. I hope I don't need to explain why :)
This is the only time in your program where you actually do want two indices: one that is incremented every time through the loop (to count how many times to run the process), and one that is incremented only when you put a number in the array (to figure out where the next number goes). Everywhere else, you've created a completely useless j variable (the uselessness should be apparent from the fact that there is no code that actually uses the value, only code to set it).