Pointer Array outputting integer variables without issue, but strings are all empty - c++

I am a C++ novice and have an assignment using Oldie McOldSchool arrays and pointers. I have looked at this specific problem for about 8-12 cumulative hours now, kind of want to shove my face into a brick wall and don't really know what to think at this point. I am hoping from help from the experts here at SO!
I have the following class
#include <iostream>
#include <string>
using namespace std;
#include "mainclass.h"
#include "mysubobject1.h"
const string dataString[] =
{
"stringvalue,stringvalue,stringvalue,stringvalue,19,51,36,41,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,52,37,44,STUFF2",
"stringvalue,stringvalue,stringvalue,stringvalue,19,53,38,46,STUFF3",
"stringvalue,stringvalue,stringvalue,stringvalue,19,54,39,49,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,55,30,38,STUFF2",
};
MyObject* myObjectArray[5];
const string* dataArray[5];
int delimiterPositionArray[5][9];
string tokenArray[5][9];
Stuff stuff;
void main()
{
MainClass* mainClass = new MainClass();
dataArray[0] = &dataString[0];
dataArray[1] = &dataString[1];
dataArray[2] = &dataString[2];
dataArray[3] = &dataString[3];
dataArray[4] = &dataString[4];
/*Parse the contents of string into Token array. I have this working and can share if necessary but trimmed it out to keep this easy to look at */
for (int i = 0; i < 5; i++)
{
/* Logic to set the value of stuff goes here - it's very simple and trimmed for ease of reading */
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
}
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject;
myObject.SetStuff(stuff);
}
myObject.SetString1(string1);
myObject.SetString2(string2);
myObject.SetString3(string3);
myObject.SetString4(string4);
myObject.SetInt1(int1);
int* intArray[] = { &int2, &int3, &int4 };
myObject.SetIntArray(intArray);
//Awful temporary array filling logic (which doent work properly, but works for the purpose of testing this problem)
if (myObjectArray[0] == nullptr)
{
myObjectArray[0] = &myObject;
}
else
{
if (myObjectArray[1] == nullptr)
{
myObjectArray[1] = &myObject;
}
/* ….until the array is filled */ }
}
And the question:
When I inspect this line of code from the main method in the mainclass.cpp in the VB debugger, all looks perfect. Token array contains what I expect:
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
I keep stepping through the code and get through the end of the add method. I see that everything looks fine by the time I reach the end of the add method. The strings and integers all appear to get set perfectly. I inspect the following line after the debugger runs over it and see everything looks great. Each array field has the data I expect in it. (the logic sucks and the data is the same for each array index, but that is for a later troubleshooting session :D)
myObjectArray[0] = &myObject;
After the add method runs, execution is deferred back to the main method and the following code outputs the results to the screen:
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
This is where the problem is.... mainClass->myObjectArray[0] has empty values in all string properties and nothing is outputted for them (they contain "").... but the int properties have the proper output for some reason!
If anyone would have any insight into why the ints are available and the strings don't appear to be, I would be eternally grateful!
Thanks again!

Given you really didn't post all of your code, the code you did post shows one major issue, and could be the reason why your program behaves as it does.
In your MainClass::add() function, you're storing the addresses of local variables in the MainClass::myObjectArray array, and attempting to access these addresses from outside the add() function.
A synopsis of the code:
int main()
{
MainClass* mainClass = new MainClass();
//...
mainClass->add(...);
//...
cout << mainClass->myObjectArray[0] << endl; // <-- index 0 points to a garbage value
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject; // <-- Local variable
//...
int* intArray[] = { &int2, &int3, &int4 }; // <-- Another local variable
//...
myObject.SetIntArray(intArray); // <-- Storing address of local
//...
myObjectArray[0] = &myObject; // <-- Storing address of local
//...
}
When add() returns, those addresses will not be pointing to valid variables, since those variables no longer are valid since they are local variables.
So the fix is that you have to ensure that whatever pointers you place in your myObjectArray array, the lifetimes (scope) of those variables that are pointed to will last as long as myObjectArray.
A better solution to use an array of a type that stores "any" value such as an array of std::any.
In addition to this, you should attempt to reduce the unnecessary calls to new. For example, your main function starts off on the wrong foot:
int main()
{
MainClass* mainClass = new MainClass();
This could have simply been:
int main()
{
MainClass mainClass;

Related

How to access variables in a class using an array of objects?

I am new to pointers and I am having trouble in accessing the variables inside a class.
I want to make a sort of database of possible moves in a Chess game, and I think that using pointers is the way to go, since I wouldn't be wasting memory and prevent any unnecessary memory errors.
main.cpp
#include <iostream>
#include "moves.h"
using namespace std;
int main()
{
moves* possibleMoves[100];
&(possibleMoves[0]->piece) = 100;
cout << *&possibleMoves[0]->piece << endl;
return 0;
}
moves.h
#ifndef MOVES_H
#define MOVES_H
class moves
{
public:
moves();
int piece;
int X;
int Y;
int addX;
int addY;
int score;
};
#endif // MOVES_H
Any help would be appreciated. Thank you very much in advance.
Currently it doesn't output anything and I don't know what to do.
I am having trouble in accessing the variables inside a class
It looks like you are making a mess of pointers and references.
There isn't a real need in your code to use array of pointers. Instead using normal array of objects would do.
moves possibleMoves[100];
possibleMoves[0].piece = 100;
cout << possibleMoves[0].piece << endl;
Btw, class moves incorrectly exposes all data members to public - they should be private. And moves constructor needs to be implemented or otherwise should be removed to use the default one.
You are creating an array of pointers with:
moves* possibleMoves[100];
when what you want is an array of moves.
Then you are trying to assign piece in possibleMoves[0] a value of 100 with:
&(possibleMoves[0]->piece) = 100;
but you are actually doing something quite different. As #Henri Menke said best to read up on &, *, . and ->.
To make your intended code work try:
int main()
{
moves possibleMoves[100];
possibleMoves[0].piece = 100;
cout << possibleMoves[0].piece << endl;
return 0;
}
Here you create an array of moves objects, then assign the value of piece in object 0 a value of 100. You retrieve the value and print it to cout.

C++ error: unknown type name

So, here's my code:
/****************************************************************
File: Video.h
Description: class declarations
Author: David && Evan
Class: CSCI 120
Date: 2015 May 13
We hereby certify that this program is entirely our own work.
*****************************************************************/
#ifndef VIDEO_H
#define VIDEO_H
#include <iostream>
#include <string>
#include <vector>
#include "Person.h"
#include "Date.h"
using namespace std;
enum kind {MOVIE, TELEVISION, COMPUTER};
// 'MOVIE' = standalone film of any length, whether it's part of a franchise or not
// 'TELEVISION' = episode from mini- or recurring series
// 'COMPUTER' = online or locally hosted files
/* If need be, we can extend this by adding something for analog home movies,
i.e., camcorder tapes or 8mm film. */
namespace Vids
{
class Video{
public:
Video(); // default constructor
Video(string name, string audience, string location, vector<Person> directors,
vector<Person> actors, Date released);
virtual void display() = 0; // displays information for all objects of Video type
virtual void displayAll() = 0; // displays all information for one object
unsigned char getDirectorSize() const { return directorSize; }
unsigned char getActorSize() const { return actorSize; }
string getName() const { return name; }
string getAudience() const { return audience; }
string getLocation() const { return location; }
Date getReleased() const { return released; }
Date getViewed() const { return viewed; }
string Truncate(string str, size_t width) { // shortens output
if (str.length() > width)
return str.substr(0, width) + "...";
return str;
} // truncate
protected:
short runtimeMinutes;
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
// number of elements in each vector, shouldn't need more than 255
unsigned char actorSize;
string name; // title of movie
string audience; // PG = "Plenty Guns", PG-13 = "13 or more guns"
string location;
/* Location is a catch-all field for: URL, shelf disc is on, format
type, name of person it is loaned to, etc. */
vector<Person> directors(directorSize);
/* David: I considered using other containers, but none of them
offered any obvious benefits over the vector. */
vector<Person> actors(actorSize);
Date released;
Date viewed;
/* 'viewed' can be used to answer the question: "What haven't i
watched lately?" */
}; // end class Video
} // end namespace Vids
#endif
And compiling [with several other files] gives me this:
$ g++ *.cpp -o Project3
In file included from Computer.cpp:12:
In file included from ./Computer.h:15:
./Video.h:68:29: error: unknown type name 'directorSize'
vector<Person> directors(directorSize);
^
./Video.h:71:26: error: unknown type name 'actorSize'
vector<Person> actors(actorSize);
^
directorSize is declared in the same scope as directors, so why is the compiler not recognizing it?
The line
vector<Person> directors(directorSize);
is not the right syntax for declaring a member variable.
Change it to
vector<Person> directors;
Similarly, change
vector<Person> actors(actorSize);
to
vector<Person> actors;
Given that you can get the number of items in a vector by calling the size() member function, you don't need the member variables:
unsigned char directorSize;
unsigned char actorSize;
Remove them.
Well, this comment is puzzling:
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
unsigned char maxes out at 255 so if you need up to 32K then you will have to use a different type. In fact it would be better to remove this variable entirely, and retrieve the size by doing directors.size() as needed.
It is possible to initialize the vector in the class definition:
vector<Person> directors{directorSize};
However this would cause undefined behaviour if you hadn't initialized directorSize in the constructor initializer list (because you would be using an uninitialized variable directorSize).
It would be much better to change this to:
vector<Person> directors;
and presumably in your constructor initializer list, or constructor body, you will add some items into this vector.
I'll boil your problem down to a trivial case to demonstrate the problem, along with applying the "m_" member variable prefix popular among some engineers for highlighting a variable that is a "member" of something.
#include <vector>
class Class {
protected:
unsigned char m_directorSize;
std::vector<int> m_directors(m_directorSize);
};
int main()
{
Class x;
}
This does not compile http://ideone.com/VJck4Q and by isolating the problem, we learned a lot.
The line of code:
std::vector<int> m_directors(m_directorSize);
Look at the syntax of this
/typename/ /name/ ( /values/ );
The compiler thinks this is a member-function declaration, which is why it is expecting a type:
std::vector<int> something(unsigned char directorSize);
would declare a member-function called "something" that takes a parameter, directorSize, of type unsigned char. Incidentally: unsigned char is almost guaranteed to be an 8-bit value, capable of storing 0 through 255. That's a terrible choice for a size variable. There is a standard type, size_t for storing non-negative sizes and ssize_t for storing signed sizes.
It's unclear why you think you should be passing directorSize to the vector, but you can't declare a member with a function call.
If you want to shape the default behavior of an object at construction time of your class, you need to use a constructor (or use C++11/C++14, but we don't know if you're doing that):
class Foo_Sized {
std::vector<int> m_vec;
public:
Foo() : m_vec(250) // default construct 250 elements
{}
};
If you were using C++11/14:
class Foo_Sized {
std::vector<int> m_vec = std::vector<int>(250);
};
But if you want to affect one member based on the value of another, the only place you can do that is in a member function, so in this case that means the constructor.
If you're going to create a static array like that, you probably want to be using std::array instead of std::vector - the whole point of vector is that it can grow dynamically.
std::array<int, 250> m_arr;
This declares an array of integers which has a capacity of 250 and has a fixed size. It's faster than a vector but it is always 250 large. You would then have to track the "in-use" count of it and other management overhead yourself.
std::vector<int> vec;
std::cout << vec.size() << '\n'; // prints 0
vec.push(10); // add a value of 10 to the vector.
vec.push(20); // vec is now { 10, 20 }
std::cout << vec.size() << '\n'; // prints 2
vec.push(30); // vec is now { 10, 20, 30 }
std::cout << vec.size() << '\n'; // prints 3
std::cout << vec[0] << '\n'; // prints 10
std::cout << vec[3] << '\n'; // undefined behavior, there is no 3rd element
std::array<int, 3> arr;
std::cout << arr.size() << '\n'; // prints 3: fixed size.
arr[0] = 10; // can't push, fixed size.
arr[1] = 20;
std::cout << arr.size() << '\n'; // still 3, always will be.
arr[2] = 30;
std::cout << arr.size() << '\n'; // still 3, always will be.
std::cout << arr[0] << '\n'; // prints 10
std::cout << arr[3] << '\n'; // compile error: outside fixed size
If you were worrying about memory allocation, you could tell the vector to allocate memory upfront like this:
class Foo_Reserved {
std::vector<int> m_vec;
public:
Foo() : m_vec() // default construct empty
{
m_vec.reserve(250); // reserve memory for 250 elements
}
};
There are a host of other issues with your code, but they aren't directly related to your question so I'm not going to address/highlight them.
But in terms of dealing with your directorSize issues, you should consider providing an accessor that queries the vector or expose a const reference to the vector (this somewhat breaks encapsulation tho since it allows external callers to write code based on assumptions about your internal structure).
class Foo {
public:
using vec_t = std::vector<int>;
protected:
vec_t m_vec;
public:
Foo() : m_vec() // default construct empty
{
}
size_t vecSize() const { return m_vec.size(); }
// or, return a look-don't-touch reference to the vector
const vec_t& getVec() const { return m_vec; }
};
Foo f{}; // C++14 initializer
f.vecSize();
f.getVec().size();

creating a simple C++ string class

I'm writing a program where I create my own string class. The program is supposed to instruct the user to write a sentence, copy the input, and then display how many characters it contains.
Although it did build and compile (using Visual Studio Express 2013), it would copy the sentence the user is instructed to write down, not display the amount of characters, and then crash.
I'm guessing is has something to do with how the memory is dynamically allocated or how *character and _String is passed between functions. But some help on how to fix this or improve my code would be very helpful.
Header: String.h
class String
{
private:
char *characters[50]; // 50 is just a placeholder to get it to work
int size;
public:
// Constructors and Destructors
String();
String(char*);
~String();
// Other functions
void stringAssign(char*);
void printString(char*);
int stringSize(char*) const;
};
Implementation: String.ccp
#include "String.h"
#include <iostream>
#include <cstring>
String::String()
{
size = 0;
* characters = 0;
}
String::String(char* _String)
{
size = stringSize(*characters + 1);
_String = new char[size];
}
String::~String()
{
delete [] *characters;
}
void String::stringAssign(char* _String)
{
_String = characters[size];
}
void String::printString(char* _String)
{
for (int i = 0; _String[i] != '\0'; i++)
std::cout << _String[i];
}
int String::stringSize(char* _String) const
{
int size;
size = strlen(*characters);
return size;
}
Test: Main.ccp
#include "String.h"
#include <iostream>
int main()
{
char string[50];
String s;
std::cout << "Enter a sentence that is less than 50 characters\n\n";
std::cin.getline(string, 50);
s.printString(string);
std::cout << s.stringSize(string);
return 0;
}
Solved:
I got the program working. Literally all I did was replace the two *character arguments with _String in the implementation. I knew it had something to do with function passing, and I did get a little help for that. But one person gave no helpful input (and practically insulted me) and both said that there were "too many things to fix". Some elaboration on the "so many things" I had to fix would be nice.
In almost all functions, you do something with the argument of the function, _String, and not with the member field characters that is supposed to hold the string internally. So your functions do not change the string at all, but rather try to mess with something you passed them.
An example
struct Foo {
char internal[42];
void bar(char *external) { external[0] = 'X'; }
void qux(char *external) { internal[0] = 'Z'; }
};
int main() {
Foo foo;
char something[6] = "Hello";
foo.qux(something); // Did something to the member variable foo.internal; variable something is unchanged.
foo.bar(something); // Now something reads "Xello", foo.internal was not changed.
}
Your code does almost as the function bar while it should work like qux.
There is indeed too much to fix in this code.
Just in case you were mistaken... Unlike some other languages, say Python or Smalltalk, C++ passes a pointer to the current object implicitly via this.

How can I access an array stored in an object?

I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.

C++ Pointers help?

I need a little bit of help with using pointers in C++. Sorry to seem beginner but I really can't quite understand them. I have read the tutorial on pointers on the cplusplus.com website, so please don't suggest that.
I basically have a variable which holds the name of another variable, and I wish to access that variable through the holder one. I believe I need to use pointers, correct me if I'm wrong though.
E.g.
int a;
string b;
a = 10;
b = "a";
I need to access the variable "a" through the contents of variable "b".
Just to put this into better perspective, this is how I am using it:
int a;
a = 20;
void getVar(string name) {
cout << name;
}
getVar("a");
But as you can see, on the fifth line, that will just cout the value of name, in this case "a", but I want it to cout the value of the variable which name contains, so I want it to output "20".
Any help here would be much appreciated.
If you need to associate a name with a value, consider associative arrays otherwise known as dictionaries and maps. The Standard Template Library has std::map that you can use to associate text with a value:
#include <map>
#include <string>
std::map<std::string, int> my_map;
my_map["A"] = 20;
cout << my_map["A"] << endl;
What you are thinking of is called (Reflection) which C++ does not support. You can however use pointers to access what is in a variable it points to:
int a = 5; //int variable that stores 5
int *b = &a; //int pointer that stores address of a
(*b) = 10; //stores 10 into address that b points to (a)
cout << a; //prints 10
What you are trying to achieve is not possible in a compiled language (not considering reflection). You might accomplish something similar using a map data structure.
theMap["a"] = 20;
and a corresponding
void getVar(string key){
cout << theMap[key];
}
that can be called with
getVar("a");
Note that in this extremely simple sample theMap has to be in scope for the function, like in a class or a namespace.
If you use pointers you are just using a level of indirection not at all suited for your example. See Chads answer for instance.
Theres no real way for you to access variables by name like that unless you create some kind of container class that has a name member that you look up by. I'm not sure what this has to do with pointers though.
What you're asking for is called "reflection" or "introspection" - the ability to use design-time names for your program's objects (classes, variables, functions, etc) in run time. C++ does not support that out of the box - the design-time names are stripped upon compilation.
There are some libraries that provide that capability in C++; but there are also languages where reflection is is part of the language. Python or JavaScript, for example.
Maybe this could suit you:
int a = 5;
class b {
public:
b(int &x) { ref_ = x; }
int operator()(void) { return ref_; }
private:
int &ref_;
}
b my_b(a);
my_b() /* -> 5 */;
Your code does not use pointers. you're trying to convert a string into an identifier and print it's result, I don't know whether that's possible or not. If you intended using pointer your code should've looked like this:
int a = 20;
int* b = &a;
cout << *b;
quick fix for outputting integers only:
int a;
a = 20;
void getVar(int name) {
cout << name;
}
getVar(a);
If you need the function to work for any type of variable, maybe think about some template function.
Edit: Here is the code for the template program:
#include <iostream>
#include <string>
using namespace std;
template <class T>
void getVar(T name){
cout<<name<<endl;
}
int main()
{
string x="hee";
int y=10;
getVar(x);//outputs hee
getVar(y);//outputs 10
return 0;
}