Looping through array inside of stuct - c++

I'm a student, learning pointers for the first time. My assignment doesn't allow the use of string classes and should be using pointer notation to access all elements within an array (no []).
Why am I not able to access an array inside of a struct via pointers? Is my syntax off?
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here
void sayNumsPointerNotation(person peep)
{
for (int i = 0; i < 4; i++)
{
//cout << peep.*(favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(peep);
cout << endl;
}

This should work, hopefully you understand what was wrong.
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here (now it works)
void sayNumsPointerNotation(person* peep)
{
for (int i = 0; i < 4; i++)
{
cout << *(peep->favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(&peep);
cout << endl;
}

Instead of
cout << peep.*(favNums + i) << endl;
Try this:
cout << *(peep.favNums + i) << endl;

Use
cout << *(peep.favNums + i) << endl;
.*, on the other hand, is a "member pointer", and means something different.

Related

C++ linker undefined reference to function cannot find my error

It is a homework problem. It compiles fine, but linker gives undefined reference to my function getSalesData - line 20 just after my first for loop. Here is the code. I cannot find where I have done anything incorrectly; I have my prototype defined and it matches my function header, and I am simply calling the function.
// chips and salsa
#include <iostream>
#include <iomanip>
#include <string>
int getJarsSold(std::string type);
void getSalesData(int jarsSold[],int size,int &totalJars,int &highSeller,int &lowSeller);
int main() {
const int SIZE = 5;
const std::string salsaTypes[] {"Mild","Medium","Sweet","Hot","Zesty"};
int jarsSold[SIZE] = {};
int highIndex,lowIndex,totalJarsSold;
for (int i = 0; i < SIZE; i++) {
jarsSold[i] = getJarsSold(salsaTypes[i]);
}
getSalesData(jarsSold,SIZE,totalJarsSold,highIndex,lowIndex);
std::cout << " Type Jars Sold\n";
std::cout << "---------------------\n";
for (int i = 0; i < SIZE; i++) {
std::cout << std::setw(8) << salsaTypes[i] << std::setw(15) << jarsSold[i] << std::endl;
}
std::cout << "*********************\n";
std::cout << "Total Sales = " << totalJarsSold << std::endl;
std::cout << "Highest Seller = " << salsaTypes[highIndex] << std::endl;
std::cout << "Lowest Seller = " << salsaTypes[lowIndex] << std::endl;
}
int getJarsSold(std::string type) {
bool validData = false;
int numJars;
while (!validData) {
std::cout << "Enter jars sold this month for " << type << " salsa type: ";
std::cin >> numJars;
if (numJars < 0) {
std::cout << "Number of jars sold must be 0 or positive number.\n";
}
else {
validData = true;
}
}
validData = false;
return numJars;
}
void getSalesData(int jarsSold[],int size,int totalJars,int highIndex,int lowIndex) {
bool firstRun = true;
int highVal,lowVal;
totalJars = 0;
for (int i = 0; i < size; i++) {
if (firstRun) {
highIndex = i;
highVal = jarsSold[highIndex];
lowIndex = i;
lowVal = jarsSold[lowIndex];
totalJars += jarsSold[i];
firstRun = false;
}
else {
totalJars += jarsSold[i];
if (jarsSold[i] > highVal) {
highVal = jarsSold[i];
highIndex = i;
}
if (jarsSold[i] < lowVal) {
lowVal = jarsSold[i];
lowIndex = i;
}
}
}
}
Any help is appreciated. I am just using -c for compiling and -o for linking, nothing fancy as I know no better.

Why only the first element of the array is initialized to -1? while rest of them are 0 [duplicate]

This question already has answers here:
Initialization of all elements of an array to one default value in C++?
(12 answers)
Closed 4 years ago.
I've initialized arr to -1 when I print them every element is initialized to 0 except the first element.
This is the small code of a bigger problem. I'm just struck here
#include <bits/stdc++.h>
using namespace std;
int fibo()
{
int static arr[100] = {-1};
for (int i = 0; i < 100; ++i)
{
cout << "arr[" << i <<"] : " << arr[i] << endl;
}
return -2;
}
int main(void)
{
cout << "Result : " << fibo() << endl;
return 0;
}
Simplest solution -- use std::vector<int>, and the initialization of all elements becomes available to you in a very easy form (I know there are template tricks that can be done, but IMO there is no need for that level of complexity for this in your code).
Example:
#include <vector>
#include <iostream>
int fibo()
{
static std::vector<int> arr(100,-1);
for (int i = 0; i < 100; ++i)
{
std::cout << "arr[" << i <<"] : " << arr[i] << "\n";
}
return -2;
}
int main(void)
{
std::cout << "Result : " << fibo() << "\n";
return 0;
}
Live Example
#include <bits/stdc++.h>
using namespace std;
int fibo()
{
int static arr[100];
for (int i = 0; i < 100; ++i)
{
arr[i] = -1;
}
for (int i = 0; i < 100; ++i)
{
cout << "arr[" << i <<"] : " << arr[i] << endl;
}
return -2;
}
int main(void)
{
cout << "Result : " << fibo() << endl;
return 0;
}
Try using this code

'auto' declaration issue in C++

I have a problem in using auto declarations. I write a program in Visual Studio 2017 as follow:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
class MyClass
{
public:
struct mystruct {
vector<int> vi;
};
vector<mystruct> TheStructV;
void AddStructV() {
TheStructV.push_back(mystruct());
};
};
int main()
{
MyClass MyObj[3];
for (int a = 0; a < 3; a++) {
MyObj[a].AddStructV();
for (int i = 1; i <= 5; i++) {
MyObj[a].TheStructV[MyObj[a].TheStructV.size() - 1].vi.push_back(i * 10 + idx);
}
idx++;
}
for (int b = 0; b<3; b++) {
cout << "MyObj[" << b << "] struct vector size:" << MyObj[b].TheStructV.size() << endl;
cout << "MyObj[" << b << "] struct vi size:" << MyObj[b].TheStructV[0].vi.size() << endl;
}
for (int i = 0; i < 3; i++) {
cout << "MyObj[" << i << "].vi:";
for (int j = 0; j < 5; j++) {
cout << MyObj[i].TheStructV[0].vi[j] << "-";
}
cout << endl;
}
return 0;
}
It works as expected, and the output is:
MyObj[0] struct vector size:1
MyObj[0] struct vi size:5
MyObj[1] struct vector size:1
MyObj[1] struct vi size:5
MyObj[2] struct vector size:1
MyObj[2] struct vi size:5
MyObj[0].vi:11-21-31-41-51-
MyObj[1].vi:12-22-32-42-52-
MyObj[2].vi:13-23-33-43-53-
However, if I change the code to this:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
class MyClass
{
public:
struct mystruct {
vector<int> vi;
};
vector<mystruct> TheStructV;
void AddStructV() {
TheStructV.push_back(mystruct());
};
};
int main()
{
MyClass MyObj[3];
int idx = 1;
for (auto M : MyObj) {
M.AddStructV();
for (int i = 1; i <= 5; i++) {
M.TheStructV[M.TheStructV.size() - 1].vi.push_back(i * 10 + idx);
}
idx++;
}
for (int b = 0; b<3; b++) {
cout << "MyObj[" << b << "] struct vector size:" << MyObj[b].TheStructV.size() << endl;
cout << "MyObj[" << b << "] struct vi size:" << MyObj[b].TheStructV[0].vi.size() << endl;
}
idx = 1;
for (auto MC : MyObj) {
cout << "MyObj[" << idx - 1 << "].vi:";
for (auto thisStruct : MC.TheStructV) {
cout << thisStruct.vi[0] << "-";
cout << thisStruct.vi[1] << "-";
cout << thisStruct.vi[2] << "-";
cout << thisStruct.vi[3] << "-";
cout << thisStruct.vi[4] << "-";
}
cout << endl;
idx++;
}
return 0;
}
It compiles without problem, but I get an error when I run it, and the output is:
MyObj[0] struct vector size:0
The program is stuck here.
It seems that I am missing something. I even tried replacing auto M with MyClass M, but still the same problem.
This line will make a copy of your object
for (auto M : MyObj)
change it to a reference so you can modify it
for (auto& M : MyObj)

Set array dimension at runtime

I have a struct, which, depending on user inputs at runtime, will either require a 1D array or a 3D array. It will never need both. Right now, I have it set up like in the sample code below, with separate variables that can point to either a 1D array, or a 3D array. I would like to have just one variable in the struct that can point to either a 1D array or a 3D array, where the dimension is set at runtime. I have intermediate knowledge of C, and am a beginner with C++. I'd be willing to accept an answer based on C++ concepts but only if there is no slowdown (or negligible slowdown) compared to using C when iterating over the values. If it's a 3D array, then the for loops that access and change the array's values are the biggest bottleneck in my code. Once the array is set up, I won't need to change the dimension or size of the array.
Is there a way to do this, or should I just settle for always having an extraneous variable in my struct?
#include <iostream>
using namespace std;
typedef struct {
int dim;
int *one_d_arr;
int ***three_d_arr;
} Struct;
int main() {
int count = 0;
int *arr1 = (int*) malloc(2 * sizeof(int));
arr1[0] = 0;
arr1[1] = 1;
int ***arr3 = (int***) malloc(2 * sizeof(int**));
for (int i=0; i<2; i++) {
arr3[i] = (int**) malloc(2 * sizeof(int*));
for (int j=0; j<2; j++) {
arr3[i][j] = (int*) malloc(2 * sizeof(int));
for (int k=0; k<2; k++) {
arr3[i][j][k] = count++;
}
}
}
Struct s;
s.one_d_arr = NULL;
s.three_d_arr = NULL;
cout << "Enter number of dimensions: ";
cin >> s.dim;
if (s.dim==1) {
s.one_d_arr = arr1;
cout << s.one_d_arr[0] << ", " << s.one_d_arr[1] << endl;
}
else if (s.dim==3) {
s.three_d_arr = arr3;
cout << s.three_d_arr[0][0][0] << ", " << s.three_d_arr[0][0][1] << endl;
cout << s.three_d_arr[0][1][0] << ", " << s.three_d_arr[0][1][1] << endl;
cout << s.three_d_arr[1][0][0] << ", " << s.three_d_arr[1][0][1] << endl;
cout << s.three_d_arr[1][1][0] << ", " << s.three_d_arr[1][1][1] << endl;
}
else {
cout << "Must enter 1 or 3" << endl;
}
}
My recommendation is to use two different types here, instead of a single struct. Using an abstract base class, you can make both subclasses conform to a single interface, but they would have different underlying behavior. A very basic example:
class ArrayBase {
int dim;
public:
// This function is pure virtual, which means it's impossible to
// instantiate an instance of ArrayBase. Any class that inherits from
// ArrayBase must implement printArray().
virtual void printArray() = 0;
}
class Array1D : public ArrayBase {
int* array;
void printArray() {
// some code to print this one-dimensional array
}
}
class Array3D : public ArrayBase {
int*** array;
void printArray() {
// some code to print this three-dimensional array
}
}
Later, when you need to use the array, you can dynamically allocate the type you need, like this:
ArrayBase* inputArray;
// if the user wants a 1D array
inputArray = new Array1D();
// if the user wants a 3D array
inputArray = new Array3D();
// this will call the appropriate function to print the array
inputArray->printArray();
If you really want to have a single type, using boost::any is one way to condense your two array pointers into one. I would not recommend this approach, but it would work.
One of the juicy things about the C/C++ pointers is the existence of void pointers. A void pointer can point to anything you want, from int to int ***.
So you can simply use the following code:
#define CAST1(arr) ((int *)arr)
#define CAST3(arr) ((int ***)arr)
#define CAST(arr,i) CAST##i(arr)
typedef struct {
int dim;
void *arr;
} Struct;
int main()
{
Struct s;
cin >> s.dim;
int count = 0;
if (s.dim == 1){
s.arr = malloc(2 * sizeof(int));
CAST(s.arr, 1)[0] = 0;
CAST(s.arr, 1)[1] = 1;
}
else if (s.dim == 3){
s.arr = malloc(2 * sizeof(int ***));
for (int i = 0; i < 2; i++){
CAST(s.arr, 3)[i] = (int **) malloc(2 * sizeof(int **));
for (int j = 0; j < 2; j++){
CAST(s.arr, 3)[i][j] = (int *)malloc(2 * sizeof(int *));
for (int k = 0; k < 2; k++){
CAST(s.arr, 3)[i][j][k] = count++;
}
}
}
}
if (s.dim == 1) {
cout << CAST(s.arr, 1)[0] << ", " << CAST(s.arr, 1)[1] << endl;
}
else if (s.dim == 3) {
cout << CAST(s.arr, 3)[0][0][0] << ", " << CAST(s.arr, 3)[0][0][1] << endl;
cout << CAST(s.arr, 3)[0][1][0] << ", " << CAST(s.arr, 3)[0][1][1] << endl;
cout << CAST(s.arr, 3)[1][0][0] << ", " << CAST(s.arr, 3)[1][0][1] << endl;
cout << CAST(s.arr, 3)[1][1][0] << ", " << CAST(s.arr, 3)[1][1][1] << endl;
}
else {
cout << "Must enter 1 or 3" << endl;
}
system("pause");
return 0;
}

C++ Hamming Function

This program is supposed to create three arrays of class object My_array. The first array is filled with random numbers. The second array is an exact copy of the first. The third array is entered by the user. The program checks to make sure that the first two arrays indeed equal each other and then it check to the hamming distance of the first and third array. The professor defines the hamming distance as each part off the array that is different.
My problem has been getting hamming to work. I actually have a hard time with operating overloading so I am surprised that works (well I have no errors showing in VS Studio) but not the hamming part. Any help would be appreciated. There are three files in order: main.cpp, my_array.cpp, and my_array.h. Function definitions and declarations were provided by professor. I am required to insert how each function operates.
#include "my_array.h"
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "How big of an array shall we work with? ";
cin >> size;
My_array a(size);
My_array b(size);
My_array c(size);
a.randomize(100);
b = a;
c.input();
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << "a != b: " << (a != b) << endl;
cout << "a == b: " << (a == b) << endl;
cout << "The hamming distance is: " << a.hamming(c);
return 0;
}
#include "my_array.h"
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <time.h>
// Constructor
My_array::My_array(int the_size)
{
array = NULL;
size = 0;
resize(the_size);
}
// Destructor.
My_array::~My_array()
{
empty();
}
// Copy constructor
My_array::My_array(My_array &data)
: size(data.size)
{
array = new int[size];
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
// Overloaded assignment operator.
My_array &My_array::operator=(My_array &data)
{
if (this != &data) {
resize(data.size);
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
else
cout << "Attempt to copy an object on itself. "
<< "Operation ignored." << endl;
return *this;
}
void My_array::input()
{
int j;
cout << "Please enter " << size << " numbers.\n";
for (int i = 0; i < size; i++)
{
cout << "Number " << i + 1 << ": ";
cin >> j;
array[i] = j;
}
}
void My_array::randomize(int limit)
{
srand(time(NULL));
for (int i = 0; i < size; i++)
array[i] = rand() % limit + 1;
}
bool My_array::operator ==(My_array &data)
{
if(this->size != data.size)
return false;
for (int i = 0; i <size; i++)
{
if (*this[i].array != data.array[i])
return false;
}
return true;
}
bool My_array::operator !=(My_array &data)
{
if (*this == data)
return false;
return true;
}
int My_array::hamming(My_array &data)
{
int ham = 0;
for (int i = 0; i < size; i++)
if (*this[i].array != data[i].array)
ham++;
return ham;
}
// This function will empty the target object
void My_array::empty()
{
if (size != 0 && array != NULL) {
size = 0;
delete[] array;
}
}
// Resize the array.
void My_array::resize(int the_size)
{
if (size >= 0) {
empty();
if (the_size != 0) {
size = the_size;
array = new int[size];
}
}
else
cout << "Resize attepmted with a negative size. "
<< "Operation ignored." << endl;
}
// Access an element of the array.
int &My_array::operator[](int index)
{
if (index < size)
return array[index];
else {
cerr << "Illegal access to an element of the array." << endl
<< "The size of the array was " << size
<< " and the index was " << index << endl;
exit(1);
}
}
// Accessor
int My_array::get_size()
{
return size;
}
void My_array::output()
{
cout << "The array of size " << size
<< " contains the elements:" << endl;
for (int i = 0; i<size; i++)
cout << array[i] << ' ';
cout << endl;
}
//overloading the << operator.
ostream &operator<<(ostream &out, My_array &data)
{
out << "The array of size " << data.size
<< " contains the elements:" << endl;
for (int i = 0; i<data.size; i++)
out << data.array[i] << ' ';
out << endl;
return out;
}
#ifndef MY_ARRAY_H
#define MY_ARRAY_H
#include <iostream>
using namespace std;
class My_array {
protected:
int size;
int *array;
public:
// Constructor
My_array(int the_size = 0);
// Destructor
~My_array();
// Copy constructor
My_array(My_array &data);
// Assignment operator
My_array &operator=(My_array &data);
void input();
void randomize(int limit);
bool operator ==(My_array &data);
bool operator !=(My_array &data);
int hamming(My_array &data);
// Deletes the array
void empty();
// Resize the array.
void resize(int the_size = 0);
// Access an element of the array.
int &operator[](int index);
// Returns the size of the array.
int get_size();
// Output the elements of the array.
void output();
friend ostream &operator<<(ostream &out, My_array &data);
};
#endif
This:
*this[i].array != data[i].array
should be this:
array[i] != data.array[i]
or this:
array[i] != data[i]
The *this is unnecessary, and data[i] is a reference to an int (the same one you get by calling data.array[i], thanks to your operator[]), and an int has no member called "array".