Trying to use a linked list with ADT, but getting an unexpected error that I am unsure about

I am attempting to write a doubly linked list with abstract data types to store class objects from files passed to the program as command line arguments. At the present point, I am simply trying to get the linked list to work with anything so it's currently a singly linked list. Much of the other parts of the program present are just for testing things little by little.

Everything compiles and runs correctly, which I tested every time I made a change, but then when I tried to actually use the linked list things started to break. Currently, I am trying to just have it hold an integer as the first step and then when it works I will try to get it to hold objects.

Using either of these declarations work to create a list object:


sleepRecordList<typedef> list;

or

sleepRecordList<int> list;

However, when I try to insert an integer into the list like so:

list.insertLast(1);

I get this error:

Error LNK2019 unresolved external symbol "public: void __thiscall sleepRecordList<int>::insertLast(int const &)" (?insertLast@?$sleepRecordList@H@@QAEXABH@Z) referenced in function _main

Error LNK1120 1 unresolved externals

To me, it sounds like a mismatch between the header and the .cpp file, but I didn't see a problem there so then I removed const from it and got this error instead:

Error C2244 'sleepRecordList<Type>::insertLast': unable to match function definition to an existing declaration

Here's what the method looks like that I am trying to access:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class Type>
void sleepRecordList<Type>::insertLast(const Type & item)
{
    Node<Type> *newNode;
    newNode = new Node<Type>;
    newNode->data = item;
    newNode->link = nullptr;

    if (first == nullptr)
    {
        first = newNode;
        last = newNode;
        count++;
    }
    else
    {
        last->link = newNode;
        last = newNode;
    }
}


In my program I am not using namespace std; instead I am using each part of the namespace as I need it, but in the off-chance I missed something I added using namespace std; and then I got these errors instead:

Error C2872 'end': ambiguous symbol

Each time I tried using that object, which incidentally worked fine before adding the entire namespace and the old error comes back when removing them so I am fairly certain now that I'm not missing something simply like that.




Now, I expect that someone would want to see more than this, and I'm not sure just how much will be needed, so the following is the entire program typed out with file name labels:

(will have to put it in a reply, because of max characters)

include.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  #pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <iostream> 
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <stdlib.h>

//"using" explicitly as needed rather than the entire namespace. 
// Seems to work as well as the #define approach. 
// If a situation should arise where two namespaces have the same word I want to use, 
// I'd #define the second with a different name

using std::cout;
using std::cin;
using std::endl;
using std::string;
// #define string std::string   
using std::ifstream;
using std::stringstream;
using std::getline;
using std::strcpy;
using std::remove_if;
using std::cerr;
using std::to_string;
using std::setfill;
using std::setw;
using std::logic_error;


class.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#pragma once
#include "include.h"

enum class checkStatus
{
    Invalid_Status,
    OK,
    Out_Of_Range
};
// TODO: Implement the above and rewrite normalize to use

class Time
{
protected:
    int hour;
    int min;
    int sec;
public:
    Time();
    Time(int hour, int min, int sec);

    long diff(const Time time) const;            // return difference in time in sec
    void diff(const Time start, const Time end); // compute difference in time

    //Setters:
    void setTime(int hour, int min, int sec);
    void setHour(int hour);
    void setMinute(int min);
    void setSecond(int sec);

    //Getters:
    int getHour() const;
    int getMinute() const;
    int getSecond() const;

    //Copy constructor
    Time(const Time &time);

    string toString() const;
    void addTime(const Time time);
    void addTime(const long sec);

    //Destructor
    ~Time();

private:
    void normalize();

};

class Date
{
public:
    int	day;
    int	month;
    int	year;
    string	toString();

    //Destructor
    ~Date();
};

class Sleep //: public Time
{
public: 
    Time startTime;
    Time endTime;
    Date startDate;
    Date endDate;
    int playerNumber;   // expect 0 - 99
    string playerName;  // Last name given so may not be unique

    //	need	operator=
    string	toString()	const;

    //// The following no longer needed:
    //int dayStart;       // Expect 1 - 31
    //int monthStart;     // Expect 1 - 12
    //int yearStart;      // Expect 2017 or larger
    //int hourStart;      // expect 0 - 23
    //int minuteStart;    // expect 0 - 59
    //int secondStart;    // expect 0 - 59
    //int dayEnd;         // expect 1 - 31
    //int monthEnd;       // Expect 1 - 12
    //int yearEnd;        // Expect 2017 or larger
    //int hourEnd;        // Expext 0 - 23
    //int minuteEnd;      // Expect 0 - 59
    //int secondEnd;      // expect 0 - 59
};

template <class Type>
class Node
{
public:
    Type data;
    Node<Type> *link;
};

template <class Type>
class sleepIterator : public Node<Type>
{
private:
    Node<Type> *current;
public:
    sleepIterator();
    sleepIterator(Node<Type> * );
    Type operator * (); //dereference operator
    sleepIterator<Type> operator++(); //increment operator
    bool operator==(const sleepIterator<Type>&) const;
    bool operator!=(const sleepIterator<Type>&) const;
};

template <class Type>
class sleepNode
{
protected:
    int count;
    Node<Type> *first;
    Node<Type> *last;
private:
    void copyList(const sleepNode<Type>&);
public:
    const sleepNode<Type> & operator=(const sleepNode<Type> &);
    void initializeList();
    bool isEmptyList() const;
    void print() const;
    int length() const;
    void destroyList();
    Type front() const;
    Type back() const;
    virtual bool search(const Type &) const = 0;
    virtual void insertFirst(const Type&) = 0;
    virtual void insertLast(const Type&) = 0;
    virtual void deleteNode(const Type&) = 0;
    sleepNode<Type> begin();
    sleepNode<Type> end();
    sleepNode();
    sleepNode(const sleepNode<Type> &);
    ~sleepNode();
};

template <class Type>
class sleepRecordList
{
public:
    bool search(const Type &) const;
    void insertFirst(const Type &);
    void insertLast(const Type &item);
    void deleteNode(const Type &);

};



Last edited on

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

#pragma warning(disable: 4996) 
// This was required in order to compile in Visual Studios 2015 because 
// it doesn't like sscanf

#include "class.h"
#include "include.h"

const int maxLines = 100; // Max students
const int maxDays = 31; // Max days in month

// Prototypes
ifstream *openFileWithCheck(string name);

Time start;
Time end;
Time total;
sleepRecordList<Sleep> student;

int main(int argc, char *argv[])
{
    string name = "data.csv"; //This is the filename used
    ifstream *inFile;

    Sleep singleStudentRecord;
    // to meet the requirement to report the bytes stores for each sleep period
    cout << "Size of core record: " << sizeof(singleStudentRecord) << " bytes." << endl; 
    // an interesting extra I was curious about
    cout << "Size of sleep record list: " << sizeof(student) << " byte(s)." << endl << endl;

    if (argc < 2) 
    {
        cout << "No file name given." << endl;
        //TODO: Return string assignment and use the 
        //following when ready to only use command line arguments:
        
        // return(1);
    }
    else
    {
        for (int i = 1; i < argc; i++) 
        {
            
            name = argv[i];

                            // These functions called for each filename given
            inFile = openFileWithCheck(name); 

            //fileAccess(inFile, players);
        }
    }

    

    start.addTime(10000);
    end.addTime(1200);

    start.addTime(10000);
    end.addTime(1200);

    long sec = 0;

    sec += start.diff(end); // time difference

    total.addTime(sec);

    cout << total.toString() << endl << endl;

        /*     The following just to test usage of linked list     */
    sleepRecordList<typedef> list; 
//trying to use anonymous types to test because I want to be able to store the entire record

    //// Doesn't compile when I use the following. 
    //// It says "Unresolved external symbol referenced in main"

//    list.insertLast(1);
//    list.insertLast(2);
//    list.insertLast(3);




     
     /*  -----------------------------------------------------  */

    system("pause");

    return(0);
}

ifstream *openFileWithCheck(string name)
{
    ifstream *inFile;
    inFile = new ifstream(name);

    if (inFile->fail())
    {
        cout << "Invalid file name in the current directory." << endl;
        exit(EXIT_FAILURE);
    }
    else
    {
        string temp1;
        getline(*inFile, temp1);
        cout << temp1;
        return(inFile);
    }
    return(inFile);
}

Last edited on

class.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  #include "class.h"
#include "include.h"

/* --- Begin Time class --- */

Time::Time() 
{
    hour = 0;
    min = 0;
    sec = 0;
}

Time::Time(int hour, int min, int sec)
{
    this->setTime(hour, min, sec);
}

Time::Time(const Time &time)
{
    //Shallow copying non-pointers
    hour = time.hour;
    min = time.min;
    sec = time.sec;

    ////Following used to test the copy constructor. 
    //cout << "Copy constructor called" << endl;

}

string Time::toString() const {

    string result;
    result = std::to_string(hour) + ":" + to_string(min) + ":" + to_string(sec);
    return result;
}

long Time::diff(const Time time) const 
{
    long diff = 0;

    diff += sec - time.sec;
    diff += (min - time.min) * 60;
    diff += (hour - time.hour) * 3600;
    return diff;
}

void Time::diff(const Time start, const Time end)
{
}

void Time::setTime(int hour, int min, int sec)
{
    setHour(hour);
    setMinute(min);
    setSecond(sec);
}

void Time::setHour(int hour)
{
    this->hour = hour;
}

void Time::setMinute(int min)
{
    this->min = min;
}

void Time::setSecond(int sec)
{
    this->sec = sec;
}

int Time::getHour() const
{
    return this->hour;
}

int Time::getMinute() const
{
    return this->min;
}

int Time::getSecond() const
{
    return this->sec;
}

void Time::addTime(const Time time) {
    min += time.min;
    sec += time.sec;
    hour += time.hour;
    normalize();
}

void Time::addTime(const long sec) {
    this->sec += sec;
    normalize();
}

Time::~Time()
{
    //// The following used to test:
    // cout << "Destructor Called!" << endl;
}

void Time::normalize() {
    min += sec / 60;
    sec = sec % 60;
    hour += min / 60;
    min = min % 60;
}

/* --- Begin Date class --- */


string Date::toString()
{
    return string();
}

Date::~Date()
{
}

/* --- Begin Sleep class --- */

string Sleep::toString() const
{
    return string();
}

/* --- Begin Node class --- */


/* --- Begin sleepIterator class --- */


template<class Type>
sleepIterator<Type>::sleepIterator() //constructor
{
    current = nullptr;
}

template<class Type>
sleepIterator<Type>::sleepIterator(Node<Type>*) //constructor with parameters
{
    current = ptr;
}

template<class Type>
Type sleepIterator<Type>::operator*() //deference overload
{
    return current->data;
}

template<class Type>
sleepIterator<Type> sleepIterator<Type>::operator++() //increment overload
{
    current = current->link;
    return *this;
}

template<class Type>
bool sleepIterator<Type>::operator==(const sleepIterator<Type>&) const //equality operator
{
    return (current == other.current);
}

template<class Type>
bool sleepIterator<Type>::operator!=(const sleepIterator<Type>&) const //inequality operator
{
    return (current != other.current);
}

/* --- Begin sleepNode class --- */

template<class Type>
void sleepNode<Type>::copyList(const sleepNode<Type>&)
{
    Node<Type> *newNode, *current;
    
    if (first != nullptr)
    {
        destroyList();
    }

    if (other.first == nullptr)
    {
        first = nullptr;
        last = nullptr;
        count = 0
    }
    else
    {
        current = other.first;
        count = other.count;
        first = new Node<Type>;
        first->data = current->data;
        first->link = nullptr;
        current = current->link;

        while (current != nullptr)
        {
            newNode = new Node<Type>;
            first->data = current->data;
            newNode->link = nullptr;
            last = newNode;
            current = current->link;
        }
    }
}

template<class Type>
const sleepNode<Type>& sleepNode<Type>::operator=(const sleepNode<Type>&)
{
    if (!= &other)
    {
        copyList(other);
    }
    return *this;
}

template<class Type>
void sleepNode<Type>::initializeList() // reinitializes the list to empty
{
    destroyList();
}

template<class Type>
bool sleepNode<Type>::isEmptyList() const
{
    return(first == nullptr);
}

template<class Type>
void sleepNode<Type>::print() const
{
    Node<Type> *current;
    current = first;

    while (current != nullptr)
    {
        cout << current->data << " ";
        current = current->link;
    }
}

template<class Type>
int sleepNode<Type>::length() const
{
    return count;
}

template<class Type>
void sleepNode<Type>::destroyList()
{
    Node<Type> *temp;
    
    while (first != nullptr)
    {
        temp = first;
        first = first->link;
        delete temp;
    }

    last = nullptr;
    count = 0;
}

template<class Type>
Type sleepNode<Type>::front() const
{
    assert(first != nullptr)
    return first->data;
}

template<class Type>
Type sleepNode<Type>::back() const
{
    return Type();
}

template<class Type>
sleepNode<Type> sleepNode<Type>::begin()
{
    sleepNode<Type> temp(first);
    return temp;
}

template<class Type>
sleepNode<Type> sleepNode<Type>::end()
{
    sleepNode<Type> temp(nullptr);
    return temp;
}

template<class Type>
sleepNode<Type>::sleepNode()
{
    first = nullptr;
    last = nullptr;
    count = 0;
}

template<class Type>
sleepNode<Type>::sleepNode(const sleepNode<Type>& other)
{
    first = nullptr;
    copyList(other);
}

template<class Type>
sleepNode<Type>::~sleepNode()
{
}

/* --- Begin sleepRecordList class --- */

template<class Type>
bool sleepRecordList<Type>::search(const Type & searchItem) const
{
    Node<Type> *current;
    bool found = false;
    current = first;

    while (current != nullptr && !found)
    {
        if (current->data == searchItem)
        {
            found = true;
        }
        else
        {
            current = current->link;
        }
    }

    return found;
}

template<class Type>
void sleepRecordList<Type>::insertFirst(const Type & item)
{
    Node<Type> *newNode;
    newNode = new Node<Type>;
    newNode->data = item;
    newNode->link = first;
    first = newNode;
    count++;

    if (last == nullptr)
    {
        last = newNode;
    }
}

template<class Type>
void sleepRecordList<Type>::insertLast(const Type & item)
{
    Node<Type> *newNode;
    newNode = new Node<Type>;
    newNode->data = item;
    newNode->link = nullptr;

    if (first == nullptr)
    {
        first = newNode;
        last = newNode;
        count++;
    }
    else
    {
        last->link = newNode;
        last = newNode;
    }
}

template<class Type>
void sleepRecordList<Type>::deleteNode(const Type & item)
{
    Node<Type> *current, *trailCurrent;
    bool found;

    if (first == nullptr)
    {
        cout << "This is an empty list." << endl;
    }
    else
    {
        if (first->data == item)
        {
            current = first;
            first = first->link;
            count--;
            if (first == nullptr)
            {
                last = nullptr;
            }
            else
            {
                found = false;
                trailCurrent = first;
                current = first->link;

                while (current != nullptr && !found)
                {
                    if (current->data != item)
                    {
                        trailCurrent = current;
                        current = current->link;
                    }
                    else
                    {
                        found = true;
                    }
                }

                if (found)
                {
                    trailCurrent->link = current->link;
                    count--;

                    if (last == current)
                    {
                        last = trailCurrent;
                    }

                    delete current;
                }
                else
                {
                    cout << "List does not contain the item requested." << endl;
                }
            }
        }
    }
}



That's the entire program as it is right now, which compiles and runs with the problem area commented out with comments noting it in main.cpp
Last edited on
Topic archived. No new replies allowed.