To take in a string (including spaces) and write it to a file, I use:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ofstream myFile("readme.txt");
string a;
getline(cin, a);
myFile << a;
myFile.close();
}
But should I be managing the memory assigned to the string, and if so what's the easiest way?
No, std::string manages its own memory.
No, you don't need to. Unlike C (where strings are pointers to arrays that have to be managed), The std::string class is an object which manages its own memory. The memory for a is released correctly when the variable a goes out of scope at the end of the program.
As others have stated, std::string (a d every other STL container, for that matter) manages its own memory, and will be freed when it goes out of scope. If you want more control over when it goes out of scope, you can do this:
int main()
{
ofstream myFile("readme.txt");
{
string a;
getline(cin, a);
myFile << a;
} // <-- string is freed here
// do other things...
}
In C++ string template class provided in is a typedef for std::basic_string<char> and it manages the memory dynamically. So you shouldn't. You have still options however to help this class in this task. String provides for this purpose appropriate interface, for example
void reserve( size_type new_cap = 0 );
Informs a std::basic_string object of a planned change in size, so
that it can manage the storage allocation appropriately.
Related
I'm having a data abort exception in my code. It is very likely I am doing a very bad operation with chars. This code seems to work, but I wonder if it is actually invalid. The question is, what happens if you copy the data of one struct to another with char arrays involved. How is the data copied?
I have two functions, one which will purposefully leak, because I want to also know what happens if the struct created with new lives on purposefully, but the struct whose data it copied goes out of scope.
// Example program
#include <iostream>
#include <string>
#include "string.h"
typedef struct {
char name[12];
char stupid[12];
int hello;
} tFile;
void CopyFileAndDelete(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
delete file2;
}
void CopyFileAndLeak(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
}
int main()
{
tFile file1;
memset(&file1, 0, sizeof file1);
file1.hello = 22;
snprintf(file1.name, 12, "%s", "hellogoodfriendhwoareyou");
snprintf(file1.stupid, 12, "%s", "greate");
CopyFileAndDelete(&file1);
CopyFileAndLeak(&file1);
}
Other than this code being generally unsafe and more C than C++, it's correct (other than the leak.) There is no way this can produce an exception (unless new throws due to memory allocation failure.)
Arrays inside structs will be copied as you'd expect. The compiler will generally do a memcpy() to copy them (or a special memcpy-like built-in to optimize the copy operation.)
This isn't code you should write though. Use std::string instead. Don't use new and delete, use value types instead. If you really need to allocate, use unique_ptr or shared_ptr to do it.
Don't write code like this in C++ :-)
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
#include <iostream>
#include<string.h>
using namespace std;
char *rt()
{
char a[20];
strcpy(a,"I am a beginner");
cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
cout<<endl;
cout<<a;
return 0;
}
Here I have made a short program for understanding the same....I was expecting the output to be as
I am a beginner
I am a beginner
UPDATE:
But it turned out to be
I am a beginner
ëóG
I have read many articles and post but I am not able to understand their complex language....so I will appreciate a no-nonsense answer ( for a stupid...like me!!)
UPDATE:
Actually, there is one question in my assignment which goes like this
class COMPUTER
{
char chiptype[10];
int speed;
public:
void showdetails()
{
cout<<chiptype;
cout<<"\t"<<speed;
}
void getdetails()
{
cin.getline(chiptype,10);
cin>>speed;
}
};
Here the data has to be read and stored into a binary file....and the records having chiptype as "CD" are to be displayed.
Now my question is that...as the variable chiptype is private so I can't use it for comparison in main()....so I thought of making a function which returned the value stored in chiptype.
And I am not allowed to use std::string as well as node implementation...
char a[20]; is allocated on stack. When the function rt() returns, the stack unwinds and a goes out of scope. Hence you do not get your desired result.
While you are on C++, may I suggest using std::string
Read the comment below:
The other trick is to wrap the array in a struct, and return the
struct. Since a struct is copyable, the array internally becomes
copyable and will not lose scope. See this answer. Then you're not
dealing with pointers at all. See this live example – PaulMcKenzie
Use std::string instead of char[]
#include <iostream>
#include<string>
std::string rt()
{
std::string a("I am a beginner");
std::cout<<a;
return a;
}
int main()
{
std::string a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
return 0;
}
In your original code char a[20] is allocated on the stack and return a; will return a pointer to a stack variable that is no longer valid when you receive it in you main() -- handling strings in c++ should generally be done using std::string as it handles all the nasty memory management that wil kill your program if you aren't careful.
If you have to use pointers and not use std::string, you would need to go the c style way with the risk of having memory leaks if you miss a step or two. The code would look something like this using c style (keeping the cout c++)
#include <iostream>
#include <strings.h>
std::string rt()
{
char *a = malloc(20); // allocate the memory on heap
strcpy(a,"I am a beginner");
std::cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
free(a); // release the memory
return 0;
}
Caution: I don't recommend that you do the above style -- in a real world application you will likely get into trouble by either forgetting to free the memory, or accidentally accessing the memory after it has been free'd
The problem is that the memory of a will be destroyed as soon as program returns from the function. I do not think you should work with dynamic memory at your level of knowledge, so I suggest you define the array outside and just modify it inside the function:
#include <iostream>
#include<string.h>
#define MAX_LENGTH 20
using namespace std;
void rt(char *a)
{
strcpy(a,"I am a beginner");
cout<<a;
}
int main()
{
char a[MAX_LENGTH];
rt(a);
cout<<endl;
cout<<a;
return 0;
}
Furthermore, you should take care that rt is not writing more than MAX_LENGTH characters.
As mentioned by other use std::string instead of char [].
std::string rt()
{
std:: string a = "I am a beginner"; // This statement is equivalent to std::string a("I am a beginner");
std::cout << a "\n";
return a;
}
Main reason of not getting the desired result is " char a[] is allocated on stack, but when function return stack become empty.
P.S : You need to include <string> in your program, to use std::string
I'm trying to learn about pointers and first class objects in C++. I'm sure the problem exists in my pointer assignments or calls. I was wondering if someone could help me to better understand pointers as well as using static variables/methods.
FirstClass.h
#pragma once
class FirstClassObject {
public: FirstClassObject();
FirstClassObject(int);
FirstClassObject(int, FirstClassObject);
static void next_attr();
static int attribute;
int num;
FirstClassObject *buffer;
FirstClassObject *next;
~FirstClassObject();
};
FirstClassObject.cpp
#include "FirstClass.h"
#include <stdlib.h>
#include <string>
using namespace std;
FirstClassObject::FirstClassObject(){
num = attribute;
next_attr();
};
FirstClassObject::FirstClassObject(int attr){
num = attr;
next_attr();
}
FirstClassObject::FirstClassObject(int attr, FirstClassObject object){
num = attr;
next_attr();
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
next = buffer;
}
void FirstClassObject::next_attr(){
attribute++;
}
FirstClassObject::~FirstClassObject(){
free(buffer);
free(next);
}
FirstClassObject_test.cpp
#include "FirstClass.h"
#include <iostream>
using namespace std;
int FirstClassObject::attribute = 0;
FirstClassObject get_next_object(FirstClassObject object){
FirstClassObject next_object;
next_object.buffer = object.next;
return next_object;
}
int main(){
FirstClassObject object;
FirstClassObject otherobject(4, object);
cout << get_next_object(otherobject).num << "these numbers should be the same " << object.num << '\n';
return 0;
}
Thanks in advance.
First and foremost, this is wrong:
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
malloc() is not the same as new[].
Your FirstClassObject type is a non-POD type since it has a non-trivial destructor. This means you cannot properly construct it using malloc(). All malloc() does is allocate memory, and that's it. You need to actually construct a FirstClassObject object, and to do that using dynamically, you use new[ ].
Secondly, malloc() requires the number of bytes to allocate. What is sizeof(FirstClassObject)? I bet it isn't 5 (the argument you gave to malloc()). But the main point is that even if you gave malloc() the correct number of bytes, you aren't properly constructing your objects by using it.
Third, because FirstClassObject is non-POD, usage of memcpy() is also not good. In short, memcpy() does not copy objects. To copy an object, you invoke the copy constructor.
It looks like you're reading C language books and/or reading C language resources, not C++ books and resources. If you are, put down the C for a bit and learn C++ from the proper sources. If you attempt to mix C with C++ (without the proper experience), you wind up with issues such as your example.
First:
buffer = (FirstClassObject*) malloc(5)
This allocates a buffer of size 5, not 5 FirstClassObject. To do this, you need to do something like:
buffer = (FirstClassObject*) malloc(5*sizeof(FirstClassObject));
Second:
memcpy(buffer,&object,1);
This copies only 1 byte out of your object struct. Not a complete object. Here, sizeof is your friend as well although it is dangerous as receiving buffer is not a fully constructed object.
Then this line:
next_object.buffer = object.next;
would do member to member copy(providing it compiled as you are trying to affect an object to a pointer) effectively writing pass the boundary of your previously under-allocated buffer giving you the assert.
I was going through these two class implementations and found out that the strstream class is deprecated.
And if I use the stringstream class as replacement, then there is big difference between how they log in the buffer since the stringstream class object maintains a deep copy of the buffer.
Has anyone faced any problem while replacing strstream with stringstream class?
What would be the output of this code and why?
#include<iostream>
#include <sstream>
#include <strstream>
int main(){
char strArr[] = "Soheb Khan is great";
char stringArr[] = "TurboCharging";
std::strstream strStream(strArr,19);
std::stringstream stringStream(std::string(stringArr,19));
std::cout<<"Before Modification strArr= "<<strArr<<" & stringArr= "<<stringArr<<std::endl;
strStream << "Fifa 2012 is nice";
stringStream << "Sometimes its sucks";
std::cout<<"After Modification strArr= "<<strArr<<" & stringArr= "<<stringArr<<std::endl;
return 0;
}
The classes from <strstream> are hideous to use. When they were more popular I haven't seen any correct production used (well, they got corrected when I spotted the problems). Either people didn't terminate the string using std::ends or they didn't release the memory using s.freeze(0) (or, most often, both). Although the <sstream> class do create a copy I haven't found this to be a problem.
In case memory allocation actually matters for your use case, either because you need to allocate large chunks or because you have many of them, you can take control easily and have data read from or written to buffers you provide using a custom stream buffer. For example, a stream buffer writing to a readily allocate chunk of memory is trivial to write:
struct omembuf
: std::streambuf {
{
omembuf(char* base, std::size_t size) {
this->setp(base, base + size);
}
char* begin() const { return this->pbase(); }
char* end() const { return this->pptr(); }
};
Here is what I am trying to do:
1) Open an ofstream object in my main body. I can do this no problem.
2) Associate this object with a filename. No problem.
3) Pass this object to a class and send output within this class. I can't do this.
Here is my code. I would appreciate any help. Thanks!
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
public:
Object(ofstream filein);
} Object;
Object::Object(ofstream filein)
{
filein << "Success";
}
int main (int argc, char * const argv[])
{
ofstream outfile;
outfile.open("../../out.txt");
Object o(outfile);
outfile.close();
return 0;
}
You must pass stream objects by reference:
Object::Object( ofstream & filein )
{
filein << "Success";
}
And why are you using a typedef on the class? It should look like this:
class Object
{
public:
Object(ofstream & filein);
};
It is worth mentioning, that in c++0x you will have another options (besides passing by reference or by pointer):
std::move. Streams are not copyable, but you will be able to move them into another place (it depends if streams will implement the move operator, but they probably will).
unique_ptr. Streams are not copyable. When using pointers, a risk of resource leak arises. Using shared_ptr incorporates unnecessary costs when you want to have streams stored in a collection, and nowhere else. Unique_ptr solves this. You will be able to store streams in a collection in safe and efficient way.