access private member variable through private member, same class - c++

// M9P369.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
const int MaxSize = 100;
using namespace std;
class Set {
int len; // number of members
char members[MaxSize]; // the set is stored in this array
int find(char ch); // find an element
public:
Set() { len = 0; } // constructor to make a null set initially
int getLength() { return len; } // return number of elements in the set
void showset(); // display the set
bool isMember(char ch); // check for membership
Set operator+(char ch); // overload operator to add an element to the set
Set operator-(char ch); // overload operator to remove an element from the set
Set operator+(Set ob2); // set Union - overloaded by the different type from above overload+ function
Set operator-(Set ob2); // set difference same as above.
};
// Return the index of the element passed in, or -1 if nothing found.
int Set::find(char ch) {
int i;
for (i=0; i < len; i++)
if (members.[i] == ch) return i;
return -1;
}
// Show the set
void Set::showset() {
cout << "{ ";
for (int i=0; i<len; i++)
cout << members[i] << " ";
cout << "}\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
I am learning operator overloading, and came across a class access problem.
The line
if (members.[i] == ch) return i;
Gives a tooltip error 'expression must have class type', and compile errors:
\m9p369.cpp(34): error C2059: syntax error : '['
\m9p369.cpp(40): error C2228: left of '.showset' must have class/struct/union
\m9p369.cpp(41): error C2228: left of '.cout' must have class/struct/union
I am defining the private member function find() of class Set, and I get the error upon trying to access the private member char array of the same class, members. Error seems to say I should specify which class it's referring to, why? I already specify the class in the definition:
int Set::find(char ch) {
As I understand, members should be in the scope of the function definition. I looked hard for any stray characters I couldn't find anything odd, all parenthesis seem to match.

Problem is here:
members.[i]
It should be just
members[i]

Remeove the . from
if (members.[i] == ch) return i;
~~~~~~~~~~~^

Related

Using a 2D array for a game map in C++

Software: Visual Studio 2017 Community
Hi, everybody,
I am making a simple 2d console game in C++ (perhaps very simplified Dwarf Fortress if you know it).
And I want a map to be displayed in console with ASCII.
Something like this:
I have a WorldMap class declared in the header file(simplified version).
And I declare a 2d array inside it.
#pragma once
#include <iostream>
class WorldMap
{
public:
WorldMap();
virtual ~WorldMap();
private:
int worldWidth;
int worldHeight;
char worldMap; // Declare a variable that will hold all the characters for the map
};
And then define it in the .cpp file:
#include "WorldMap.h"
#include <algorithm>
WorldMap::WorldMap()
{
worldWidth = 50;
worldHeight = 50;
worldMap[50][50]; // Define the map array
// And then here I will also somehow need to be able to fill the whole map with '.' symbols, and so on
}
So that is the basic idea of what I am trying to achieve. The reason why I can't define the array size immediately is because I want to be able to choose the size of the map when the map is created.
I have already tried:
The code above.
Error:
error C2109: subscript requires array or pointer type
Declaring 2d array as char worldMap[][]; and then defining it as worldMap[50][50]; .
Error:
error C2087: 'worldMap': missing subscript
warning C4200: nonstandard extension used: zero-sized array in struct/union
message : This member will be ignored by a defaulted constructor or copy/move assignment operator
Declaring 2d array as char worldMap[worldWidth][worldHeight];, expecting that when the object is created, the width and height variables will be defined first, and then they will define the array.
Error:
error C2327: 'WorldMap::worldWidth': is not a type name, static, or enumerator
error C2065: 'worldWidth': undeclared identifier
error C2327: 'WorldMap::worldHeight': is not a type name, static, or enumerator
error C2065: 'worldHeight': undeclared identifier
Using char* worldMap; and char** worldMap, but so far I can't even understand how double pointer works, yet char* worldMap actually works with a 1D array without errors, until I start accessing values of the elements in the array.
I suppose a workaround would be to use a string or 1D char array and when displaying it just use mapWidth to end line each 50 characters for example, which will give the same result. But I feel like that's not a good way to achieve this since I will need to access x and y coords of this map and so on.
I guess what I am asking is:
What's the best way of declaring a 2d array for a class and then defining it in the object?
What's the best way to store a map for such a console game? (Not necessarily using arrays)
Thank you for reading. I will really appreciate any help, even just ideas and tips might push me in the right direction :)
What's the best way of declaring a 2d array for a class and then defining it in the object?
What's the best way to store a map for such a console game? (Not necessarily using arrays)
This is not "the best way" but it's one way of doing it.
Create a class wrapping a 1D std::vector<char>.
Add operator()s to access the individual elements.
Add misc. other support functions to the class, like save() and restore().
I've used your class as a base and tried to document what it's doing in the code: If some of the functions I've used are unfamiliar, I recommend looking them up at https://en.cppreference.com/ which is an excellent wiki that often has examples of how to use the particular function you read about.
#include <algorithm> // std::copy, std::copy_n
#include <filesystem> // std::filesystem::path
#include <fstream> // std::ifstream, std::ofstream
#include <iostream> // std::cin, std::cout
#include <iterator> // std::ostreambuf_iterator, std::istreambuf_iterator
#include <vector> // std::vector
class WorldMap {
public:
WorldMap(unsigned h = 5, unsigned w = 5) : // colon starts the initializer list
worldHeight(h), // initialize worldHeight with the value in h
worldWidth(w), // initialize worldWidth with the value in w
worldMap(h * w, '.') // initialize the vector, size h*w and filled with dots.
{}
// Don't make the destructor virtual unless you use polymorphism
// In fact, you should probably not create a user-defined destructor at all for this.
//virtual ~WorldMap(); // removed
unsigned getHeight() const { return worldHeight; }
unsigned getWidth() const { return worldWidth; }
// Define operators to give both const and non-const access to the
// positions in the map.
char operator()(unsigned y, unsigned x) const { return worldMap[y*worldWidth + x]; }
char& operator()(unsigned y, unsigned x) { return worldMap[y*worldWidth + x]; }
// A function to print the map on screen - or to some other ostream if that's needed
void print(std::ostream& os = std::cout) const {
for(unsigned y = 0; y < getHeight(); ++y) {
for(unsigned x = 0; x < getWidth(); ++x)
os << (*this)(y, x); // dereference "this" to call the const operator()
os << '\n';
}
os << '\n';
}
// functions to save and restore the map
std::ostream& save(std::ostream& os) const {
os << worldHeight << '\n' << worldWidth << '\n'; // save the dimensions
// copy the map out to the stream
std::copy(worldMap.begin(), worldMap.end(),
std::ostreambuf_iterator<char>(os));
return os;
}
std::istream& restore(std::istream& is) {
is >> worldHeight >> worldWidth; // read the dimensions
is.ignore(2, '\n'); // ignore the newline
worldMap.clear(); // empty the map
worldMap.reserve(worldHeight * worldWidth); // reserve space for the new map
// copy the map from the stream
std::copy_n(std::istreambuf_iterator<char>(is),
worldHeight * worldWidth, std::back_inserter(worldMap));
return is;
}
// functions to save/restore using a filename
bool save(const std::filesystem::path& filename) const {
if(std::ofstream ofs(filename); ofs) {
return static_cast<bool>(save(ofs)); // true if it suceeded
}
return false;
}
bool restore(const std::filesystem::path& filename) {
if(std::ifstream ifs(filename); ifs) {
return static_cast<bool>(restore(ifs)); // true if it succeeded
}
return false;
}
private:
unsigned worldHeight;
unsigned worldWidth;
// Declare a variable that will hold all the characters for the map
std::vector<char> worldMap;
};
Demo
There is no best way to do anything*. It's what works best for you.
From what I understand you want to make a dynamic 2D arrays to hold your char of world map. You have a lot of options to do this. You can have a worldMap class nothing wrong with that. If you want dynamic 2D arrays just make functions out of this kind of logic.
#include <iostream>
#include <vector>
int main() {
int H = 10, W = 20;
char** map = NULL; //This would go in your class.H
//Make a function to allocate 2D array
map = new char* [H];
for (int i = 0; i < H; i++) {
map[i] = new char[W];
}
//FILL WITH WHATEVER
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
map[i][j] = 'A';
}
}
//do what ever you want like normal 2d array
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
std::cout << map[i][j] << " ";
}
std::cout << std::endl;
}
//Should always delete when or if you want to make a new one run time
for (int i = 0; i < H; i++)
delete[] map[i];
delete[] map;
map = NULL;
//Also you can use vectors
std::cout << "\n\n With vector " << std::endl;
std::vector<std::vector<char>> mapV;
//FILL WITH WHATEVER
for (int i = 0; i < H; i++) {
std::vector<char> inner;
for (int j = 0; j < W; j++) {
inner.push_back('V');
}
mapV.push_back(inner);
}
//do what ever you want kind of like a normal array
//but you should look up how they really work
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
std::cout << mapV[i][j] << " ";
}
std::cout << std::endl;
}
mapV.clear();
return 0;
}

Uninitialised local variable from class

When I'm trying to access classes public variable (in this case trying to input text row) it shows that it's uninitialized. However, I declared it in class as a public variable.
I know that's some dummy mistake, but can't find it :D
#include <iostream>
#include <conio.h>
using namespace std;
class stringlength {
private:
int lengt;
public:
char * row;
int len()
{
for (int i = 0, lengt = 0; (*(row + i) != '\0'); i++, lengt++) {}
return lengt;
}
};
int main()
{
stringlength test;
cout << "Enter a string:";
cin >> test.row;
cout << "Length is: " << test.len();
_getch();
}
This program is expected to give a length of the inputted row (like strlen function)
Error is:
Error C4700 uninitialized local variable 'test' used
Thanks for help ;)
Declaring the variable does not mean that it's initialized.
Initialize it in a constructor, or just char * row = nullptr; (if 0 is the intended initialization).
Same for all the variables that you have which have no constructors.
Edit: in this specific case you need to initialize to a new pointer char * row = new char[...]

Error in program with structures and pointers (Structures, C++)

I have a structure , which contains three variables under the object list.-Names, registration nos, amount.
struct vendor
{
int reg, amt;
char add[30];
}list[10];
I have made a function to find the minimum amount(amt) ,using the referencing concept.
int low(vendor *p, int n)
{
int i;
min = (p->amt);
for(i =1;i<n;i++)
{
if(min > *(p->amt))
{
min = *(p->amt);
}
p++;
}
return min;
}
In the main I have included the syntax:
low(list, n);
I am getting an error:
Invalid argument of unary '*' operator.
I have tried using the dot operator also and is not working.
This is my first program in pointers in structs with functions.
Can you please point out the error in the code.
Thank You very much
Anupam
(Update) the full code:
#include <iostream>
using namespace std;
struct vendor
{
int reg, amt;
char add[30];
}list[10];
int low(vendor *p, int n)
{
int i;
min = (p->amt);
for(i =1;i<n;i++)
{
if(min > (p->amt))
{
min = (p->amt);
}
p++;
}
return min;
}
int main()
{
int i;
int fa;
int n,fr;
cin >> n;
for(i =0;i<n;i++)
{
cin >>list[i].reg>>list[i].add>>list[i].amt;
// Enter reg no. , address and amount.
}
low(list, n); // Calling function
for(i = 0;i<n;i++)
{
if(fr == list[i].amt)
// This is to check for position of least amount.
// For printing the reg no. and address of least amt.
{
fa = i;
}
}
cout << fr <<"\n" << fa <<endl;
// print the reg no. and address of least amt.
}
Errors:
Overloaded function with no contextual type information.
Invalid operands of types <unresolved overloaded function
Cannot resolve overloaded function
The declaration for min is missing in low() function.
int min = (p->amt);
This should help you compile your code.
p is a pointer to a vendor. *p is a vender. p->amt is an int.
So when you want the amt of an object that is pointed to by p you can do it in one of two ways: p->amt or (*p).amt
You fix your code by using p->amt or (*p).amt. *p->amt or *(p->amt) are invalid.
p is a object of vendor which type is pointer . "->" is used to use pointer object . So use p->amt .
you can also use (*p).amt .
Updated Answer :
decleration of min is missing . please use this :
int min = p->amt ;
or use this :
int min = (*p).amt;

list as member in a class

I am having some trouble! My goal is to check an input number against a list of prime numbers to see if it is prime (in the list) via the find() function. I haven't gotten that far yet. This is homework so I have to overload the function operator and do it in this dumb (imho) way. Here is what I have thus far:
using namespace std;
class isprime {
public: isprime() { /*nothing...yet?*/
}
bool operator()(int);
list <int> pnums(1, 2);
private: int expandList(int number);
};
bool isprime::operator()(int number) {
if (pnums.back() < number) {}
}
int isprime::expandList(int number) {
for (int j = pnums.back(); j = number; j++) {
for (int i = 2; i < sqrt(j); i++) {
if (j % i != 0) pnums.push_back(j);
}
}
}
int main() {
isprime pcheck;
int number;
while (cin >> number) {
if (pcheck(number)) cout << number << " is prime!\n";
}
}
Here are my errors:
prime2.cpp:12: error: expected identifier before numeric constant
prime2.cpp:12: error: expected ',' or '...' before numeric
constant prime2.cpp: In member function 'bool
isprime::operator()(int)': prime2.cpp:19: error:
'((isprime*)this)->isprime::pnums' does not have class type
prime2.cpp: In member function 'int isprime::expandList(int)':
prime2.cpp:23: error: '((isprime*)this)->isprime::pnums' does not have
class type prime2.cpp:25: error:
'((isprime*)this)->isprime::pnums' does not have class type
I don't understand what is going wrong. Could anyone help me out?
The biggest problem is how you are trying use the constructor for the list in your class. If you simply remove (1, 2) from the list declaration in your class, it should compile. Second, if you want to call the constructor of an object in your class, I recommend this method
class isprime{
public:
isprime() : pnums(1,2) { /*nothing...yet?*/ }
...
list <int> pnums;
...

Trying to make my own string class

These are the errors I'm getting for my program.
myString1.cpp: In constructor ‘MyString1::MyString1(char*, int)’:
myString1.cpp:6: error: expected primary-expression before ‘]’ token
myString1.cpp:6: error: expected primary-expression before ‘]’ token
myString1.cpp: In member function ‘MyString1 MyString1::append(MyString1)’:
myString1.cpp:11: error: invalid use of member (did you forget the ‘&’ ?)
myString1.cpp: In member function ‘void MyString1::clear()’:
myString1.cpp:25: error: expected primary-expression before ‘]’ token
myString1.cpp:25: error: expected primary-expression before ‘{’ token
myString1.cpp:25: error: expected `;' before ‘{’ token
myString1.cpp: In member function ‘bool MyString1::empty()’:
myString1.cpp:29: error: expected primary-expression before ‘]’ token
myString1.cpp:31: error: expected primary-expression before ‘else’
myString1.cpp:31: error: expected `;' before ‘else’
And here is my program in the three different parts.
myString1.h
#ifndef MYSTRING1_H
#define MYSTRING1_H
class MyString1
{
private:
char chars[];
int size;
public:
MyString1();
MyString1(char chars[], int size);
MyString1 append(MyString1 s);
char at(int index);
int length();
void clear();
bool empty();
int find(char ch);
};
#endif
myString1.cpp
#include "myString1.h"
using namespace std;
MyString1::MyString1(char chars[], int size)
{
this->chars[] = chars[];
this->size = size;
}
MyString1 MyString1::append(MyString1 s)
{
for(int i = size; i > size - s.length; i++)
chars[i] = s.at(i);
}
char MyString1::at(int index)
{
return chars[index];
}
int MyString1::length()
{
return size;
}
void MyString1::clear()
{
size = 0;
chars[] = {};
}
bool MyString1::empty()
{
if(chars[]){
return true;
else
return false;
}
}
int MyString1::find(char ch)
{
for(int i = 0; i < size; i++)
if(chars[i] = ch)
return i;
}
testMyString1.cpp
#include <iostream>
#include "myString1.h"
using namespace std;
int main()
{
MyString1 first("cat", 4);
MyString1 second("dog", 4);
cout << first.at(1) << " and " << second.at(1) << endl;
first.append(second);
cout << first.at(6) << endl;
return 0;
}
Im a newbie just trying to learn how to use the g++ compiler so just looking for some help reading the error messages and debugging my code. Also I'm sure there is some very bad code so any help is appreciated.
The code has a lot of mistakes so I don't know where to start from but I suppose that generally giving you some pointers to help you with understanding your code would be okay.
In my opinion you don't need to have a size index in a String class since there is the strlen() function that will gladly compute it for you.
Now for your class declaration check how you declare the pointer that will hold the string for you. You need to do it like below:
class MyString1
{
private:
char* chars;//this declares a pointer to a char that will hold the string for you
public:
...
Also you are never allocating the char* that holds the strings. Your constructor should be:
MyString1::MyString1(const char* chars)
{
this->chars = (char*) malloc(strlen(chars)+1); //this will allocate an array of strlen() chars +1
strcpy(this->chars,chars);
}
As you can see I am not using a size index since strlen can quite efficiently find that out for you. +1 is for the '\0' that signifies the end of a string.
Now to append something to the string, that's gonna be tricky.
void MyString1::append(const MyString1& s) //it's good to give a constant reference to the string here
{
//first of all we gotta reallocate the pointer,since we don't have enough memory for the string
int newsize = strlen(this->chars) + strlen(s)+1;
this->chars = (char*) realloc(this->chars,newSize); \\ no check for realloc failure, I know but this is just an example
strcat(this->chars,s.chars);
}
You don't need to return anything when you append. You are doing something to THIS string.
Your ::at() function is almost okay. Imagine though what would happen if the size of the string was 10 and you request MyString1::at(12). This would probably cause a Segmentation fault (that's not good).
So you should alter your code to do bounds checking like below:
char MyString1::at(int index)
{
//if it's out of bounds let's return -1 which will signify that we got an out of bounds value (could also throw an exception here but that's a different subject altogether)
if(index > strlen(this->chars) || index <0)
return -1;
return chars[index];
}
Also in C/C++ you have to free the memory that you allocate. So in order to do that you should declare something called a destructor
MyString1::~MyString1()
{
free(this->chars);
}
Finally the is empty function can just be like that:
bool MyString1::empty()
{
return (this->chars[0] == '\0';
}