I've narrowed my code down, and I found the source of the problem, it's when I open a file.
The file does exists, and I don't get any warning or errors when compiling.
int main(int argc, const char* args[])
{
cout << "Wellcome" << endl;
cout << args[1];
ifstream exists(args[1]);
if(!exists)
{
printf("FILE NOT FOUND");
return 1;
}
exists.close();
ifstream* in;
in->open(args[1],ios::binary|ios::in);
//do stuff
in->close();
return 0;
}
You have created a pointer to an ifstream object, but you never allocated an ifstream for it to point to. To fix this, consider just stack-allocating it:
ifstream in;
in.open(args[1],ios::binary|ios::in);
//do stuff
in.close();
In general, you usually don't need to dynamically allocate objects unless you want them to outlive the function that created them.
Hope this helps!
Related
first time here. I am a student doing some c++ coding for end year project. The programme that I coded does not read the text file even though everything seems to be in order. Some helps would be fantastic!
void transactionRecords(double total, char answer, string nameT, int HpNo, string address)
{
fstream myFile;
string name;
char idStatus;
double amt, sumAll=0;
myFile.open("transaction.txt",fstream::in);
if (!myFile) cout<<"Unable to Open File under Input Mode";
else
{
while (!myFile.eof())
{
myFile>>name>>idStatus>>address>>HpNo>>amt;
if (myFile.fail()) break;
}
myFile.close();
myFile.open("transaction.txt",fstream::app);
if (!myFile) cout<<"Unable to Open File under App Mode";
else
{
myFile<<nameT<<" "<<answer<<" "<<address<<" "<<HpNo<<" "<<total<<endl;
if (myFile.fail()) cout<<"Error encountered while adding data!\n";
}
}
myFile.close();
}
this is whats in the text file
Johns Y pasir_ris 81231211 4.14
First, I suggest you use the RAII principle when creating files that is:
void myfunction() {
ifstream f{"file.txt"};
// your logic here
// NB -- no need to manually close file, prevents resource leaks
}
There is no need to manually close or open such a file, it is opened by the constructor and closed when the destructor is invoked upon exiting the current scope. This prevents leaks of file handles and is a pervasive technique in C++.
Second, use the standard stream read loop in C++:
while (myFile>>name>>idStatus>>address>>HpNo>>amt) {
// your logic here, the read has succeded
// TODO process myFile, name, idStatus etc.
}
With these changes, your example should look something like:
void transactionRecords(double total, char answer, string nameT, int HpNo, string address)
{
ifstream myFile{"transaction.txt"};
string name;
char idStatus;
double amt, sumAll=0;
if (!myFile) cout<<"Unable to Open File under Input Mode";
return;
while (myFile>>name>>idStatus>>address>>HpNo>>amt) {
// TODO do something here??
}
ofstream tFile{"transaction.txt"};
if (!myFile) cout<<"Unable to Open File under App Mode";
return;
if (!(tFile<<nameT<<" "<<answer<<" "<<address<<" "<<HpNo<<" "<<total<<endl)) {
cout<<"Error encountered while adding data!\n";
}
}
}
You should probably do something in the TODO block, currently you are only storing the last values read? If you only mean to process one line from the file, swap the while loop with an if.
I tried making a program earlier that tells the user then number of char, words, and lines in a text file. I made functions to determine the numbers of each, yet I was passing them by value. This resulted in an error since after reading the number of char it would be at the end of the file and then output zero for the other two. Now I cant seem to rewrite my functions so that the file is open and closed each time its checked for char, words, and lines. Any one see where my errors are?? Thanks! (just copied and pasted one of my functions for now).
int num_of_lines(ifstream file)
{
string myfile;
myfile = argv[1];
ifstream l;
l.open(myfile);
int cnt3 = 0;
string str;
while(getline(file, str))cnt3++;
l.close();
return(cnt3);
}
int main(int argc, char **argv)
{
int num_of_char(ifstream file);
string file;
file = argv[1];
if(argc == 1)die("usage: mywc your_file");
ifstream ifs;
ifs.open(file);
if(ifs.is_open())
{
int a, b, c;
a = num_of_lines(ifs);
cout <<"Lines: " << a << endl;
}
else
{
cerr <<"Could not open: " << file << endl;
exit(1);
}
ifs.close();
return(0);
}
There is no way to "reopen" a file other than knowing the name and creating a new ifstream, but you can use the seekg member function to set your read position in the file, and setting it to 0 will have the next read operation start from the beginning of the file.
A stream is not possible to copy, so you can't pass it "by value", but must pass it by reference.
int num_of_lines(ifstream &file)
{
int count = 0;
string str;
while (getline(file, str)) {
count++;
}
file.seekg(0);
return count;
}
For the full problem, I agree with Mats Petersson, though. Counting both characters, lines and words in one pass will be much more efficient than reading through the file three times.
#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <sstream>
using namespace std;
class CFile {
public:
CFile(string filename);
~CFile();
void ReadFile();
void WriteFile(string outputFilename);
void Calculate();
string m_filename;
int m_numberInput;
double* m_xData;
double* m_yData;
int m_numberOutput;
double* m_xDataOut;
double* m_yDataOut;
};
CFile::CFile(string filename)
{
m_filename = filename;
string line;
ifstream myfile(m_filename.c_str());
if (myfile.is_open())
{
getline(myfile,line);
myfile.close();
stringstream Str;
Str << line;
Str >> m_numberInput;
m_xData = new double[m_numberInput];
m_yData = new double[m_numberInput];
cout << sizeof(m_xData) / sizeof(m_xData[0]) << endl;
}
else cout << "Unable to open file.\n";
}
CFile::~CFile()
{
delete[] m_xData;
delete[] m_yData;
m_xData = 0;
m_yData = 0;
delete[] m_xDataOut;
delete[] m_yDataOut;
m_xDataOut = 0;
m_yDataOut = 0;
}
void CFile::ReadFile()
{
ifstream infile(m_filename.c_str());
string line;
if (infile.is_open())
{
int x, y, i = 0;
while (getline(infile,line))
{
infile >> x >> y;
m_xData[i] = x;
m_yData[i] = y;
i++;
}
infile.close();
}
else cout << "Unable to open file.\n";
}
void CFile::WriteFile(string outputFilename)
{
ofstream outfile(outputFilename.c_str());
if (outfile.is_open())
{
for(int i=0; i < m_numberInput; i++)
outfile << m_xDataOut[i] << " " << m_yDataOut[i] << endl;
outfile.close();
}
else cout << "Unable to open file.\n";
}
void CFile::Calculate()
{
m_xDataOut = new double[m_numberInput];
m_yDataOut = new double[m_numberInput];
for(int i=0; i < m_numberInput; i++)
{
m_xDataOut[i] = m_xData[i];
m_yDataOut[i] = sqrt(m_yData[i]);
}
}
int main()
{
CFile file("Input.dat");
file.ReadFile();
file.Calculate();
file.WriteFile("Output.dat");
file.~CFile();
}
The error message is as follows:
main(11915,0x7fff77d3d310) malloc: *** error for object 0x7f8a99403940: pointer
being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This is code which ironically worked well some weeks ago. I change OS and compilers and now it doesn't anymore. I read about this error in other threads, but couldn't really understand how to use the solutions on my code. The code reads in a data file, does sth. with it and then writes the changed values into another file.
Where is the allocation error?
Thank you very much in advance for your help! :-)
Your Destructor is called twice. You call it explicitly, and it is also called when exiting main(). You should remove your explicit destrcutor call.
Two problems:
You don't necessarily initialise all four pointers, in which case it's not safe to apply delete to them. You can fix this by initialising them to null before doing anything; or, better still, replace them with std::vector<double> so you don't have to mess around with delete at all. That will also fix the class's invalid copy semantics (it breaks the Rule of Three) and the potential memory leaks if construction fails.
You're calling the destructor manually (file.~CFile(), at the end of main). Don't do that: the destructor is called automatically when the program leaves the variable's scope, and it's an error to call it twice.
As #claptrap pointed out your memory managements were also buggy.
You should migrate to std::vector<double> rather than raw double arrays and pointers. You can think of vec.resize(N) as a variant of new double[N] which never needs an explicit delete[].
If you are on Linux, it's a good practice to run your program under valgrind which automatically traces memomry allocations/deallocations and points out any invalid memory operations. I bet your Linux distro has a pre-compiled package for it.
http://valgrind.org/docs/manual/quick-start.html
This here is causing the issue
delete[] m_xDataOut;
delete[] m_yDataOut;
you have not initialized the pointers in your constructor
I have built a .cpp program in order to write some content to a .txt file created within the .cpp file.
I manage to write the desired content, however, when I am trying to open the created file from terminal, it says that it cannot find it although it is there.
When I try to open it with vi or nano it's content it's empty. It is like creating a new file.
However, when I open it outside terminal, I can see its content as I wanted.
What could be the problem and how can I fix this situation?
Bellow, I have added the code.
The problem is with the system(buffer) command. I receive the following error: sh: cannot open video2.txt: No such file. I have tried to opened the files from command prompt and I get the above described situation.
int main(int argc,char* argv[])
{
fstream RawStipFile;
RawStipFile.open(strcat(argv[1],".txt"));
string line;
if (RawStipFile.is_open())
{
getline(RawStipFile, line);
int i = 0;
ofstream OutVideoStip;
ofstream VideoList;
VideoList.open("VideoList.txt");
while ( RawStipFile.good() )
{
getline (RawStipFile,line);
char* l;
l = (char*) malloc(sizeof(char));
l[0]=line[0];
//cout<<line[0]<<endl;
if (line[0]==35)
{
if (OutVideoStip.is_open())
{
OutVideoStip.close();
}
i++;
//char* base;
//base = (char*) malloc(1000*sizeof(char));
//sprintf(base, "%d", i);
char* b;
b = &line[1];
VideoList<<b<<endl;
OutVideoStip.open(strcat(b, ".txt"));
}
else
{
OutVideoStip << line << endl;
}
}
OutVideoStip.close();
RawStipFile.close();
VideoList.close();
}
else
{
cout << "Unable to open file \n";
}
fstream VideoNames;
VideoNames.open("VideoList.txt", fstream::in);
if (VideoNames.is_open())
{
while ( VideoNames.good() )
{
getline(VideoNames, line);
line=line.substr(1,line.length());
if (line.compare(""))
{
string initial = "./txt2mat<";
initial.append(line);
initial.append(".txt>");
initial.append(line);
initial.append(".dat");
cout<<initial<<endl;
const char* buffer;
buffer = initial.c_str();
system(buffer);
}
}
}
else
{
cout<<"Unable to open file. \n";
}
VideoNames.close();
return 0;
}
You are using strcat in a wrong way. I don't know if that's the cause of your problem, but it can result in undefined behavour;
int main(int argc,char* argv[])
{
fstream RawStipFile;
RawStipFile.open(strcat(argv[1],".txt"));
Here you modify argv[1]. You append 4 characters to it, without allocating any memory.
string line;
...
char* b;
b = &line[1];
VideoList<<b<<endl;
OutVideoStip.open(strcat(b, ".txt"));
a string takes care of it's own memory management. You can't asume it has reserved 4 more bytes for you to append. If you need to append, use string member functions, not strcat.
just a loose guess: the current working directory is not the same?
Try either using chdir first or opening by absolute path /home/simon/VideoList.txt
I'm very new to the world of C++ error handling, but I was told here:
Checking for file existence in C++
...that the best way to checks for file existence was with a try-catch block. From my limited knowledge on the topic, this sounds like sound advice. I located this snippet of code:
http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/Readafileintrycatchblock.htm
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
try{
char buffer[256];
ifstream myfile ("test.txt");
while (! myfile.eof() )
{
myfile.getline (buffer,100);
cout << buffer << endl;
}
}catch(...){
cout << "There was an error !\n";
}
return 0;
}
...but when I compile it using
g++ -Wall -pedantic -o test_prog main.cc
And run the program in a directory where test.txt does not exist, the prog keeps spitting out empty lines to the terminal. Can anyone figure out why?
Also is this a good way to check for file existence for a file you actually want to open and read from (versus just something where your indexing a bunch of files and checking them over)?
Thanks!
In C++ iostreams do not throw exeptions by default. What you need is
ifstream myfile("test.txt");
if(myfile) {
// We have one
}
else {
// we dont
}
By default the fstream objects do not throw. You need to use void exceptions ( iostate except ); to set the exception behavior. You can fetch the current settings using iostate exceptions ( ) const;. Change your code just a bit:
#include <fstream>
#include <iostream>
#include <stdexcept>
using namespace std;
int main ()
{
try{
char buffer[256];
ifstream myfile ("test.txt");
myfile.exceptions ( ifstream::eofbit | ifstream::failbit | ifstream::badbit );
while (myfile)
{
myfile.getline (buffer,100);
cout << buffer << endl;
}
myfile.close();
}catch(std::exception const& e){
cout << "There was an error: " << e.what() << endl;
}
return 0;
}
First of all, for the try block to do any good, you need to enable exceptions for the stream.
Second, a loop like:
while (! myfile.eof() )
Will lead to nothing but trouble, and you're seeing that here. The problem (in this case) is that when the file failed to open, eof will never be signaled -- you can't/don't reach the end of the file because there is no file. Therefore, your loop runs forever, on an existentialist search for the end of a nonexistent file. Fix the loop, and things get better in a hurry:
char buffer[256];
ifstream myfile ("test.txt");
while (myfile.getline(buffer,100))
{
cout << buffer << endl;
}
While you're at it, a bit more fixing wouldn't hurt (unless you really meant to use less than half of the space you allocated for your buffer):
char buffer[256];
ifstream myfile ("test.txt");
while (myfile.getline(buffer,sizeof(buffer)))
{
cout << buffer << endl;
}
Or, of course, eliminate the problem entirely:
std::string buffer;
ifstream myfile("test.txt");
while (getline(myfile, buffer))
cout << buffer << "\n";
Edit: note that none of these (at least currently) depends on exceptions at all. They're all set up to write a line to the output if we succeeded in our attempt at reading a line from the input. If the file didn't open, the body of the loop simply won't execute, because we won't be able to read from a file that didn't open. If we want to print an error message telling the user that the file didn't open, we'd have to handle that separately from what's above. For example:
ifstream myfile("test.txt");
if (!myfile) {
std::cerr << "File failed to open";
return FAIL;
}
while (std::getline(myfile // ...