error when trying class with linked list c++ - c++

I am trying out simple class and linked list implementation.
Please help me out with this code as i am receiving
"list iterator not dereferencable"
when running the code.
Thanks
#include<iostream>
#include<list>
#include<string>
using namespace std;
class Car
{
public:
void getType(string x)
{
type = x;
}
string showType()
{
return type;
}
private:
string type;
};
void main()
{
string p;
list<Car> c;
list<Car>::iterator curr = c.begin();
cout << "Please key in anything you want: ";
getline(cin, p);
curr->getType(p);
cout << "The phrase you have typed is: " << curr->showType() << endl;
}

Write the following way
cout << "Please key in anything you want: ";
getline(cin, p);
c.push_back( Car() );
list<Car>::iterator curr = c.begin();
curr->getType(p);
And it is much better to rename the member function getType to setType.:)
Take into account that the function main without parameters shall be declared like
int main()
^^^

You didn't insert anything into your list. So the iterator is not valid, it's pointing to c.end() and dereferencing it is undefined behaviour.
Instead add a Car to your list before you get the begin iterator.
#include<iostream>
#include<list>
#include<string>
using namespace std;
class Car
{
public:
void setType(const string& x)
{
type = x;
}
string showType()
{
return type;
}
private:
string type;
};
int main()
{
string p;
list<Car> c;
c.push_back(Car{});
auto curr = c.begin();
cout << "Please key in anything you want: ";
getline(cin, p);
curr->setType(p);
cout << "The phrase you have typed is: " << curr->showType() << endl;
}

Related

Getting and error when I try to call my class template function from main

I'm getting the below error when try to call my function add() from the main.
C:\studies\NMB1231_Question5\main.cpp:25:23: error: no matching function for call to 'Dictionary<std::vector<int>, std::vector<std::__cxx11::basic_string<char> > >::add(int&, std::__cxx11::string&)'
.h file
#include <vector>
#include <string>
#include <iostream>
using namespace std;
template <class A,class B>
class Dictionary
{
public:
Dictionary();
void add(A key, const B &value);
B find (A key) const;
void display();
private:
vector<A> keys;
vector<B> values;
};
.cpp
#include "Dictionary.h"
#include <vector>
#include <iostream>
using namespace std;
template <class A,class B>
Dictionary<A,B>::Dictionary()
{
//nothing to do, vector member variables are empty on declaration
};
template <class A,class B>
void Dictionary<A,B>::add(A key, const B &value)
{
keys.push_back(key);
values.push_back(value);
}
template <class A,class B>
B Dictionary<A,B>::find (A key) const
{
B value = " ";
for (unsigned int i = 0; i < keys.size(); i++)
if (key == keys[i])
value = values[i];
if (value == " ")
return "no such key can be found";
else return value;
}
template <class A,class B>
void Dictionary<A,B>::display()
{
for (unsigned int i = 0; i < keys.size(); i++)
cout << keys[i] << ' ' << values[i] << endl;
return;
}
main
#include <iostream>
#include <cstdlib>
#include "Dictionary.h"
#include <vector>
using namespace std;
int main()
{
Dictionary <vector<int>, vector<string > > part1;
string part;
int key;
//add 4 values to the parts dictionary
for (int i = 0; i <= 3; i++)
{
cout << "Please enter a part name and a key to add to the parts dictionary." << endl;
cout << "Part name: ";
getline(cin, part);
cout << "Key for part name: ";
cin >> key;
part1.add(key,part);
cin.get();
}
cout << endl;
part1.display();
cout << endl;
//find the part for a key
cout << "For which key do you want to find the part? ";
cin >> key;
cout << "The part for key " << key << " is ";
cout << part1.find(key) << endl;
// cout << parts.find(100002);
return 0;
}
In main, you are declaring your part1 variable as Dictionary<vector<int>, vector<string>>. So its A template parameter is vector<int> and its B template parameter is vector<string>.
Dictionary::add() takes instances of A and B as parameters. So, in this case, add() is expecting a vector<int> in its 1st parameter and a vector<string> in its 2nd parameter. But main is passing an int and a string instead. That is why you are getting the error.
You need to declare part1 as Dictionary<int, string> instead.
That being said, there are other problems with your code.
Dictionary::add() does not look for an existing key before pushing the input into the vectors. If the key already exists, you should replace the existing entry with the new value, otherwise push the new key and value. By definition, a dictionary should not contain duplicate keys.
Dictionary::find() does not compile when B is not std::string or const char*. Also, if it can't find the specified key it should either return a default-constructed B, or throw an exception.
You really should be using std::(unordered_)map instead of std::vector. Let it handle the key/value management for you.
You can't implement a template class in separate .h/.cpp files (not the way you are trying to do, anyway).

Passing array of strings to a function

I am trying to create a program that uses class, arrays, and functions to show information about two students(Name, id#, classes registered). The part I am struggling with is passing arrays to a function. How do I do that?
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Student // Student class declaration.
{
private:
string name;
int id;
string classes;
int arraySize;
public:
void setName(string n)
{
name = n;
}
void setId(int i)
{
id = i;
}
void setClasses(string c, int num)
{
classes = c;
arraySize = num;
}
string getName()
{
return name;
}
int getId()
{
return id;
}
void getClasses()
{
for (int counter=0; counter <arraySize; counter++) {
cout << classes[counter] << endl;
}
}
};
int main()
{
//Student 1
string s1Name = "John Doe";
int s1Id = 51090210;
int const NUMCLASSES1 = 3;
string s1Classes[NUMCLASSES1] = {"C++","Intro to Theatre","Stagecraft"};
//Student 2
string s2Name = "Rick Harambe Sanchez";
int s2Id = 666123420;
int const NUMCLASSES2 = 2;
string s2Classes[NUMCLASSES2] = {"Intro to Rocket Science","Intermediate Acting"};
//
Student info;
info.setName(s1Name);
info.setId(s1Id);
//info.setClasses(s1Classes, NUMCLASSES1);
cout << "Here is Student #1's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
info.setName(s2Name);
info.setId(s2Id);
// info.setClasses(s2Classes, NUMCLASSES1);
cout << "\n\nHere is student #2's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
return 0;
}
The usual way to pass around variable-length lists in C++ is to use an std::vector. A vector is a single object that you can easily pass to a function, copying (or referencing) its contents. If you are familiar with Java, it's basically an ArrayList. Here is an example:
#include <vector>
#include <string>
using namespace std;
class foo {
private:
vector<string> myStrings;
public:
void setMyStrings(vector<string> vec) {
myStrings = vec;
}
}
//...
foo myObj;
vector<string> list = {"foo","bar","baz"};
myObj.setMyStrings(list);
If don't want to use the standard library though, you can pass an array C-style. This involves passing a pointer to the first element of the array, and the length of the array. Example:
void processStrings(string* arr, int len) {
for (int i = 0; i < len; i++) {
string str = arr[i];
//...
}
}
string array[] = {"foo","bar","baz"};
processStrings(array, 3); // you could also replace 3 with sizeof(array)
Passing raw arrays like this, especially if you wanted to then copy the array into an object, can be painful. Raw arrays in C & C++ are just pointers to the first element of the list. Unlike in languages like Java and JavaScript, they don't keep track of their length, and you can't just assign one array to another. An std::vector encapsulates the concept of a "list of things" and is generally more intuitive to use for that purpose.
Life lesson: use std::vector.
EDIT: See #nathanesau's answer for an example of using constructors to initialize objects more cleanly. (But don't copy-paste, write it up yourself! You'll learn a lot faster that way.)
You can pass array of any_data_type to function like this
void foo(data_type arr[]);
foo(arr); // If you just want to use the value of array
foo(&arr); // If you want to alter the value of array.
Use std::vector. Also, don't add functions you don't need. Here's an example of using std::vector
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class Student // Student class declaration.
{
private:
vector<string> classes;
string name;
int id;
public:
Student (const vector<string> &classesUse, string nameUse, int idUse) :
classes (classesUse),
name (nameUse),
id (idUse)
{
}
void print ()
{
std::cout << "Name: " << name << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Classes: ";
for (int i = 0; i < classes.size (); i++)
{
if (i < classes.size () - 1)
{
std::cout << classes[i] << ", ";
}
else
{
std::cout << classes[i] << std::endl;
}
}
std::cout << std::endl;
}
};
int main()
{
Student John ({"C++","Intro to Theatre","Stagecraft"},
"John",
51090210);
John.print ();
Student Rick ({"Intro to Rocket Science","Intermediate Acting"},
"Rick",
666123420);
Rick.print ();
return 0;
}
Name: John
Id: 51090210
Classes: C++, Intro to Theatre, Stagecraft
Name: Rick
Id: 666123420
Classes: Intro to Rocket Science, Intermediate Acting
In the private variables of class Student, you are storing a string:
String classes;
where as you should be storing an array of strings like:
String classes[MAX_NUM_CLASSES];
then in the set classes function, pass in an array of strings as the first argument, so it should be :
void setClasses(string[] c, int num)
{
classes = c; //not sure if simply setting them equal will work, rather copy entire array using a for loop
arraySize = num;
}
This should point you in the right direction
Also, use std::vector instead of string[], it will be easier.

C++ Initializing and Functions from Derived Class from Vector of Pointer Base

I have a problem where I have 2 classes, Word and Noun. Noun is derived from Word.
All Words and Nouns are to be stored in a single vector hence why I require it being in pointer.
The problem is I can't seem to initialize or call functions from the derived class Noun.
I can pushback for a new Word but not for a Noun.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Word{
protected:
string wordName, def, type;
public:
Word();
Word(string wordName, string def, string type) {
this->wordName = wordName;
this->def = def;
this->type = type;
};
void getWord() {
cout << wordName << endl;
}
void getDef() {
cout << def << endl;
}
void getType() {
cout << type << endl;
}
};
class Noun : public Word{
public:
Noun();
Noun(string wordName, string type, string def);
};
int main(){
vector <Word*> wordVector;
for (int i = 0; i < 2; i++)
{
string wordName, def, type;
cin >> wordName;
cin >> def;
cin >> type;
cout << endl;
wordVector.push_back(new Noun(wordName, def, type)); //new Word(wordName, def, type) works
}
for (int i = 0; i < 2; i++)
{
wordVector[i]->getWord(); //how do you call the function from Noun?
wordVector[i]->getDef();
wordVector[i]->getType();
}
system("pause");
return 0;
}
It comes out with 1 unresolved external symbol.
There are too many things wrong with this code, so allow me to present a correct, complete rewrite that does what you mean:
#include <iostream>
#include <memory> // for std::unique_ptr
#include <string>
#include <vector>
class Word
{
private:
std::string wordName, def, type;
public:
virtual ~Word() = default;
Word(std::string w, std::string d, std::string t)
: wordName(std::move(w))
, def(std::move(d))
, type(std::move(t)) {}
void printWord() const { std::cout << wordName << '\n'; }
void printDef() { std::cout << def << '\n'; }
void printType() const { std::cout << type << '\n'; }
};
class Noun : public Word
{
public:
using Word::Word;
};
int main()
{
std::vector<std::unique_ptr<Word>> wordVector;
for (int i = 0; i != 2; ++i)
{
std::string w, d, t;
if (!(std::cin >> w >> d >> t))
{
std::cerr << "Failed to read input!\n";
continue;
}
wordVector.push_back(std::make_unique<Noun>(
std::move(w), std::move(d), std::move(t)));
}
for (const auto& wp : wordVector)
{
wp->printWord();
wp->printDef();
wp->printType();
}
}
A completely unsorted and incomplete set of issues that I corrected:
Memory management (std::unique_ptr)
Virtual destructor for deletion through base
No nonsensical default constructors
Inheriting constructors rather than manual forwarding
Properly named member functions
Const correctness
No superfluous semicolons
No superfluous std::endl
Not abusing namespace std
Range-based for loop
I/O error handling
Initialize rather than assign
Enable move optimizations
No raw new
Correct access level for private members (exposed via member functions)
I think you just forgot to initialize the superclass constructor In your Noun class try this
class Noun : public Word{
public:
Noun();
Noun(string wordName, string type, string def): Word(wordName, type, def){};
};
I have tested it and it worked.
Also theres a light modification in you main(). just a slight. so that i can see what input it is asking for.
int main(){
vector <Word*> wordVector;
for (int i = 0; i < 2; i++)
{
string wordName, def, type;
cout<< "entere name";
cin >> wordName;
cout<< "entere def";
cin >> def;
cout<< "entere type";
cin >> type;
cout << endl;
wordVector.push_back(new Noun(wordName, def, type)); //new Word(wordName, def, type) works
}
for (int i = 0; i < 2; i++)
{
wordVector[i]->getWord(); //how do you call the function from Noun?
wordVector[i]->getDef();
wordVector[i]->getType();
}
system("pause");
return 0;
}

program for show the detail of the student as like name fathername roll no cgpa on output

#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
struct student
{
string::name(20)
string::fathername(20)
int rollno;
float cgpa;
{
student s1,s2;
s1.name ='ali';
s1.fathername='akram';
s1.rollno=1;
s1.cgpa=2.2;
cout<<s1.name<<endl;
cout<<s1.fathername<<endl;
cout<<s1.rollno<<endl;
cout<<s1.cgpa<<endl;
getch();
}
this program give me error when i use parameter in program this program give me thre error when use parameter why?
#include<iostream>
#include<string>
using namespace std;
int main()
{
struct student
{
string name;
string fathername;
int rollno;
double cgpa;
};
student s1, s2;
s1.name = "ali";
s1.fathername = "akram";
s1.rollno = 1;
s1.cgpa = 2.2;
cout << s1.name << endl;
cout << s1.fathername << endl;
cout << s1.rollno << endl;
cout << s1.cgpa << endl;
getchar();
return 0;
}
Your code has got a several errors. First of all I do not see a reason why you added , second important thing is that you should format your code, instead of using string::name(20); simply use string name;,third is that you have to put ; when you are ending a struct.

dynamic object creation in c++?

If my class name is TEST i want to create an object of TEST class having name given by the user during run time??
i tried this-
#include<iostream>
#include<string.h>
#include<conio.h>
using namespace std;
class TEST
{
void end()
{
cout<<"Hi";
}
};
int main()
{
string name;
cout<<"Give a object name";
cin>>name;//taking name from user
TEST name;//here i am getting error while creating object of TEST class
return 0;
}
It's not clear exactly what you are trying to do here, except perhaps learning basic c++ constructs. Here is some code to get you going.
#include <iostream>
#include <string>
#include <map>
using namespace std;
class TEST
{
public:
//Constructor - sets member string to input
TEST( string input ) : _name( input )
{
}
//Destructor called when object goes out of scope
~TEST()
{
cout << "Hi from destructor" << endl;
}
//Variable stored by the class
string _name;
};
int main()
{
string inputString;
cout << "Give a object name";
cin >> inputString;
// Give name to your class instance through the constructor
TEST foo( inputString );
// Store a copy of the object "foo" in a map that can be referenced by name
map< string, TEST > userNamedObjects;
userNamedObjects.insert( { inputString, foo } );
// Access the object's data based on user input name
cout << "From map: " << userNamedObjects.at( inputString )._name << endl;
// Sanity check
cout << foo._name << endl;
// Or set it directly
foo._name = "Patrick Swayze";
cout << foo._name << endl;
// The stored object doesn't change, because it's a copy
cout << "From map: " << userNamedObjects.at( inputString )._name << endl;
return 0;
}