list requires class type - c++

So I'm trying to make a bubble sort algorithm in class and I'm having this problem where it keeps giving me an error when I'm trying to find the length of the list where it says "expression must have a class type" and for the life of me I cannot figure out what to do. the tutorial I'm using isn't an help and I cannot find any other people with the same problem.
if anyone gets what it is asking I would appreciate the help, and any explanation would also be appreciated as I'm still new and would like to understand so I can try to learn
this was all done on VS 2017 (the free version)
#include "pch.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
bool found = true;
int target{ 0 };
int temp{};
bool ordered{ false };
int list[10] = { 4,6,5,1,3,2,10,8,9,7 };
cout << list.length() << endl;
bool swapped{ false };
while (ordered = false)
{
target = 0;
while (target != list.length)
{
if (list[target] > list[target + 1])
{
swapped == true;
list[target] = temp;
list[target] = list[target + 1];
list[target + 1] = temp;
target = target + 1;
}
else
{
target = target + 1;
}
}
if (swapped == false)
{
ordered = true;
}
}
cout << list << endl;
getchar();
return 0;
}
link to the photo of the error message

The error you have mentioned ("expression must have a class type") is caused by the below statement and other similar statements :
cout << list.length() << endl;
list is an integer array of size 10 as per this statement int list[10];
So you cannot use a . on it. You can use the . operator on a structure or class or union only. And even if list were a class/structure, length() method should be defined in it for the above to work.
Instead you should use sizeof operator. You can store it in a variable and use it later on.
size_t length = sizeof list/sizeof list[0];
cout << length << endl;

Related

Assigning a struct pointer value from struct vector

#include <iostream>
#include <vector>
using namespace std;
struct Sn {
int SnId;
double spentEnergy;
};
class Node {
//other stuff
private:
vector<Sn> SnRecord;
public:
int getBestSn(Sn* bestSn);
void someFunction();
};
int main()
{
Node nd;
nd.someFunction();
return 0;
}
void Node::someFunction() {
//adding some records in vector just for testing purpose
Sn temp;
temp.SnId = 1; temp.spentEnergy = 5;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
cout << "Size of SnReocord is " << SnRecord.size() << endl;
//choosing best sn
Sn *bestSn;
int returnCode = -1;
returnCode = getBestSn(bestSn);
if (returnCode == 0){ //means there is a best SN
cout<< "Found best SN with id = "<< bestSn->SnId << endl;
}
else {
cout <<"NO SN "<< endl;
}
}
int Node::getBestSn(Sn* bestSn) {
int tblSize = (int)SnRecord.size();
if (tblSize == 0)
return -1;
//here i have to assign *bestSn a selected value from vector
//suppose SnRecord[2] is best Sn
cout << "Best sn id is " << SnRecord[2].SnId<< endl; //works OK,
bestSn = &SnRecord[2]; ///// giving me core dump ERROR in my own program but in this simplified version it only gives wrong value
return 0;
}
The output now is:
Size of SnReocord is 3
Best sn id is 2
Found best SN with id = 520004336
In my own program it gives me Core dump error, if I comment this line (and make proper other comments according to function call), the error is gone and simulation executes normally.
I saw examples with arrays, the work if a pointer is assigned a value in this way:
int numbers[5];
int * p;
p = &numbers[2]; //works OK.
but for vectors its not working. Or may be its problem of vector of structures, I'm unable to figure out. Any suggestions?
Ok actually the problem is solved by using suggestion of Sn* & bestSn. But I don't understand this solution. Why can't I pass a pointer variable and it saves a pointer value in it which latter could be accessed?

openmpi/c++: defining a mpi data type for class with members of variable length (pointers pointing to malloced memory)?

i am currently learning to use openmpi, my aim is to parallelize a simple program whose code i will post bellow.
The program is for testing my concept of paralleling a much bigger program, i hope to learn all i need to know for my actual problem if i succeed with this.
Basically it is a definition of a simple c++ class for lists. A list consists of two arrays, one integer and one double. Entries with the same indicies belong together, in a way that the integer entry is some kind of list entry identifier (maybe an object ID) and the double entry is some kind of quantifier (maybe the weight if an object).
The basic purpose of the program is to add lists together (this is the task i want to parallelize). Adding works as follows: For each entry in one list it is checked if there is the same integer entry in the the other list, if so then the double entry gets added to the double entry in the other list, if there is no such entry in the other list then both the integer and the double entries gets added to the end of the list.
Basically each summand in this list addition represents a storage and each entry is a type of object with a given amount (int is the type and double is the amount), so adding two lists means putting the stuff from the second storage to the first.
The order of the list entries is irrelevant, this means that the addition of lists is not only associative but commutative too!
My plan is to add a very large number of such lists (a few billions) so parallelizing could be to let each thread add a subset of lists first and when this is finished distribute all such sublists (one for each thread) to all of the threads.
My current understanding of openmpi is that only the last step (distributing of finished sublists) needs any special non standard stuff. Basically i need a AllReduce but with a custom data type and a custom operaton.
The first problem i have is understanding how to create a fitting MPI data type. I came to the conclusion that i probably need MPI_Type_create_struct to create a struct type.
I found this site with a nice example: http://mpi.deino.net/mpi_functions/MPI_Type_create_struct.html
from which i learned a lot but the problem is, that in this case there are fixed member arrays. In my case i have lists with arbitrary sized member variables or better with pointers pointing to memory blocks of arbitrary size. So doing it like in the example would lead to creating a new MPI datatype for each list size (using fixed sized lists could help but only in this minimalistic case, but i want to learn how to do it with arbitrary sized lists are preparation for my actual problem).
So my question is: how to create a data type for this special case? What is the best way?
I even thought to maybe write some non mpi code to serialize my class/object, (which would be a lot of work for my real problem but in this example it should be easy) to a single block of bits. Then i could simply use a MPI function to distribute those blocks to all threads and then i just have to translate it back to the actual object, and then i could let each thread simply add the "number-of-threads" lists together to have the same full reduced list on all threads (because the operation is commutative it is not important if the order is the same on each thread in the end).
The problem is that i do not know which MPI function to use to distribute a such memory blocks to each thread so that in the end each thread has an array of "number-of-threads" such blocks (similar like AllReduce but with blocks).
But thats just another idea, i would like to hear from you whats the best way.
Thank you, here is my fully working example program (ignore the MPI parts thats just preparation, you can simply compile with: g++)
As you can see, i needed to create custom copy constructors because standard of the pointer members. I hope thats not a problem for MPI?
#include <iostream>
#include <cstdlib>
#if (CFG_MPI > 0)
#include <mpi.h>
#else
#define MPI_Barrier(xxx) // dummy code if not parallel
#endif
class list {
private:
int *ilist;
double *dlist;
int n;
public:
list(int n, int *il, double *dl) {
int i;
if (n>0) {
this->ilist = (int*)malloc(n*sizeof(int));
this->dlist = (double*)malloc(n*sizeof(double));
if (!ilist || !dlist) std::cout << "ERROR: malloc in constructor failed!" << std::endl;
} else {
this->ilist = NULL;
this->dlist = NULL;
}
for (i=0; i<n; i++) {
this->ilist[i] = il[i];
this->dlist[i] = dl[i];
}
this->n = n;
}
~list() {
free(ilist);
free(dlist);
ilist = NULL;
dlist = NULL;
this->n=0;
}
list(const list& cp) {
int i;
this->n = cp.n;
this->ilist = NULL;
this->dlist = NULL;
if (this->n > 0) {
this->ilist = (int*)malloc(this->n*sizeof(int));
this->dlist = (double*)malloc(this->n*sizeof(double));
if (!ilist || !dlist) std::cout << "ERROR: malloc in copy constructor failed!" << std::endl;
}
for (i=0; i<this->n; i++) {
this->ilist[i] = cp.ilist[i];
this->dlist[i] = cp.dlist[i];
}
}
list& operator=(const list& cp) {
if(this == &cp) return *this;
this->~list();
int i;
this->n = cp.n;
if (this->n > 0) {
this->ilist = (int*)malloc(this->n*sizeof(int));
this->dlist = (double*)malloc(this->n*sizeof(double));
if (!ilist || !dlist) std::cout << "ERROR: malloc in copy constructor failed!" << std::endl;
} else {
this->ilist = NULL;
this->dlist = NULL;
}
for (i=0; i<this->n; i++) {
this->ilist[i] = cp.ilist[i];
this->dlist[i] = cp.dlist[i];
}
return *this;
}
void print() {
int i;
for (i=0; i<this->n; i++)
std::cout << i << " : " << "[" << this->ilist[i] << " - " << (double)dlist[i] << "]" << std::endl;
}
list& operator+=(const list& cp) {
int i,j;
if(this == &cp) {
for (i=0; i<this->n; i++)
this->dlist[i] *= 2;
return *this;
}
double *dl;
int *il;
il = (int *) realloc(this->ilist, (this->n+cp.n)*sizeof(int));
dl = (double *) realloc(this->dlist, (this->n+cp.n)*sizeof(double));
if (!il || !dl)
std::cout << "ERROR: 1st realloc in operator += failed!" << std::endl;
else {
this->ilist = il;
this->dlist = dl;
il = NULL;
dl = NULL;
}
for (i=0; i<cp.n; i++) {
for (j=0; j<this->n; j++) {
if (this->ilist[j] == cp.ilist[i]) {
this->dlist[j] += cp.dlist[i];
break;
}
} if (j == this->n) {// no matching entry found in this
this->ilist[this->n] = cp.ilist[i];
this->dlist[this->n] = cp.dlist[i];
this->n++;
}
}
il = (int *) realloc(this->ilist, (this->n)*sizeof(int));
dl = (double *) realloc(this->dlist, (this->n)*sizeof(double));
if (!il || !dl)
std::cout << "ERROR: 2nd realloc in operator += failed!" << std::endl;
else {
this->ilist = il;
this->dlist = dl;
}
return *this;
}
};
int main(int argc, char **argv) {
int npe, myid;
#if (CFG_MPI > 0)
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&npe);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
#else
npe=1;
myid=0;
#endif
if (!myid) // reduce output
std::cout << "NPE = " << npe << " MYID = " << myid << std::endl;
int ilist[5] = {14,17,4,29,0};
double dlist[5] = {0.0, 170.0, 0.0, 0.0, 24.523};
int ilist2[6] = {14,117,14,129,0, 34};
double dlist2[6] = {0.5, 170.5, 0.5, 0.5, 24.0, 1.2};
list tlist(5, ilist, dlist);
list tlist2(6, ilist2, dlist2);
if (!myid) {
tlist.print();
tlist2.print();
}
tlist +=tlist2;
if (myid) tlist.print();
#if (CFG_MPI > 0)
MPI_Finalize();
#endif
return 0;
}

C++ Member Function Clearing Matrix

I have had a similar issue with quite a few projects I have worked on involving classes containing arrays. I have a class that is supposed to handle a 2 dimensional matrix representing a TicTacToe game. There is an enumeration in the class for the status of the current game and one member function that has an enumeration return type. I cant seem to figure out why I can create the class set values in the matrix and as soon as I call the member function with the enumerated return type the whole array is reinitialized to 0. I think it has something to do with the constructor being called again or something along those lines but I have not been able to find anything after searching for the past few hours. Any help would be greatly appreciated.
Here is my header file containing the class information:
#ifndef TTT_H
#define TTT_H
#include <cstdlib>
#include <iostream>
using namespace std;
class TicTacToe
{
private:
enum Status{WinX, WinO, Continue, Draw};
int **board;
public:
TicTacToe();
~TicTacToe();
void PrintBoard();
bool ValidMove(int, int);
bool PlayerMove(int, int, int);
Status GameStatus(); //this one causes the problem
void Debug();
};
#endif
Here is the code for CPP file with the member function definitions:
#include "TicTacToe.h"
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <cassert>
using namespace std;
TicTacToe::TicTacToe()
{
board = new int*[3];
assert(board != 0);
for(int i=0;i<3;i++)
{
cout << "Constructor Ran again" << endl; //for testing
board[i] = new int[3];
assert(board[i] != 0);
for(int j=0;j<3;j++)
board[i][j] = 9;
}
}
TicTacToe::TicTacToe(TicTacToe &copy)
{
board = new int*[3];
assert(board != 0);
}
TicTacToe::~TicTacToe()
{
if(board)
delete[] board;
}
void TicTacToe::PrintBoard()
{
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
cout << "| ";
switch(board[i][j]){
case 0:
cout << "O ";
break;
case 1:
cout << "X ";
break;
case 9:
cout << " ";
break;
}
}
cout << "|" << endl;
cout << "------------" << endl;
}
}
bool TicTacToe::ValidMove(int row, int col)
{
bool valid = false;
if(row < 3 && col < 3)
{
if(board[row][col] == 9)
valid = true;
}
return valid;
}
bool TicTacToe::PlayerMove(int player, int row, int col)
{
bool done = false;
if(ValidMove(row,col) == true)
{
if(player == 1)
board[row][col] = 1;
else
board[row][col] = 0;
done = true;
}
return done;
}
TicTacToe::Status TicTacToe::GameStatus() //This function is the problem
{
int check, empty = 0;
bool done = false;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
check += board[i][j];
if(board[i][j] = 9)
empty++;
}
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
}
if(empty == 0)
return Draw;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
check += board[j][i];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
}
check = board[0][0] + board[1][1] + board[2][2];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
check = board[0][2] + board[1][1] + board[2][0];
if(check == 0)
return WinO;
else if(check == 3)
return WinX;
check = 0;
return Continue;
}
void TicTacToe::Debug()
{
//cout << &board[0][0] << endl;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
cout << board[i][j];
cout << endl;
}
}
Here is the driver file I am using to test:
#include "TicTacToe.h"
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
int row, col;
bool valid;
enum Status{WinX, WinO, Continue, Draw};
TicTacToe * T;
T = new TicTacToe;
assert(T != 0);
cout << "There are 2 players. P1 is x P2 is o" << endl;
do
{
T->PrintBoard();
valid = false;
while(valid == false)
{
cout << "\nP1 choose a cell" ;
cin >> row >> col;
if(T->ValidMove(row, col) == true)
{
T->PlayerMove(1, row, col);
valid = true;
}
else
{
cout << "Not a valid choice" << endl;
valid = false;
}
}
T->PrintBoard();
cout << endl;
T->GameStatus(); //<<<<<this is the pain in my butt
T->PrintBoard();
valid = false;
while(valid == false)
{
cout << "\nP2 choose a cell" ;
cin >> row >> col;
if(T->ValidMove(row, col) == true)
{
T->PlayerMove(2, row, col);
valid = true;
}
else
{
cout << "Not a valid choice" << endl;
valid = false;
}
}
}
while(/*T->GameStatus() == Continue*/ 1==1);
//the call to GameStatus was commented out of the
//while statement for testing
return 0;
}
I know the code inside of the GameStatus function is far from pretty but the array is messed up before any of those lines are processed.
I left all of the other functions just to show that they work properly without issue.
Thanks in advance for any help you may be able to give.
You've got a simple typo in your code..
if(board[i][j] = 9) // will always return true (refp)
empty++;
Other remarks
When looking at your code a bit more thoroughly I see that you have a few other miss-happens, intentional or unintentional.. that I don't know:
int check is not initialized in TicTacToe::GameStatus
You are not freeing the allocated memory properly, you'll
need to free all entries in board, ie. delete board[i])
I don't like bugs, how can I get rid of the operator= vs operator== problem?
A quite common method to circumvent the problem of making a typo and writing = when you mean to compare (==) two variables is to flip the operands around (if one of them is a constant value, such as 9.
if(9 = board[i][j]) will not compile and such a bug would've never appeared in your code.
I'll have to say that I don't like writing my statements that way.. though it's a quite common method, especially in the "beginner" segment.
check is not initialized in GameStatus() .
if (board[i][j] = 9)
Isn't the above line of code resetting the array contents? You probably want to use == here, instead.
You have a serious issue in memory management. Look:
Your constructor performs 4 allocations (an array of pointers and 3 arrays of ints, to emulate a 2D arrray),
Your destructor performs 1 deallocation (= memory leak),
You have a custom destructor but you don't define (or block) operator= (you need to, see What is The Rule of Three?)
Your copy constructor is incomplete and doesn't create a "valid" object.
Basically the above is likely to cause you some memory problems. I suggest to:
Rewrite the destructor to first free all the arrays of ints, then the array of pointers,
Make the class TicTacToe uncopiable by declaring the copy constructor and the operator= as private.
Also some minor details on that matter:
board = new int*[3];
assert(board != 0);
The assertion is unnecessary. If the allocation fails, the operator new will throw an exception.
if(board)
delete[] board;
Operators delete and delete[] don't do anything if their argument is a null pointer, so that condition is redundant. Also you have designed your object with the invariant that the board exists as long as the TicTacToe object exists, so that check is totally unnecessary, right?
Keep it safe and simple!

getting mergesort to work on linked-list?

Apologies if this is a silly / simple question.. but I'm very lost. I'm having trouble getting this program to run. I've written this program to read in 2 values, the first being a number of elements in a linked list, and the second to be the maximum random value that can be put into each element.
It should then use the merge sort algorithm included to sort and reprint the sorted list.
Ok, so I'm getting errors like:
base operand of `->' has non-pointer type `LIST'
and
request for member `element' in `conductor', which is of non-aggregate type `LIST *'
...(and a few others).
Yes this is for a class.. I've written the program but I'm not sure what I've done wrong here or why I'm getting errors? Any help is appreciated! Thank you
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
typedef struct LIST {
int element;
LIST *next;
};
LIST split(LIST list)
{
LIST pSecondCell;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return NULL;
else {
pSecondCell = list.next;
list.next = pSecondCell.next;
pSecondCell.next = split(pSecondCell->next);
return pSecondCell;
}
}
LIST merge(LIST list1, LIST list2)
{
if (list1 == NULL)
return list2;
else if (list2 == NULL)
return list1;
else if (list1.element <= list2.element) {
list1.next = merge(list1.next, list2);
return list1;
} else {
list2.next = merge(list1, list2.next);
}
}
LIST MergeSort(LIST list)
{
LIST SecondList;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return list;
else {
SecondList = split(list);
return merge(MergeSort(list), MergeSort(SecondList));
}
}
int main(int argCount, char *argVal[])
{
int i, number, max;
struct timeval time1;
struct timeval time2;
//check for correct number of arguments
if (argCount != 3) {
cout << "Incorrect number of arguments" << endl;
return 0;
}
// initialize read in n and max values
number = atoi(argVal[1]);
max = atoi(argVal[2]);
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for (i = 0; i < number; i++) {
conductor.element = rand() % max;
conductor.next = new LIST;
conductor = conductor.next;
}
// time how long it takes to sort array using mergeSort
gettimeofday(&time1, NULL);
mergeSort(root);
gettimeofday(&time2, NULL);
// print name, sorted array, and running time
cout << "Heather Wilson" << endl;
conductor = root;
for (i = 0; i < number - 2; i++) {
cout << conductor.element << ", ";
conductor = conductor.next;
}
double micro1 = time1.tv_sec * 1000000 + time1.tv_usec;
double micro2 = time2.tv_sec * 1000000 + time2.tv_usec;
cout << conductor.element << endl;
cout << "Running time: " << micro2 - micro1 << " microseconds" << endl;
return 0;
}
For base operand of->' has non-pointer type LIST'
Replace the -> with a .. You want to access a member of a local LIST, not a member of a pointed at object.
request for memberelement' in conductor', which is of non-aggregate type LIST *
This is the opposite. Replace the . with a ->. You want to access a member of the pointed at LIST, not a member of the pointer.
For clarification, I didn't read the code. There's too much of it. But those are the usual ways to address those specific errors. parapura seems to have actually read the code.
First: you should never have let the code grow this big with so many errors. You should start small and simple, then build up, testing at every stage, and never add to code that doesn't work.
Here's a stripped-down beginning of your code, with some bugs fixed:
#include <iostream>
using namespace std;
typedef struct LIST{
int element;
LIST *next;
};
int main(){
int i, number, max;
number = 5;
max = 100;
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for(i=0; i<number; i++){
conductor->element = rand() % max;
cout << "element " << i << " is " << conductor->element << endl;
conductor->next = new LIST;
conductor = conductor->next;
}
conductor = root; // Forgot this, didn't you!
for(i=0; i<number-2;i++){
cout << conductor->element << ", ";
conductor = conductor->next;
}
return 0;
}
Take a look at this, verify that it works, make sure you understand the changes I made, then you can take a crack at implementing your split, merge and MergeSort functions and the I/O (one at a time, and testing at every stage, naturally).
I think all the places you are passing
LIST merge ( LIST list1 , LIST list2 )
it should be
LIST* merge ( LIST* list1 , LIST* list2 )

Getting segmentation fault after destructor

I'm making a small file reading and data validation program as part of my TAFE (a tertiary college) course, This includes checking and validating dates.
I decided that it would be best done with a seperate class, rather than integrating it into my main driver class.
The problem is that I'm getting a segmentation fault(core dumped) after my test program runs. Near as I can tell, the error occurs when the program terminates, popping up after the destructor is called. So far I have had no luck finding the cause of this fault, and was hoping that some enlightened soul might show me the error of my ways.
date.h
#ifndef DATE_H
#define DATE_H
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <cstdlib>
using std::exit;
#include <iostream>
using std::cout;
using std::endl;
class date {
public:
explicit date();
~date();
bool before(string dateIn1, string dateIn2);
int yearsBetween(string dateIn1, string dateIn2);
bool isValid(string dateIn);
bool getDate(int date[], string dateIn);
bool isLeapYear(int year);
private:
int days[];
};
#endif
date.cpp
#include "date.h"
date::date() {
days[0] = 31;
days[1] = 28;
days[2] = 31;
days[3] = 30;
days[4] = 31;
days[5] = 30;
days[6] = 31;
days[7] = 31;
days[8] = 30;
days[9] = 31;
days[10] = 30;
days[11] = 31;
}
bool date::before(string dateIn1, string dateIn2) {
int date1[3];
int date2[3];
getDate(date1, dateIn1);
getDate(date2, dateIn2);
if (date1[2] < date2[2]) {
return true;
} else if (date1[1] < date2[1]) {
return true;
} else if (date1[0] < date2[0]) {
return true;
}
return false;
}
date::~date() {
cout << "this is for testing only, plox delete\n";
}
int date::yearsBetween(string dateIn1, string dateIn2) {
int date1[3];
int date2[3];
getDate(date1, dateIn1);
getDate(date2, dateIn2);
int years = date2[2] - date1[2];
if (date1[1] > date2[1]) {
years--;
}
if ((date1[1] == date2[1]) && (date1[0] > date2[1])) {
years--;
}
return years;
}
bool date::isValid(string dateIn) {
int date[3];
if (getDate(date, dateIn)) {
if (date[1] <= 12) {
int extraDay = 0;
if (isLeapYear(date[2])) {
extraDay++;
}
if ((date[0] + extraDay) <= days[date[1] - 1]) {
return true;
}
}
} else {
return false;
}
}
bool date::getDate(int date[], string dateIn) {
string part1, part2, part3;
size_t whereIs, lastFound;
whereIs = dateIn.find("/");
part1 = dateIn.substr(0, whereIs);
lastFound = whereIs + 1;
whereIs = dateIn.find("/", lastFound);
part2 = dateIn.substr(lastFound, whereIs - lastFound);
lastFound = whereIs + 1;
part3 = dateIn.substr(lastFound, 4);
stringstream p1(part1);
stringstream p2(part2);
stringstream p3(part3);
if (p1 >> date[0]) {
if (p2>>date[1]) {
return (p3>>date[2]);
} else {
return false;
}
return false;
}
}
bool date::isLeapYear(int year) {
return ((year % 4) == 0);
}
and Finally, the test program
#include <iostream>
using std::cout;
using std::endl;
#include "date.h"
int main() {
date d;
cout << "1/1/1988 before 3/5/1990 [" << d.before("1/1/1988", "3/5/1990")
<< "]\n1/1/1988 before 1/1/1970 [" << d.before("a/a/1988", "1/1/1970")
<<"]\n";
cout << "years between 1/1/1988 and 1/1/1998 ["
<< d.yearsBetween("1/1/1988", "1/1/1998") << "]\n";
cout << "is 1/1/1988 valid [" << d.isValid("1/1/1988") << "]\n"
<< "is 2/13/1988 valid [" << d.isValid("2/13/1988") << "]\n"
<< "is 32/12/1988 valid [" << d.isValid("32/12/1988") << "]\n";
cout << "blerg\n";
}
I've left in some extraneous cout statements, which I've been using to try and locate the error.
I thank you in advance.
Change:
private:
int days[];
to:
private:
int days[12];
The problem is that you never actually initialize the days field in the type date. This means that when you are setting the values in the constructor you are accessing uninitialized memory.
You need to explicitly initialize the days value in some way. The easiest fix is to use a vector for the type or to hard code the size of the array to 12.
private:
int days[12];
Or
private:
std:vector<int> days;
...
date::date() {
days.push_back(31);
days.push_back(28);
...
}
You don't say which compiler you are using, but if I compile this code using g++ with the -Wall and -pedantic flags:
struct S {
int a[];
};
int main() {
S s;
}
I get the warning message:
warning: ISO C++ forbids zero-size array 'a'
The moral is that you should always compile using as many compiler warnings as possible - it can save you mountains of time and result in more correct code.
int days[];
This is a non-standard extension. You must specify a size for the array, such as:
static const MonthCount = 12;
int days[MonthCount];
To actually have an array to use. Otherwise you have a "zero-sized array" (not standard!). Your program is tromping over memory every time you use any element of your current array.
I agree with the previous answers to this question, but I would add the rationale for their correctness:
Segmentation faults are caused whenever you attempt to access memory you are not allowed to access.
http://en.wikipedia.org/wiki/Segmentation_fault
You were not allowed to access "days[0]" through days "[11]" because the computer had not given the "days[]" variable that you declared enough memory to hold any elements, thus when you tried to access said elements, it threw a segfault.
Any variables not declared with the "new" operator are placed on the "stack," which is a contiguous chunk of memory the computer has sectioned away for use by the program. In order to keep everything stored in the stack contiguous, the computer will only give exactly the amount memory you require for you to use whenever you request it, so that if you request to create an int, for example, it will only give you enough memory to store that single int.
When you wrote the line int days[]; the computer attempted to evaluate how much memory it would require, assessed it as an empty array, and gave you enough memory to store said empty array. Because the computer did not give your array any extra space beyond what was needed for an empty array, it knew that the memory you tried to access in that array had not been assigned to it, so it threw a segmentation fault and crashed.
If you have not yet learned about the "stack" and "heap" in your computer science class, then sorry if this is a bit overwhelming, but I perhaps overcomplicated things, and I think you likely soon will.