I am solving exercises for a C++ exam I have soon. Consider the following exercise:
A travel agency uses lists to manage its trips. For each trip the agency registers its point of departure, point of arrival, distance and time/duration
1) Define the necessary structures to represent a list of trips
2) Write a function that, given integer i returns the point of departure and point of arrival of the trip in position i
Defining the structure is easy:
struct list{
char departure[100];
char arrival[100];
double distance;
double time;
list* next = NULL;
};
My problem is the function. The actual work, to find the ith trip is easy. But how can I return the two char arrays/strings departure and arrival? If this were a question in my exam, I would have solved it like this:
typedef list* list_ptr;
list_ptr get_trip(list_ptr head, const int i){
if(i<0 || head==NULL){
return NULL;
}
for(int k = 0; k<i;k++){
head = head->next;
if(head==NULL){
return NULL;
}
}
return head;
}
I am returning a pointer to the list element. One then has to print departure and arrival. I could easily return just the departure or just the arrival by using a function with return type char*. How can I properly return 2 strings?
I know that there is ways doing this using std::tuple, but I cannot use this as we haven't had it in the lecture(we only had the really basic stuff, up to classes).
Am I right that returning both strings is not possible without using additional libraries?
Cheers
OK, to start with, your list type has some problems. Don't use char[] in C++ unless you really, really have to (note: if you think you have to, you're probably wrong). C++ provides a standard library that is wonderous in its applications (well, compared to C), and you should use it. In particular, I'm talking about std::string. You're probably OK using double for distance and duration, although a lack of units means that you're going to have a bad time.
Let's try this:
struct Trip {
std::string departure;
std::string arrival;
double distance_km;
double duration_hours;
};
Now you can either use std::vector, std::list, std::slist, or roll your own list. Let's assume the last.
class TripList {
public:
TripList() = default;
// Linear in i.
Trip& operator[](std::size_t i);
const Trip& operator[](std::size_t i) const;
void append_trip(Trip trip);
void remove_trip(std::size_t i);
private:
struct Node {
Trip t;
std::unique_ptr<Node> next;
};
std::unique_ptr<Node> head;
Node* tail = nullptr; // for efficient appending
};
I'll leave implementation of this to you. Note that list and trip are separate concepts, so we're writing separate types to handle them.
Now you can write a simple function:
std::pair<string, string> GetDepartureAndArrival(const TripList& list, std::size_t index) {
const auto& trip = list[index];
return {trip.departure, trip.arrival};
}
Related
I have a C++ program that creates Huffman codes for all characters in file. It works good, but I want to create nodes without using new operator because I know that you shouldn't use it. I tried using a vector global variable for saving nodes but that doesn't work.
std::vector<Node> nodes;
Node* create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
Node temp;
temp.m_value = value;
temp.m_counter = counter;
temp.m_left = left;
temp.m_right = right;
nodes.push_back(temp);
return &nodes[nodes.size() - 1];
}
Edit: I added more code, I did't really explained what doesn't work. Problem is in generate_code(), it never reaches nullptr. I also tried using Node and not Node* but the same thing happened.
void generate_code(Node* current, std::string code, std::map<unsigned char, std::string>& char_codes) {
if (current == nullptr) {
return;
}
if (!current->m_left && !current->m_right) {
char_codes[current->m_value] = code;
}
generate_code(current->m_left, code + "0", char_codes);
generate_code(current->m_right, code + "1", char_codes);
}
void huffman(std::ifstream& file) {
std::unordered_map<unsigned char, ull> char_frequency;
load_data(file, char_frequency);
std::priority_queue<Node*, std::vector<Node*>, Comparator> queue;
for (auto& node : char_frequency) {
queue.push(create_node(node.first, node.second, nullptr, nullptr));
}
while (queue.size() != 1) {
Node* left = queue.top();
queue.pop();
Node* right = queue.top();
queue.pop();
auto counter = left->m_counter + right->m_counter;
queue.push(create_node('\0', counter, left, right));
}
std::map<unsigned char, std::string> char_codes;
Node* root = queue.top();
generate_code(root, "", char_codes);
for (auto& i : char_codes) {
std::cout << +i.first << ": " << i.second << "\n";
}
}
The general answer is of course to use smart pointers, like std::shared_ptr<Node>.
That said, using regular pointers is not that bad, especially if you hide all pointers from the outside. I wouldn't agree with "you shouldn't use new", more like "you should realize that you have to make sure not to create a memory leak if you do".
In any case, for something like you do, especially with your vector, you don't need actual pointers at all. Simply store an index for your vector and replace every occurence of Node* by int, somewhat like:
class Node
{
public:
// constructors and accessors
private:
ValueType value;
int index_left;
int index_right;
}
I used a signed integer as index here in order to allow storing -1 for a non-existent reference, similar to a null pointer.
Note that this only works if nothing gets erased from the vector, at least not before everything is destroyed. If flexibility is the key, you need pointers of some sort.
Also note that you should not have a vector as a global variable. Instead, have a wrapping class, of which Node is an inner class, somewhat like this:
class Tree
{
public:
class Node
{
...
};
// some methods here
private:
vector<Node> nodes;
}
With such an approach, you can encapsulate your Node class better. Tree should most likely be a friend. Each Node would store a reference to the Tree it belongs to.
Another possibility would be to make the vector a static member for Node, but I would advise against that. If the vector is a static member of Node or a global object, in both cases, you have all trees you create being in one big container, which means you can't free your memory from one of them when you don't need it anymore.
While this would technically not be a memory leak, in practice, it could easily work as one.
On the other hand, if it is stored as a member of a Tree object, the memory is automatically freed as soon as that object is removed.
but I want to create nodes without using new operator because I know that you shouldn't use it.
The reason it is discouraged to use new directly is that the semantics of ownership (i.e. who is responsible for the corresponding delete) isn't clear.
The c++ standard library provides the Dynamic memory management utilities for this, the smart pointers in particular.
So I think your create function should look like follows:
std::unique_ptr<Node> create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
std::unique_ptr<Node> temp = std::make_unique<Node>();
temp->m_value = value;
temp->m_counter = counter;
temp->m_left = left;
temp->m_right = right;
return temp;
}
This way it's clear that the caller takes ownership of the newly created Node instance.
So I recently came across a data structure roughly like this:
template<class T>
struct Node {
size_t m_next;
size_t m_prev;
T m_key;
}
template<class T, size_t N>
struct DS {
Node<T> m_elements[N];
size_t m_head;
size_t m_tail;
}
I simplified a bit, just to keep this brief: I don't do error handling when DS gets too full. Normally N is large enough that this isn't a concern.
One note is T must have some way of representing "no value"; why this is needed can be seen below. (I'll refer to this value as TOMBSTONE below.)
The API for this data structure is roughly the same as for a linked list, but it performs much better because everything fits nicely in the cache.
The actual implementation is different from a linked list in that it doesn't need to allocate any new memory for new nodes. For example, pushing to the back of DS is roughly like this:
void DS::push_back(T t) {
size_t attempt = 0;
size_t i = hash(t, attempt++);
while (true) {
if (m_elements[i] == TOMBSTONE) {
m_elements[m_tail].m_next = i;
m_elements[i] = Node(N, m_tail, t);
m_tail = i;
break;
}
i = hash(t, attempt++);
}
}
where hash(T t, size_t attempt) finds places to try to insert new elements. (This is so there's nice spread, rather than clumping everything at the start.)
I hesitate to call this a linked list because of the vast performance and implementation differences from a normal linked list. I also want to point out that this question is not about when to use what data-structures, or if the above data-structure is good/fast/safe/whatever. This data-structure works quite well for us in the very specific situation we use it in.
Is there any name for this particular implementation/data-structure?
It is linked list. It's mentioned on Wikipedia as "Linked list using arrays of nodes"
It's a double-linked linked list, implemented with a C-style array.
Hello I am new fairly newly to C++ and I am constructing a program that will simulate a colony of bunnies. I am a bit stuck on how to resolve this issue on how to get methods to recognize my global pointer variables. I get this error when I try to compile my program.
enter code here
main.cpp: In function ‘bool ageCheck(BunnyNode*)’:
main.cpp:133:5: error: ‘head’ was not declared in this scope
if(head){
^
I have several more errors that are similar to this one. I am under the impression that if I understand why this error is being given, I will be able to sort out the others. I chose an error from the ageCheck() method that is supposed to traverse the linked list of bunnies and check their ages.
This is what I have
enter code here
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
//#include "listofbunny.h"
using std::cin;
using namespace std;
typedef struct BunnyNode {
string* name;
int age;
bool gender;
string* color;
bool radioactive_bunny;
BunnyNode *next;
BunnyNode *head;
BunnyNode *tail;
BunnyNode *current;
}
char menu();
int randomGeneration(int x);
void generateFeatures(BunnyNode * newBunny);
void startCheck(int pass);
void sizeCheck(bool& terminate);
bool fatherCheck(BunnyNode * bunny, bool& fatherPresent);
bool motherCheck(BunnyNode * bunny);
bool ageCheck(BunnyNode * bunny);
void addBunnyAge();
void addBabyBunny();
void addBunny();
void addBunny(BunnyNode * mother);
int mutantCount();
void mutantTransform();
void purge();
string getGender(BunnyNode * bunny);
string getName(BunnyNode * bunny);
int getColonySize();
void printColony();
void printFeature(BunnyNode * bunny);
void printSize();
bool ageCheck(BunnyNode * bunny){
if(head){
if(bunny->age >= MAX_AGE && bunny->radioactive_bunny == false){
return 1;
}
else if(bunny->age >= MAX_MUTANT_AGE && bunny->radioactive_bunny){
return 1;
}
else
return 0;
}
}
A typical linked list structure is made of three parts
The Data
class Bunny
{
string name; // don't use pointers unless you really, really need them
int age;
bool gender;
string color;
bool radioactive_bunny;
public:
string getGender(); // don't need to know which Bunny anymore because
// these functions are bound to a particular Bunny
string getName();
...
};
The Node
struct Node
{
Bunny data; // we will ignore templates for now. But they are rilly kool!
Node * next; // here is a good time to use a pointer: to point to the next node
Node(): next(nullptr) // node constructor. This really helps. Trust me.
{
}
}
Nodes know nothing except their data and a link to the next Node. The dumber you can make a Node, the safer you are. Also note that the Node contains the Data. This allows you to easily swap out the Data without having to re-write the whole node and sets you up for easy templating of the Lined List structure later (though you're probably better off jumping to std::list).
And the Linked List:
class LinkedList
{
Node *head;
Node *tail;
Node *current; // not as useful as you might think
public:
LinkedList(): head(nullptr),tail(nullptr),current(nullptr)
{
}
void add(Bunny & bunny);
void remove(const string & bunnyname);
Bunny & get(const string & bunnyname);
Bunny & getNext(); // current may help here, but look into iterators
...
};
Note that we never let the caller at a Node. They could do something stupid like delete it or mangle Node::next.
Adding, removing and iterating through the list has been beaten to death on Stack Overflow, so you should be able to find tonnes of examples of how to do this. For example: Using pointers to remove item from singly-linked list. There is, in my opinion, a really important trick in that link well worth the time spent learning. Pointers are like fire: A handy servant, but a terrifying master.
The big trick to getting linked lists is use a pencil and paper to draw the list and the nodes. See how they are connected. Redraw the list step by step as you add, remove, etc... so you can see how it needs to be done. Then write code to match the drawings. I know. Easier said than done, but way easier than banging your head against a wall with no plan whatsoever.
now i have been making games for a few years using the gm:s engine(tho i assure you i aint some newbie who uses drag and drop, as is all to often the case), and i have decided to start to learn to use c++ on its own, you know expand my knowledge and all that good stuff =D
while doing this, i have been attempting to make a list class as a practice project, you know, have a set of nodes linked together, then loop threw those nodes to get a value at a index, well here is my code, and i ask as the code has a single major issue that i struggle to understand
template<class type>
class ListNode
{
public:
type content;
ListNode<type>* next;
ListNode<type>* prev;
ListNode(type content) : content(content), next(NULL), prev(NULL) {}
protected:
private:
};
template<class type>
class List
{
public:
List() : SIZE(0), start(NULL), last(NULL) {}
unsigned int Add(type value)
{
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
else
{
ListNode<type> a(value);
this->last->next = &a;
a.prev = this->last;
this->last = &a;
}
this->SIZE++;
return (this->SIZE - 1);
}
type Find(unsigned int pos)
{
ListNode<type>* a = this->start;
for(unsigned int i = 0; i<this->SIZE; i++)
{
if (i < pos)
{
a = a->next;
continue;
}
else
{
return (*a).content;
}
continue;
}
}
protected:
private:
unsigned int SIZE;
ListNode<type>* start;
ListNode<type>* last;
};
regardless, to me at least, this code looks fine, and it works in that i am able to create a new list without crashing, as well as being able to add elements to this list with it returning the proper index of those elements from within the list, however, beyond that the problem arises when getting the value of a element from the list itself, as when i ran the following test code, it didn't give me what it was built to give me
List<int> a;
unsigned int b = a.Add(313);
unsigned int c = a.Add(433);
print<unsigned int>(b);
print<int>(a.Find(b));
print<unsigned int>(c);
print<int>(a.Find(c));
now this code i expected to give me
0
313
1
433
as that's what is been told to do, however, it only half does this, giving me
0
2686684
1
2686584
now, this i am at a lost, i assume that the values provided are some kind of pointer address, but i simply don't understand what those are meant to be for, or what is causing the value to become that, or why
hence i ask the internet, wtf is causing these values to be given, as i am quite confused at this point
my apologies if that was a tad long and rambling, i tend to write such things often =D
thanks =D
You have lots of undefined behaviors in your code, when you store pointers to local variables and later dereference those pointers. Local variables are destructed once the scope they were declared in ends.
Example:
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
Once the closing brace is reached the scope of the if body ends, and the variable a is destructed. The pointer to this variable is now a so called stray pointer and using it in any way will lead to undefined behavior.
The solution is to allocate the objects dynamically using new:
auto* a = new ListNode<type>(value);
Or if you don't have a C++11 capable compiler
ListNode<type>* a = new ListNode<type>(value);
First suggestion: use valgrind or a similar memory checker to execute this program. You will probably find there are many memory errors caused by dereferencing stack pointers that are out of scope.
Second suggestion: learn about the difference between objects on the stack and objects on the heap. (Hint: you want to use heap objects here.)
Third suggestion: learn about the concept of "ownership" of pointers. Usually you want to be very clear which pointer variable should be used to delete an object. The best way to do this is to use the std::unique_ptr smart pointer. For example, you could decide that each ListNode is owned by its predecessor:
std::unique_ptr<ListNode<type>> next;
ListNode<type>* prev;
and that the List container owns the head node of the list
std::unique_ptr<ListNode<type>> start;
ListNode<type>* last;
This way the compiler will do a lot of your work for you at compile-time, and you wont have to depend so much on using valgrind at runtime.
I want to create a generic linked list in C/C++ (without using templates of C++).
I have written following simple program and it works fine as of now -
typedef struct node
{
void *data;
node *next;
}node;
int main()
{
node *head = new node();
int *intdata = new int();
double *doubledata = new double();
char *str = "a";
*doubledata = 44.55;
*intdata = 10;
head->data = intdata;
node *node2 = new node();
node2->data = doubledata;
head->next = node2;
node *node3 = new node();
node3->data = str;
node3->next = NULL;
node2->next = node3;
node *temp = head;
if(temp != NULL)
{
cout<<*(int *)(temp->data)<<"\t";
temp = temp->next;
}
if(temp != NULL)
{
cout<<*(double *)(temp->data)<<"\t";
temp = temp->next;
}
if(temp != NULL)
{
cout<<*(char *)(temp->data)<<"\t";
temp = temp->next;
}
return 0;
}
My question is -
I need to know the data type of the data I am printing in the code above.
For example - first node is int so i wrote -
*(int *)(temp->data)
second is double and so on...
Instead, is there any generic way of simply displaying the data without worrying about the data type?
I know you can achieve this with templates, but what if I have to do this in C only ?
Thanks,
Kedar
The whole point of a generic list is that you can store anything in it. But you have to be realistic... You still need to know what you are putting in it. So if you are going to put mixed types in the list, then you should look at using a Variant pattern. That is, a type that provides multiple types. Here's a simple variant:
typedef struct Variant
{
enum VariantType
{
t_string,
t_int,
t_double
} type;
union VariantData
{
char* strVal;
int intVal;
double doubleVal;
} data;
} Variant;
You can then tell yourself "I'm storing pointers to Variants in my void* list. This is how you would do it in C. I assume when you say "C/C++" you mean that you're trying to write C code but are using a C++ compiler. Don't forget that C and C++ are two different languages that have some overlap. Try not to put them together in one word as if they're one language.
In C, the only way to achieve generics is using a void*, as you are already doing. Unfortunately, this means that there is no easy way to retrieve the type of an element of your linked list. You simply need to know them.
The way of interpreting data in memory is completely different for different data type.
Say a 32 bit memory block has some data. It will show different values when you typecast it as int or float as both are stored with different protocols. When saving some data in memory pointed by variable of type void*, it does not know how to interpret the data in its memory block. So you need to typecast it to specify the type in which you want to read the data.
This is a little bit like sticking all the cutlery in a drawer, but instead of putting knifes in one slot, forks in another slot, and spoons in a third slot, and teaspoons in the little slot in the middle, we just stick them all in wherever they happen to land when chucking them in, and then wondering why when you just stick your hand in and pick something up, you can't know what you are going to get.
The WHOLE POINT of C++ is that it allows you to declare templates and classes that "do things with arbitrary content". Since the above code uses new, it won't compile as C. So there's no point in making it hold an non-descriptive pointer (or even storing the data as a pointer in the first place).
template<typename T> struct node
{
T data;
node<T> *next;
node() : next(0) {};
};
Unfortunately, it still gets messier if you want to store a set of data that is different types within the same list. If you want to do that, you will need something in the node itself that indicates what it is you have stored.
I have done that in lists a few times since I started working (and probably a couple of times before I got a job) with computers in 1985. Many more times, I've done some sort of "I'll store arbitrary data" in a something like a std::map, where a name is connected to some "content". Every time I've used this sort of feature, it's because I'm writing something similar to a programming language (e.g. a configuration script, Basic interpreter, LisP interpreter, etc), using it to store "variables" that can have different types (int, double, string) or similar. I have seen similar things in other places, such as OpenGL has some places where the data returned is different types depending on what you ask for, and the internal storage has to "know" what the type is.
But 99% of all linked lists, binary trees, hash-tables, etc, that I have worked on contain one thing and one thing only. Storing "arbitrary" things in a single list is usually not that useful.
The answer below is targeting at C++ and not C. C++ allows for what you want, just not in the way that you want to do it. The way I would implement your problem would be using the built-in functionality of the virtual keyword.
Here's a stand-alone code sample that prints out different values no matter the actual derived type:
#include <iostream>
#include <list>
class Base
{
public:
virtual void Print() = 0;
};
class Derived1 : public Base
{
public:
virtual void Print()
{
std::cout << 1 << std::endl; // Integer
}
};
class Derived2 : public Base
{
public:
virtual void Print()
{
std::cout << 2.345 << std::endl; // Double
}
};
class Derived3 : public Base
{
public:
virtual void Print()
{
std::cout << "String" << std::endl; // String
}
};
int main(void)
{
// Make a "generic list" by storing pointers to a base interface
std::list<Base*> GenericList;
GenericList.push_back(new Derived1());
GenericList.push_back(new Derived2());
GenericList.push_back(new Derived3());
std::list<Base*>::iterator Iter = GenericList.begin();
while(Iter != GenericList.end())
{
(*Iter)->Print();
++Iter;
}
// Don't forget to delete the pointers allocated with new above. Omitted in example
return 0;
}
Also notice that this way you don't need to implement your own linked list. The standard list works just fine here. However, if you still want to use your own list, instead of storing a void *data;, store a Base *data;. Of course, this could be templated, but then you'd just end up with the standard again.
Read up on polymorphism to learn more.