I am writing a OBDII reading library / application in C++. Data is retrieved from the car's computer by sending a simple string command, then passing the result through a function specific to each parameter.
I would like to read a config file of all the commands I want, something like this perhaps:
Name, Command, function
Engine RPM, 010C, ((256*A)+B)/4
Speed, 010D, A
Basically, very simple, all data needs to just be read in as a string. Can anyone recommend a good simple library for this? My target is g++ and/ or Clang on Linux if that matters.
You could use std::ifstream to read line by line, and boost::split to split the line by ,.
Sample code:
You could check tokens size for sanity checks of file loaded.
#include <fstream>
#include <vector>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
int main(int argc, char* argv[]) {
std::ifstream ifs("e:\\save.txt");
std::string line;
std::vector<std::string> tokens;
while (std::getline(ifs, line)) {
boost::split(tokens, line, boost::is_any_of(","));
if (line.empty())
continue;
for (const auto& t : tokens) {
std::cout << t << std::endl;
}
}
return 0;
}
You could also use String Toolkit Library if you don't want to implemented. Docs
Related
I am using a third party library which needs a ifstream object as input and I have a stringstream object which contains everything they need. Right now, I have to write the content of stringstream to a file and then send a ifstream object to the library. I am wondering if it is possible directly convert stringstream to ifstream in memory so I don't need to write a file on disk? thanks.
I your library is really accepting std::ifstream instead of std::istream, then I found the following hack:
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
void foo(std::ifstream& fs)
{
std::string h;
fs >> h;
std::cout << h << std::endl;
}
int main()
{
std::istringstream s1("hello");
std::ifstream s2;
s2.basic_ios<char>::rdbuf(s1.rdbuf());
foo(s2);
return 0;
}
I am not sure how safe it is, however, so you might investigate the topic further.
I write small test application in C++ to read the file data, So when I used the C++ -Stream class to read from files, it fails to open the file stream for the file name which gets passed as argument of the Stream class object.
Also I keep my file(Test.txt) in the directory where my program executable is kept and run.
#include<fstream>
#include<string>
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
ifstream testFile("Test.txt");
string line;
if (testFile.is_open())
{
while (getline(testFile, line))
{
line += line;
}
}
}
please also find the additional debug capture which has been captured from visual studio debugger.
If you run a program from the editor/IDE it is not always true (and generally it isn't) that the root directory for relative paths is the project directory or the one where the .exe is placed. If you run the executable from the command line placed in the directory it should work, but if you run it when the command line isn't in the directory you'll see the same error.
If you want the root directory to be the project one there is certainly an option in the editor/IDE, just surf the web or look into settings (probably run configurations)
The answer is: The file could not be opened. It is mispelled, or not existing.
But most likely it is in a different directory.
Please use a full path for the file, then you can open it. Like
ifstream testFile("c:\\temp\\Test.txt");
Then, please do not use is_open.
Simply use
if (testFile)
The ! operator for ifstream is overwritten, so this will work.
thanks all and I manage to get it working with the platform independent method. Please see the code below.
#include<fstream>
#include<string>
#include<stdlib.h>
#include<iostream>
#include <errno.h>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
int main(int argc, char *argv[])
{
fs::path Path = fs::current_path() / argv[1];
ifstream testFile(Path.c_str());
string line;
string str;
if (testFile.is_open())
{
for (std::string line; std::getline(testFile, line);)
{
str += line;
}
}
std::cout << str << endl;
}
I'm new to C++ and I've just read <C++ Primer> 4ed. Now I want to implement a little program to help me manage some mp3 files in my computer.
I have a .txt file which includes all the names(part of the names actually) of the files which I want to move(not copy) to a new folder(in the same column). For example, "word" and "file" in the .txt and I want to move all the .mp3 files whose filename contain "word" or "file" to a new folder. Hope my discription is clear, Opps..
I know how to read the strings in .txt into a set<string> and traverse it, but I have no idea how to search and move a file in a folder. I just want to know what else should I learn so that I can implement this function. I read C++ Primer and still I can't do much thing, that's really sad...
To move a file in C++, you do not have to use external libraries like Boost.Filesystem, but you can use standard functionality.
There is the new filesystem API, which has a rename function:
#include <iostream>
#include <filesystem>
int main() {
try {
std::filesystem::rename("from.txt", "to.txt");
} catch (std::filesystem::filesystem_error& e) {
std::cout << e.what() << '\n';
}
return 0;
}
The drawback is to compile it, you need a recent C++17 compiler. (I tested it on gcc 8.0.1, and I also needed to link against -lstdc++fs).
But what should work on any C++ compiler today, is the old C API, which also provides rename (cstdio):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
int main() {
if(std::rename("from.txt", "to.txt") < 0) {
std::cout << strerror(errno) << '\n';
}
return 0;
}
But note that in both cases, the rename will fail if the source and destination files are not on the same filesystem. Then you will see an error like this:
filesystem error: cannot rename: Invalid cross-device link [from.txt] [/tmp/to.txt]
In that case, you can only make a copy and then remove the original file:
#include <fstream>
#include <iostream>
#include <ios>
#include <cstdio>
int main() {
std::ifstream in("from.txt", std::ios::in | std::ios::binary);
std::ofstream out("to.txt", std::ios::out | std::ios::binary);
out << in.rdbuf();
std::remove("from.txt");
}
Or with the new API:
#include <iostream>
#include <filesystem>
int main()
{
try {
std::filesystem::copy("from.txt", "to.txt");
std::filesystem::remove("from.txt");
} catch (std::filesystem::filesystem_error& e) {
std::cout << e.what() << '\n';
}
return 0;
}
Use rename() function to move a file
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char oldname[] = "C:\\Users\\file_old.txt";
char newname[] = "C:\\Users\\New Folder\\file_new.txt";
/* Deletes the file if exists */
if (rename(oldname, newname) != 0)
perror("Error moving file");
else
cout << "File moved successfully";
return 0;
}
The only way for this to work only using std would be to read the file completely using a std::ifstream and then write it to the new location with a std::ofstream. This will however not remove the old file from disk. So basically you create a copy of the file. Its also much slower than a real move.
The optimal solution is to use OS specific APIs like win32 which e.g provide a MoveFile() function. Poco provides an platform independent abstraction of such APIs. See: http://www.appinf.com/docs/poco/Poco.File.html
Another way to move a file in Windows is using the MoveFile function as it is shown in the following code.
std::wstring oldPath = L"C:\\Users\\user1\\Desktop\\example\\text.txt";
std::wstring newPath = L"C:\\Users\\user1\\Desktop\\example1\\text.txt";
bool result = MoveFile(newPath.c_str(), oldPath.c_str());
if (result)
printf("File was moved!");
else
printf("File wasn't moved!");
under Windows run system call with batch commands:
system("move *text*.mp3 new_folder/");
system("move *word*.mp3 new_folder/");
Under Unix same with shell syntax.
I'm experimenting with C++ file I/O, specifically fstream. I wrote the following bit of code and as of right now it is telling me that there is no getline member function. I have been told (and insisted still) that there is a member function getline. Anybody know how to use the getline member function for fstream? Or perhaps another way of getting one line at a time from a file? I'm taking in two file arguments on the command line with unique file extensions.
./fileIO foo.code foo.encode
#include <fstream>
#include <iostream>
#include <queue>
#include <iomanip>
#include <map>
#include <string>
#include <cassert>
using namespace std;
int main( int argc, char *argv[] )
{
// convert the C-style command line parameter to a C++-style string,
// so that we can do concatenation on it
assert( argc == 2 );
const string foo = argv[1];
string line;string codeFileName = foo + ".code";
ifstream codeFile( codeFileName.c_str(), ios::in );
if( codeFile.is_open())
{
getline(codeFileName, line);
cout << line << endl;
}
else cout << "Unable to open file" << endl;
return 0;
}
getline(codeFileName, line);
Should be
getline(codeFile, line);
You're passing in the file name, not the stream.
By the way, the getline you're using is a free function, not a member function. In fact, one should avoid the member function getline. It's much harder to use, and harkens back to a day when there was no string in the standard library.
Typo
getline(codeFileName, line);
should be
getline(codeFile, line);
I guess the lesson is you have to learn how to interpret compiler error messages. We all make certain kinds of mistakes and learn the compiler errors they tend to generate.
When using ifstream class to read words from an input file, I have used the following expression:
#include <iostream>
#include <fstream>
int main(int argc, char *argv[])
{
std::ifstream inputStream(myFile.txt);
std::string myString;
myFile.open()
while(myFile.good())
{
myFile >> myString;
printf("%s \n", myString);
}
return 0;
}
The contents of myFile.txt are:
" This is a simple program. "
The compiles and executes as expected using g++ compiler.
However, the same code when compiled using msvc 2008, returns error at the extraction operator (>>) requiring me to replace the std::string with either an initialized character array or any of the supported native types.
This threw me off as I was expecting the usage of the standard library to be same across implementations.
I understand the compile error and know the way to fix it via using c_str().
But, it would help me a great deal, if someone could clarify why the usage for the standard library is different across platforms.
To me it is not starndard anymore !!
EDIT: Code updated to be complete. Content of myFile.txt updated.
Chances are that you forgot to #include <string>. Without it, Microsoft's version of <iostream> (and such) include enough of a declaration of std::string for some things to work, but other parts are missing, so you get strange, seemingly inexplicable failures.
One of the things that's missing is most of the operator overloads for std::string, which is exactly what you seem to be missing.
As an aside, while (myfile.good()) ... is pretty much a guaranteed bug -- you probably want:
while (myfile>>myString)
std::cout << myString << " \n";
Alternatively, you could do the job with a standard algorithm:
#include <string>
#include <algorithm>
#include <iterator>
#include <fstream>
#include <iostream>
int main() {
std::ifstream myfile("input.txt");
std::copy(std::istream_iterator<std::string>(myfile),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, " \n"));
return 0;
}
The following compiles fine for me on MSVC 2010:
std::ifstream inputStream;
std::string myString;
inputStream.open("myFile.txt", std::ifstream::in);
while(inputStream.good())
{
inputStream >> myString;
}
Note: without using std::ifstream::in as my open mode, I got the same error as you. I suggest you check what value you have for this parameter.