I thought I understood having to cast a std::string as a *char when opening a file, but I am missing something. It compiles fine but does not open. Tried a number of variations but so far only hardcoding the name in the file is working:
// const char * cEMN = cCCA.get_EMNfn().c_str();
// femn.open(cEMN); fails
// femn.open("file-foo.emn"); works
string stdEMN;
stdEMN = cCCA.get_EMNfn();
femn.open(stdEMN.c_str()); // fails
if(!femn)
{
cout << "Open of Original EMN file failed\n";
cout << "EMN file: " << cCCA.get_EMNfn() << endl;
cout << "Press any key to exit" << endl;
ch = getchar();
return 1;
}
The facts as I discern them to be are that:
femn.open("file-foo.emn");
succeeds. But
femn.open(stdEMN.c_str());
fails.
The obvious conclusion is that stdEMN.c_str() evaluates to a string that differs from "file-foo.emn".
Related
I'm trying to write a program that replaces a specific line with a word in it or if the line doesn't exist in the file it should add it. Kind of like a key value store.
I played around with the following code, unfortunately nothing came of it. Either he just overwrote the file and deleted the other lines, or he just didn't write anything at all. Finally, this code remained. It's inefficient and confusing, I know that but maybe you can help me.
!!! at the moment he is not writing anything to the file!!!
Code:
void edit(char*key, char*value){
ifstream filein("test.txt");
ofstream fileout("tempTest.txt");
if(!filein || !fileout)
{
cout << "Error opening files!" << endl;
return;
}
bool found = false;
string line;
while(getline(filein, line))
{
if(line.find(key) == 0)
{
fileout << key << "=" << value << endl;
found = true;
}
else
{
fileout << line << endl;
}
if(!found)
{
fileout << key << "=" << value << endl;
}
}
filein.close();
fileout.close();
remove("test.txt");
}
In your while loop, you keep writing
fileout << key << "=" << value << endl;
in every iteration, until your key is found.
That line should be outside of the loop.
I have a class where I store a filename that a user has provided:
string EMNfn; // IDF file EMN name
// IDF file EMN name
void CcaAna::put_EMNfn(string s)
{
CcaAna::EMNfn = s;
}
string CcaAna::get_EMNfn()
{
return EMNfn;
}
However, when I try to open the file, and I know it exists in the current directory that I am using with the following:
femn.open(cCCA.get_EMNfn());
I get a compile error C2664 ...cannot convert parameter 1 from 'class std::basic_string,class std::allocator >' to 'const char *'
When I try using:
femn.open(cCCA.get_EMNfn().c_str());
it compiles but trips my error code:
if(!femn)
{
cout << "Open of Original EMN file failed\n";
cout << "EMN file: " << cCCA.get_EMNfn() << endl;
cout << "Press any key to exit" << endl;
ch = getchar();
return 1;
}
However when I type it in directly everthing works fine:
femn.open("262-003841-7-23.emn");
running out of ideas is there another way to open the stream?
molbdnilo - I think you are on to something (see below)
OK I added the two COUT lines after and I have included the OUTPUT below the code:
cout << "EMN file: " << cCCA.get_EMNfn() << endl;
// THIS WORKS
// femn.open("262-003841-7-23.emn");
femn.open(cCCA.get_EMNfn().c_str());
// femn.open(cCCA.get_EMNfn());
cout << "this works: " << "262-003841-7-23.emn" << endl;
cout << "*****" << cCCA.get_EMNfn() << "*****" << endl;
OUTPUT:
PROCESSING USER INPUT FILE ...
EMN file: "262-003841-7-23.emn"
this works: 262-003841-7-23.emn
*****"262-003841-7-23.emn"*****
Open of Original EMN file failed
EMN file: "262-003841-7-23.emn"
Press any key to exit
What I am seeing is that the stored string has " around it. Is there a C++ way to remove those?
You are not assigning strings correctly!string variables should not be assigned with = operator . Here is a reference for working with strings.
There are lots of ways for doing your task here is one:
#include <string.h>
...
strcpy(CcaAna::EMNfn,s);//instead of CcaAna::EMNfn=s;
maybe this might work,if not check the link and use a correct way to work with strings.
cheers
I wrote this piece of code to try leveldb. I am using Unix time as keys. For values that have spaces, only the last part gets saved. Here is the code. I am running Linux Kernel 4.4.0-47-generic
while (true) {
std::string note;
std::string key;
std::cout << "Test text here ";
std::cin >> note;
std::cout << std::endl;
if(note.size() == 0 || tolower(note.back()) == 'n' ) break;
key = std::to_string(std::time(nullptr));
status = db->Put(write_options, key, note);
if(!status.ok()) break;
}
std::cout << "Read texts........" << std::endl;
leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
for(it->SeekToFirst(); it->Valid(); it->Next()){
std::cout << it->key().ToString() << " " << it->value().ToString() << std::endl;
}
delete db;
The issue is not in leveldb, but in the way you read the input:
std::string note;
std::cin >> note;
This will read only up to the first whitespace. It is common mistake, see for example:
reading a line from ifstream into a string variable
Im working on my homework assignment and I stuck because in the assignment we have to ask the user to enter a file name but also to type in either wc cc or lc (word count, character count, and line count of a file. For example, wc filename.txt. Im suppose to check the file to see if its valid or not which i understand and I know how to compare the users input to determine the different kind of function to run, but I dont understand how you could do it together. Any ideas? This is what I have so far.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
string file;
ifstream input; //input file stream
int i;
cout << "Enter a file name" << endl;
while(true){
cout << ">" ;
getline(cin,file);
input.open(file.c_str());
if (input.fail()) {
cerr << "ERROR: Failed to open file " << file << endl;
input.clear();
}
else {
i = 0;
while (getline(input, line))
if(line == "wc"){
cout << "The word count is: " << endl;
}
else if(line == "cc"){
cout << "The character count is: " << endl;
}
else if(line == "lc"){
cout << "The line count is: " << endl;
}
else if(line == "exit"){
return 0;
}
else{
cout << "----NOTE----" << endl;
cout << "Available Commands: " << endl;
cout <<"lc \"filename\"" << endl;
cout <<"cc \"filename\"" << endl;
cout <<"wc \"filename\"" << endl;
cout <<"exit" << endl;
}
}
}
return 0;
}
void wordCount(){
//TBD
}
void characterCount(){
//TBD
}
void lineCount(){
//TBD
}
You have to find the space between the command and the file name in the users input and then split the string where you find the space. Something like this
cout << "Enter a command\n";
string line;
getline(cin, line);
// get the position of the space as an index
size_t space_pos = line.find(' ');
if (space_pos == string::npos)
{
// user didn't enter a space, so error message and exit
cout << "illegal command\n";
exit(1);
}
// split the string at the first space
string cmd = line.substr(0, space_pos);
string file_name = line.substr(space_pos + 1);
This is untested code.
You could do better than this, for instance this would not work if the user entered two spaces between the command and the file name. But this kind of work rapidly gets very tedious. As this is an assignment I would be tempted to move on to more interesting things. You can always come back and improve things later if you have the time.
I think you are asking how to validate multiple arguments: the command and the file.
A simple strategy is to have function like the following:
#include <fstream> // Note: this is for ifstream below
bool argumentsInvalid(const string& command, const string & command) {
// Validate the command
// Note: Not ideal, just being short for demo
if("wc" != command && "cc" != command && "lc" != command) {
std::cout << "Invalid command" << std::endl;
return false;
}
// Validate the file
// Note: This is a cheat that uses the fact that if its valid, its open.
std::ifstream fileToRead(filename);
if(!fileToRead) {
std::cout << "Invalid file: \"" << filename << "\"" << std::endl;
return false;
}
return true;
// Note: This does rely on the ifstream destructor closing the file and would mean
// opening the file twice. Simple to show here, but not ideal real code.
}
If you want to evaluate ALL arguments before returning an error, insert a flag at the top of that function, like:
// To be set true if there is an error
bool errorFound = false;
and change all of the returns in the conditions to:
errorFound = true;
and the final return to:
return !errorFound;
Usage:
....
if(argumentsInvalid(command, filename)) {
std::cout << "Could not perform command. Skipping..." << std::endl;
// exit or continue or whatever
}
// Now do your work
Note: The specific validity tests here are over simplified.
Hi below is my function:
string Employee::get_print(void) {
string out_string;
stringstream ss;
ss << e_id << " " << type << endl;
out_string = ss.str();
return out_string;
}
e_id and type are int and they contain values from the class Employee. But when I pass them into the stringstream they just clear the string when I try to out put it. But if I don't have a int in the ss << "Some text" << endl; this output fine. What am I doing wrong =S
//Edit
Ok;
This is the calling code:
tmp = cur->get_print();
Where tmp is a string and cur is an Employee Object.
This code...
stringstream out;
out << "Test " << e_id << " " << e_type;
return out.str();
Retruns "Test " and nothing else. If I take out "Test " << my returned string is ""
I'm using GCC 4.2 on Mac OS/X 10.6.2 if that makes any difference.
I too am unable to reproduce this error. As has been mentioned, don't include the endl, as this actually appends a \n and is supposed to flush the write buffer. For this use, it is completely unnecessary and may actually lead to undesirable results...However, the code in your edit/update works just fine for me.
int main(int argc, char* argv[])
{
int e_id = 5;
int e_type = 123456;
stringstream out;
out << "Test " << e_id << " " << e_type;
cout << out.str();
return 0;
}
Produces:
Test 5 123456
My suggestions would be to double check that e_id and e_type are really just native int.
For further testing, you may want to force a cast on the values to see if it helps as such:
out << "Test " << (int)e_id << " " << (int)e_type;
Since I'm unable to reproduce this error, I'm afraid I'm unable to help any further. But best of luck to you!
Ok I have no idea what is going on with stringstream I've tried using it in other parts of my code and it doesn't work with integers. Therefore, I have reverted to using the sprintf C function:
string Employee::get_print(void) {
char out[50];
sprintf(out, "%d %d", e_id, e_type);
string output = out;
return output;
}
This returns the string which is needed.
I have moved into Netbeans and I don't have this problem. So it is an issue with Xcode.
I think the endl is not needed. You only need to write endl if you want to write a newline on a file on on std::cout.
Since you write endl, your stringstream will contain a string with 2 lines of which the second is empty. This probably confuses you. Remove the endl to get only one line.
I've got exactly the same problem - GCC and stringstream returning nothing.
As I found out, the trick is that you have to put some text data before anything else into the stringstream.
This code...
stringstream ss(stringstream::out);
ss << 3.14159;
cout << "'" << ss.str() << "'" << endl;
gets you this result:
''
But if we put a single "" inside the stringstream first...
stringstream ss(stringstream::out);
ss << "" << 3.14159;
cout << "'" << ss.str() << "'" << endl;
the result is as expected:
'3.14159'