I'm having an issue when running the code below. Every time I set the while loop to reach the .eof() it returns a std::bad_alloc
inFile.open(fileName, std::ios::in | std::ios::binary);
if (inFile.is_open())
{
while (!inFile.eof())
{
read(inFile, readIn);
vecMenu.push_back(readIn);
menu.push_back(readIn);
//count++;
}
std::cout << "File was loaded succesfully..." << std::endl;
inFile.close();
}
It runs fine if I set a predetermined number of iterations, but fails when I use the EOF funtion. Here's the code for the read function:
void read(std::fstream& file, std::string& str)
{
if (file.is_open())
{
unsigned len;
char *buf = nullptr;
file.read(reinterpret_cast<char *>(&len), sizeof(unsigned));
buf = new char[len + 1];
file.read(buf, len);
buf[len] = '\0';
str = buf;
std::cout << "Test: " << str << std::endl;
delete[] buf;
}
else
{
std::cout << "File was not accessible" << std::endl;
}
}
Any help you can provide is greatly appreciated.
NOTE: I failed to mention that vecMenu is of type std::vector
and menu is of type std::list
The main problems I see are:
You are using while (!inFile.eof()) to end the loop. See Why is iostream::eof inside a loop condition considered wrong?.
You are not checking whether calls to ifstream::read succeeded before using the variables that were read into.
I suggest:
Changing your version of read to return a reference to ifstream. It should return the ifstream it takes as input. That makes it possible to use the call to read in the conditional of a loop.
Checking whether calls to ifstream::read succeed before using them.
Putting the call to read in the conditional of the while statement.
std::ifstream& read(std::fstream& file, std::string& str)
{
if (file.is_open())
{
unsigned len;
char *buf = nullptr;
if !(file.read(reinterpret_cast<char *>(&len), sizeof(unsigned)))
{
return file;
}
buf = new char[len + 1];
if ( !file.read(buf, len) )
{
delete [] buf;
return file;
}
buf[len] = '\0';
str = buf;
std::cout << "Test: " << str << std::endl;
delete[] buf;
}
else
{
std::cout << "File was not accessible" << std::endl;
}
return file;
}
and
inFile.open(fileName, std::ios::in | std::ios::binary);
if (inFile.is_open())
{
std::cout << "File was loaded succesfully..." << std::endl;
while (read(inFile, readIn))
{
vecMenu.push_back(readIn);
menu.push_back(readIn);
//count++;
}
inFile.close();
}
Related
I'm new to C++, and I'm trying to write a project that interacts through command line. Right now, whenever I run my main (which is the executable), I always receive a segmentation fault error when the main program finished.
Edit comment:
I'm told by tutor to use as little as C++ features such as vectors or strings ... I'm also very new to C++, so i'm trying to utilize as many basic C functions as I can.
I'm
My main function looks like this:
int main(int argc, char** argv) {
cout << "starting mvote..." << endl;
int run_flag = 1;
char* actionBuffer = (char*)malloc(100 * sizeof(char));
char* action = (char*)malloc(16 * sizeof(char));
char* readPtr;
char exit[4] = { 'e','x','i','t' };
//parse command line argumentand get the filename
char* filename = argv[2];
cout << filename;
FILE* fp;
char line[64];
//from here, I'm opening the file and read it by lines
fp = fopen(filename, "r");
if (fp == NULL) {
cout << "file not exists";
return -1;
}
while (fgets(line, 64, fp) != NULL) {
cout << line << "\n";
}
fclose(fp);
while (run_flag == 1) {
cout << "what do you want?\n " << endl;
cin.getline(actionBuffer, 1024);
if (strcmp(actionBuffer, exit) == 0) {
cout << "bye!";
run_flag = 0;
break;
}
//if not exit, Look for the space in the input
readPtr = strchr(actionBuffer, ' ');
int size = readPtr - actionBuffer;
//extract the operation
strncpy(action, actionBuffer, size);
for (int i = 0; i < size; i++) {
cout << "operation:" << action[i];
}
// depend on the operation specified before the first empty space
run_flag = 0;
}
free(actionBuffer);
free(action);
return 0;
}
Description:
I first try to open up a csv file which lies in the same folder as main, and I read the file line by line. Then, I just implement a simple command where you can type exit and quit the program.
I allocate two memory, actionBuffer and action, which are used to hold command
Problem: a segmentation fault [core dumped] always exists when I type exit and hit enter, and then the process finished.
Research: So I learned that segmentation fault is due to accessing a memory that does not belongs to me. But where in my program am I trying to access such a memory?
Any advice is appreciated! Thank you.
Just to give you an idea, this would be an example of C++ code
#include<iostream>
#include<fstream>
#include<string_view>
#include<string>
#include<sstream>
#include<exception>
int main(int argc, char** argv) {
std::cout << "starting mvote...\n";
//parse command line argumentand get the filename
std::string filename = argv[2]; // NO CHECKS!
std::cout << filename <<'\n';
//from here, I'm opening the file and read it by lines
{
std::ifstream ifs(filename);
if (!ifs) {
throw std::invalid_argument("file not exists");
}
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << '\n';
}
}
bool run_flag = true;
while (run_flag) {
std::cout << "what do you want?\n";
std::string userInput;
std::getline(std::cin, userInput);
if (userInput == "exit") {
std::cout << "bye!\n";
return 0;
}
std::stringstream userInputSs(userInput);
std::string operation;
while(userInputSs >> operation){
std::cout << "operation: " << operation << '\n';
}
}
}
When I am reading file with function read(), this function doesn't save data to my buffer smoke. I'm trying to read a file and save it to smoke with binary content.
How can I do it better, with vectors?
std::ifstream file("favicon.ico", std::ios::binary);
char ak47xd[1024];
std::string testxcs = "";
if (file.is_open()) {
file.seekg(0, file.end);
const size_t length = file.tellg();
file.seekg(0, file.beg);
char smoke[318];
file.read(smoke, length);
printf("sss: %s\n",smoke);
for (int i = 0; i < length; i++) {
printf("sk: %c\n",smoke[i]);
testxcs += smoke[i];
//printf("%i : %X\n", i, smoke[i] & 0xFF);
//testxcs += (smoke[i] & 0xFF);
//printf("Smoke: %s\n",testxcs.c_str());
}
}
Output:
Here picture
Here problem
You are reinterpret_casting a char** to char*, your program's behaviour is undefined. Probably what is happening is the bytes are being written somewhere else.
You don't need three buffers to read into
#include <iostream>
#include <string>
std::ifstream file("favicon.ico", std::ios::binary);
if (file) {
file.ignore( std::numeric_limits<std::streamsize>::max() );
std::streamsize length = file.gcount();
file.clear(); // Since ignore will have set eof.
file.seekg( 0, std::ios_base::beg );
std::string testxcs(length, 0);
file.read(testxcs.data(), length);
std::cout << "sss: " << testxcs << "\n";
for (char c : testxcs)
{
std::cout << "sk: " << c << "\n";
}
}
IN IOS app, module written in C++ I am writing my data (map of basic strings and integers) to a text file. Using following method:
bool Recognizer::saveMap(const char * s)
{
if(trainingData.model && !trainingData.model.empty()) {
const string filename = string(s);
std::ofstream file(s, ios_base::trunc );
try{
if(! file.is_open())
{
file.open(s);
}
for (map<String,int>::iterator it=trainingData.idMap.begin(); it!=trainingData.idMap.end(); ++it)
{
cout << it->second << " " << it->first << endl;
file << it->first << endl << it->second << endl;
}
file.close();
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
std::streampos fileLength = iosFileSize(s);
cout << "Saved map to: " << filename << " length: " << fileLength << endl;
return true;
}
return false;
}
My contains one entry and console output indicates that two lines: string, string representing number have been written to my file.
Subsequent opening file for reading and reading using getline or using stream operator indicates that file is empty:
bool Recognizer::loadMap(const char * s)
{
std::streampos fileLenght = iosFileSize(s);
std::ifstream file(s, ios::in);
try{
if(file.is_open())
{
string name;
string lineName;
string lineTag;
int tag;
int count = 0;
while(getline(file,name))
{
if(getline(file,lineTag))
{
tag = stoi(lineTag,0,10);
count++;
cout << tag << " " << name << endl;
trainingData.idMap[name]=tag;
trainingData.namesMap[tag]=name;
}
}trainingData.personsCount=count;
file.close();
}
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
cout << "Loaded map from: " << s << " lenght: "<< fileLenght << endl;
return true;
}
I also copied from one of stackoverflow answers method returning file lenght and using it to verify lenghth of the file after write operation:
std::streampos iosFileSize( const char* filePath ){
std::streampos fsize = 0;
std::ifstream file( filePath, std::ios::binary );
fsize = file.tellg();
file.seekg( 0, std::ios::end );
fsize = file.tellg() - fsize;
file.close();
return fsize;
}
The file path passed to saveMap and loadMap seems to be legit. With path that the app could not write to, attempt to write caused exception.
There are no errors returned by write operation but both, attempts to read and iosFileSize() indicate that file is empty.
I am not sure if i need call file.open() and file.close() or file is open and closed automatically when output stream is created and later goes out of scope.
I experimented with those with the same result ( call to file.is_open returns true so the block calling file.open() is skipped.
What am I doing wrong?
I appreciate all responses.
It does not seem like you call file.flush(); anywhere in Recognizer::saveMap() after writing to the file stream. std::ofstream::flush() saves changes you've made to the file. Add file.flush(); between when you make changes to the code and when you close the file. See if that remedies your issue.
I also had the same issue. Using file.flush() everytime after you insert to a file can save your file.
However if you insert something like this, say,
file << "Insert This"; You will need to add file.flush().
But some people have issues, like if you just insert file << "Insert This" << endl; , this works fine. The key point here is that, std::endl calls flush() everytime it is used internally. you can say it is a shortend form of "\n" + flush().
I believe from looking at your code that you are overwriting your data when you open the file in the second program you should be using something like this.
std::fstream fs;
fs.open ("test.txt", ios::app)
instead of doing the ios::in
I've created a class which is supposed to read in DNA sequences: It contains an if stream private member:
Interface:
class Sequence_stream {
const char* FileName;
std::ifstream FileStream;
std::string FileFormat;
public:
Sequence_stream(const char* Filename, std::string Format);
NucleotideSequence get();
};
Implementation:
Sequence_stream::Sequence_stream(const char* Filename, std::string Format)
{
FileName = Filename;
FileStream.open(FileName);
FileFormat = Format;
std::cout << "Filestream is open: " << FileStream.is_open() << std::endl;
}
NucleotideSequence Sequence_stream::get()
{
if (FileStream.is_open())
{
char currentchar;
int basepos = 0;
std::string name;
std::vector<Nucleotide> sequence;
currentchar = FileStream.get();
if (currentchar == '>' && false == FileStream.eof()) { // Check that the start of the first line is the fasta head character.
currentchar = FileStream.get(); // Proceed to get the full name of the sequence. Get characters until the newline character.
while(currentchar != '\n' && false == FileStream.eof())
{
if (true == FileStream.eof()) {
std::cout << "The file ends before we have even finished reading in the name. Returning an empty NucleotideSequence" << std::endl;
return NucleotideSequence();
}
name.append(1, currentchar);
currentchar = FileStream.get();
} // done getting names, now let's get the sequence.
currentchar = FileStream.get();
while(currentchar != '>' && false == FileStream.eof())
{
if(currentchar != '\n'){
basepos++;
sequence.push_back(Nucleotide(currentchar, basepos));
}
currentchar = FileStream.get();
}
if(currentchar == '>')
{
FileStream.unget();
}
return NucleotideSequence(name, sequence);
} else {
std::cout << "The first line of the file was not a fasta format description line beginning with '>'. Are you sure the file is of FASTA format?" << std::endl;
return NucleotideSequence();
}
} else {
std::cout << "The filestream is not open..." << std::endl;
return NucleotideSequence();
}
}
However if I test it:
int main()
{
std::cout << "Let's try and read in a sequence!" << std::endl;
std::cout << "First we'll create a stream!" << std::endl;
Sequence_stream MyDNAStream("~/Dropbox/1_20dd5.fasta", "fasta");
std::cout << "Done!" << std::endl;
std::cout << "Now let's try and get a sequence!" << endl;
NucleotideSequence firstsequence = MyDNAStream.get();
return 0;
}
I see that the if stream is not open:
Let's try and read in a sequence!
First we'll create a stream!
Filestream is open: 0
Done!
The filestream is not open...
logout
[Process completed]
Although I thought the constructor function opens the if stream. What do I need to do to correct this so as the object is created and contains an open stream? (I know I'm yet to include a destructor which will close the stream upon destruction of the object).
Thanks,
Ben.
Your example shows that is_open returned false. I think you should check in your constructor that the file is indeed open, and throw if not.
In your case, I suspect this is due to passing "~/Dropbox/1_20dd5.fasta" as an input parameter. Did you test with a full pathname, with no ~? I have no knowledge of a C++ library that handles real path expansion (like python's os.path).
I want to read data from a txt file, but i am not able to get it. I am new to c++.
Here is my code, but it does not work. I used getline(),
ifstream inFile;
string sPassWord;
inFile.open("QdatPassWordconfig.config");
inFile.seekg(0,ios::end);
int length=inFile.tellg();
if (inFile.is_open())
{
while (!inFile.eof())
{
getline(inFile,sPassWord);
cout<<sPassWord<<endl;
}
cout<<"get data from txt file"<<endl;
// here ,I cannot read data from file
cout<<sPassWord<<endl;
}
if(!inFile.is_open() || length==0)
{
cout<<"file is create or write"<<endl;
sPassWord="BdsWUjT26";
ofstream outFile;
outFile.open("QdatPassWordconfig.config");
outFile<<sPassWord<<endl;
outFile.close();
}
inFile.close();
cout<<sPassWord<<endl;
It isn't clear if you are trying to read the first line of the file, the last line of the file, or all the lines of the file. Here program snippets for each possibility:
To read the first line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
if(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n"
}
}
To read all of the lines of the file:
// TESTED
#include <iostream>
#include <fstream>
#include <string>
int main ()
{
std::ifstream inFile("QdatPassWordconfig.config");
std::string sPassWord;
while(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
}
}
To read the last line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
int lineCount = 0;
while(std::getline(inFile, sPassWord)) {
lineCount++;
}
if(lineCount) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n";
}
}
inFile.seekg(0,ios::end);
int length=inFile.tellg();
1.You forgot seek back to the beginning. Like this:
inFile.seekg(0,ios::end);
int length=inFile.tellg();
inFile.seekg(0,ios::beg);
2.You need to practice on your if and else statement.
3.Don't use std::ifstream::eof. Use std::getline.
Do something like this:
// Declare local variables
std::ifstream inFile;
std::string sPassword = "";
::UINT length = 0;
// Attempt to open file
inFile.open( "QdatPassWordconfig.config" );
// Use your if and else statement like this:
// Is inFile open?
if( inFile.is_open( ) )
{
// Read file line by line using std::getline
while( std::getline( inFile, sPassword ) ) {
// Print sPassword
std::cout << sPassword << std::endl;
}
// Done with inFile, close it
inFile.close( );
}
else
{
// Do whatever if inFile can't be open
}
There are so many errors with your code, so I decided to show you how I would have done it (please do read the comments):
void Example( void )
{
// DECLARATION
bool bInputMode = true;
std::fstream ioFile;
::UINT nFileSize = 0;
std::string strPassword = "";
// INITIALIZATION
// *Open or create ioFile
// ioFile can now do both input and output operations
ioFile.open( "Passwords.pw",
std::fstream::in |std::fstream::out | std::fstream::app );
// *Calculate/set the value of bInputMode
// first, calculate the size of the file
// if the size of the file is = 0,
// bInputMode = false - which means to be in output mode
ioFile.seekg( 0, std::ios::end );
if( ( nFileSize = ioFile.tellg( ) ) = 0 )
bInputMode = false;
ioFile.seekg( 0, std::ios::beg );
// DO WHATEVER
// *Since bInputMode == true,
// we shall read each line from ioFile by using std::getline
if( bInputMode )
{
// *Get each line within ioFile and "copy" it to strPassword
// and then print strPassword
// *With std::getline, we could get the spaces
while( std::getline( ioFile, strPassword ) )
std::cout << strPassword << std::endl;
}
// *Since bInputMode == false,
// we shall create a new from ioFile and then write to it
else
{
std::cout << "Creating/writing a new file..." << std::endl;
strPassword = "Password123";
ioFile << strPassword << std::endl;
}
// CLEAN-UP
// We are done with ioFile, close it.
ioFile.close( );
};
Please point out any errors! Some feedback and suggestions would be great as well.