Program crash on copy constructor - c++

I have the following code I was testing:
#include<bits/stdc++.h>
using namespace std;
class Stringtype{
char* str;
int length;
public:
Stringtype(){
str='\0';
length=0;
}
Stringtype(const Stringtype& s){
cout<<"Constructor"<<endl;
strcpy(this->str, s.str);
this->length = s.length;
}
Stringtype(char* text){
strcpy(this->str, text);
this->length = strlen(str);
}
friend ostream& operator<<(ostream& stream, Stringtype s){
stream<<"Value :"<<endl;
for(int i=0;i<s.length;i++){
cout<<(s.str)[i];
}
cout<<endl;
stream<<"Length :"<<endl;
stream<<s.length<<endl;
return stream;
}
friend istream& operator>>(istream& stream, Stringtype& s){
cout<<"Enter the string"<<endl<<endl;
s.str = new char[30];
cin>>s.str;
s.length = strlen(s.str);
return stream;
}
};
int main(){
Stringtype s1, s2;
cin>>s1>>s2;
cout<<s1<<s2;
cout<<(s1>s2)<<endl;
cout<<(s1<s2)<<endl;
cout<<(s1==s2)<<endl;
cout<<(s1+s2)<<endl;
return 0;
}
This code produces the following output (after the input is taken properly):
Constructor
and then crashes.
I can't seem to understand why...
Any help is greatly appreciated. Thank you.

You never actually reserve memory for your internal memory representation of your string. You need to have a new somewhere. Otherwise you will write to memory you don't own, which is exactly what is happening here, right in the next line after the output you observe.
By the way: there should be no copy-construction here, your signature
friend ostream& operator<<(ostream& stream, Stringtype s){
should read:
friend ostream& operator<<(ostream& stream, const Stringtype& s){
Doesn't change the fact that you have errors in your memory handling though.

Please change the following
friend ostream& operator<<(ostream& stream, Stringtype s)
to
friend ostream& operator<<(ostream& stream, Stringtype& s)
Take the reference for the string s

Try initializing str="", instead str='\0';

Related

How to new a dynamic array after cin

I'm trying to make a class that contains a pointer, which is the core of a dynamic array.
How to overload the operator >> so I can cin >> to the pointer without know how many characters are going to put?
I was trying:
#include <iostream>
class MyString
{
private:
char* str;
size_t length;
public:
//some code here
friend std::istream& operator>>(std::istream& is, const MyString& other)
{
is >> other.str;
return is;
}
}
and this happened when I try to cin a string:
HEAP CORRUPTION DETECTED
Is there a way to read a string, assign it to my string, and won't use the std::string header?
(I was trying to make a string class that doesn't depend on std::string)
A naive implementation would use is.get() to retrieve one character at a time, and append it to other, resizing if needed. And stop when std::isspace(chr) is true, of course. For that, you need to dynamically allocate memory and keep track of how much space you are using / have available in the implementation of MyString.
Here is the skeleton for that; you probably need to implement the append() method.
friend std::istream& operator>>(std::istream& is, MyString& other) {
while (true) {
int chr = is.get();
if (is.eof() || std::isspace(chr)) {
break;
}
other.append((char)chr);
}
return is;
}
#include <iostream>
#include <string.h>
class MyString
{
private:
size_t length;
char* str;
void getInput(std::istream&is)
{
char c='\0';
while(c!='\n')
{
is.get(c);
length++;
str=(char*)realloc(str, length);
if(c=='\n')
{
str[length-1]='\0';
}
else{
str[length-1]=c;
}
}
}
public:
MyString()
{
length=0;
str=new char[1];
str[0]='\0';
}
//some code here
friend std::istream& operator>>(std::istream& is, MyString& other)
{
std::cout<<"Enter String: ";
other.getInput(is);
return is;
}
void printString()
{
std::cout<<str<<std::endl;
}
~MyString()
{
delete[]str;
length=0;
}
};
int main()
{
MyString s;
std::cin>>s;
s.printString();
}

How can I read data from file to vector?

So I have this code where an object of class Group has vector with objects from class Student. I am already writing information about the students from the vector into a file but I have problem with reading this information back. How can I do that?
Here is my code so far:
class Group
{
private:
string name;
vector <Student*> studentList;
public:
~Group();
Group(void);
Group(string s);
void addStudent(string name,int age,int stNum);
void removeStudent(int stNum);
friend ostream& operator << (std::ostream& out, const Group& g) {
out << g.name << "\n";
out << g.studentList.size() << "\n";
for (unsigned i=0;i<g.studentList.size();i++) {
out<< g.studentList[i]->getStudentName()<<"\n";
out<< g.studentList[i]->getStudentAge()<<"\n";
out<< g.studentList[i]->getStudentNumber()<<"\n"<<endl;
}
return out;
}
friend istream& operator>>(std::istream& in, Group& g){
in >> g.name;
for (unsigned i=0;i<g.studentList.size();i++) {
//READ DATA FROM FILE
}
return in;
}
};
Gathering up the commentary. Note this pushes the hard part, the reading and writing, into Student and I left that bit blank. Normally I'd do it because I'm evil, but apparently in this case it is already written.
Major changes:
No Student pointers. Lest memory management overhead and better cache friendliness! By Grabthar's hammer. What a savings.
Student does the Student reading and writing.
std::vector handles the element counting so it doesn't need to be stored in and read from the output. Note: This could slow the reading down a little because you can't pre-allocate storage in the vector.
#include <string>
#include <iostream>
#include <vector>
// note the lack of using namespace std;
// it can be problematic, and especially so in a header.
class Student
{
//fill in the blanks
friend std::ostream& operator <<(std::ostream& out, const Student& s)
{
//fill in the blanks
return out;
}
friend std::istream& operator >>(std::istream& in, const Student& s)
{
//fill in the blanks
return in;
}
};
class Group
{
private:
std::string name;
std::vector<Student> studentList; // death to pointers!
public:
//~Group(); // Don't need a destructor without the pointer
Group(void);
Group(std::string s);
void addStudent(std::string name, int age, int stNum);
void removeStudent(int stNum);
friend std::ostream& operator <<(std::ostream& out, const Group& g)
{
out << g.name << "\n";
//out << g.studentList.size() << "\n"; not necessary. vector handles it.
for (std::vector<Student>::const_iterator it = g.studentList.cbegin();
it != g.studentList.cend();
++it)
{
if (!(out << *it))// let Student's << do all the work
{ // write failed. Might as well stop trying to write.
break;
}
}
return out;
}
friend std::istream& operator>>(std::istream& in, Group& g)
{
in >> g.name;
Student temp;
while (in >> temp) // let Student's >> do all the work
{
g.studentList.push_back(temp);
}
return in;
}
};

how to write operator overloading for operator [] in c++

I want to make three[0]='p'; work in the code below. I think I have to make an operator overloading for that but I don't know how to do. What I want to get is to change first index of "Lottery winner!" to 'p'. (To get "pottery winner!").
#include<iostream>
#include<cstring>
using namespace std;
class str
{
char* a;
public:
str(char *aa=""){
this->a = new char[strlen(aa)+1];
strcpy(a,aa);
}
~str(){
delete a;
}
friend ostream& operator<<(ostream &out, str &aa);
friend istream& operator>>(istream &in, str &aa);
};
ostream& operator<<(ostream &out, str &aa){
out<<aa.a;
return out;
}
istream& operator>>(istream &in, str &aa){
in>>aa.a;
return in;
}
void main(){
str three("Lottery winner!");
three[0]='p';
cout<<three<<endl;
}
This is the general signature of the operator[]:
T& operator[](any_type);
In your context it would look like this:
struct str {
...
char& operator[](std::size_t pos) {
return a[pos];
}
};
class str
{
// ...
public:
// ...
char& operator[] (int x)
{
// add array out-of-bounds check here if you like to ...
return a[x];
}
}
operator char*()
{
return a;
}
Could also work

Overloaded ostream operator error in c++

I try to overload ostream operator in a class Student as follows:
//Student.h
class Student
{
public:
Student(){}
~Student(){}
friend std::ostream& operator<< (std::ostream&,const Student&);
friend std::istream& operator>> (std::istream&,const Student&);
private:
char* snum;
};
//Student.cpp
#include "Student.h"
std::ostream& operator<< (std::ostream& output,const Student& c)
{
output<<c.snum<<", "<<c.name<<", "<<c.email<<endl;
return output;
}
std::istream& operator>> (std::istream& input,const Student& cN)
{
cout<<"Input number: ";
input>>cN.snum;
return input;
}
//main.cpp
#include "Student.h"
int main()
{
Student st;
std::cin >> st;
std::cout << st << std::endl;
return 0;
}
But when i input the snum,i get error message "Segmentation Fault".
I change char* snum; to char snum;,it return compiler error The operation "std::istream>> const char" is illegal.
Thank you for help.
You need that snum will point on allocate memory and then you can input it with data, for exemple:
char* p_var = new char[20]; // 20 bytes allocation
// ... using p_var
delete[] p_var; // Releasep_var memory
In your case, you should do the allocation in the Ctor and the release in the Dtor.
you can read this for more info:
http://www.cplusplus.com/doc/tutorial/basic_io/
tell me if your problem got solved by using below changes...
class Student
{
private:
char snum;
char name;
char email;
public:
Student(){};
~Student(){};
friend std::ostream& operator<< (std::ostream&,Student&);
friend std::istream& operator>> (std::istream&,Student&);
};
std::ostream& operator<< (std::ostream& output,Student& c)
{
output<<c.snum<<", "<<c.name<<", "<<c.email<<endl;
return output;
}
std::istream& operator>> (std::istream& input, Student& cN)
{
cout<<"Input number: ";
input>>cN.snum;
input>>cN.name;
input>>cN.email;
return input;
}
int main()
{
Student st;
std::cin >> st;
std::cout << st << std::endl;
return 0;
}
use string or char array or assign char *x some memory before using for cin...

How can I store a string of characters using friend operators?

I'm trying to create a program that uses Caesar Cipher using class inheritance, but friend operator does not let me use getline. I've tried looking up different methods of overloading getline but I'm not sure what I'm doing wrong (I've only recently stopped using the namespace std so there's probably a couple of errors there).
It's still a work in progress. I don't know if I need length, or that if those overloaded + operators will actually add extra words to an old string, for example (though I can figure that out later, I just want to know how I can use getline properly here). Any help is appreciated.
#include <iostream>
#include <string>
class Sentence{
private:
std::string codeSentence;
int length;
public:
Sentence();
Sentence(std::string codeSentence);
Sentence(const Sentence &obj);
~Sentence();
void setS (std::string codeSentence);
std::string getS() const;
Sentence & operator = (const Sentence &obj);
Sentence operator +(const Sentence &obj) const;
Sentence operator +(std::string codeSentence) const;
friend Sentence operator +(std::string codeSentence, const Sentence &obj);
friend std::ostream & operator << (std::ostream & out, const Sentence &obj);
friend std::istream & operator >> (std::istream & in, Sentence &obj);
friend std::istream & getline (std::istream & in, const Sentence & obj);
};
Sentence::Sentence(){
}
Sentence::Sentence(const Sentence &obj){
(*this) = obj;
}
Sentence::Sentence(std::string codeSentence){
this->codeSentence = codeSentence;
}
Sentence::~Sentence(){
}
void Sentence::setS(std::string codeSentence){
this->codeSentence = codeSentence;
}
std::string Sentence::getS() const{
return (this-> codeSentence);
}
Sentence & Sentence::operator=(const Sentence &obj){
this->codeSentence = obj.codeSentence;
return (*this);
}
Sentence Sentence::operator+(const Sentence &obj) const{
return (Sentence(this->codeSentence + ' ' + obj.codeSentence));
}
Sentence Sentence::operator+(std::string codeSentence) const{
return (Sentence(this->codeSentence + ' ' + codeSentence));
}
Sentence operator+(std::string codeSentence, const Sentence &obj){
return (Sentence(codeSentence + ' ' + obj.codeSentence));
}
std::istream & getline (std::istream & in, const Sentence & obj){
if (in >> obj.length)
getline(in, obj.codeSentence);
return (in);
}
std::istream & operator >> (std::istream & in, Sentence &obj){
in.getline(obj.codeSentence, sizeof(obj.codeSentence));
return (in);
}
The issue with getLine is that you're modifying the Sentence which is passed in as const. Just take away the const; you WANT to modify it after all.