file reading in debian; - c++

I need to read config file, containing key value pairs.
File contains several strings like this:
key1=value1
key2=value2
keyN=valueN
***//terminate
class CFG
{
public:
static void Init(char* path_);
static string Param(string name_);
static string PrintAll();
private:
static void GetPathEXE(string path_);
static void ParseConfigFile();
static map<string, string> mapData;
};
void CFG::ParseConfigFile()
{
ifstream file;
file.open(Param("HomePath") + Param("Slash") + "ConfigMS.cfg");
if (file.is_open())
{
string file_line;
cmatch results;
regex reg3("(.*)=(.*)", std::regex_constants::ECMAScript);
std::cout<<"Parsing cfg file"<<endl;
while (getline(file, file_line) && (file_line.substr(0, 3) != "***"))
{
std::cout<<file_line<<endl;
std::regex_match(file_line.c_str(), results, reg3);
mapData.insert(std::pair<string,string>(results.str(1),results.str(2) ));
mapData[string(results.str(1))] =string( results.str(2));
std::cout<<"key: "<<results.str(1)<<" val: "<<results.str(2)<<endl;
}
//mapData["OuterIP"] = "10.77.1.68";
std::cout<<"Config loaded\n";
for (auto it : mapData)
{
std::cout<<it.first<<"="<<it.second<<endl;
}
if (Param("OuterIP") == "") mapData["Error"] = "IP for receiving messages not set in *.cfg file.\n";
//else if (data["sipName"] == "") error = "sipName for receiving messages not set in *.cfg file.\n";
}
else { mapData["Error"] = "Could not open *.cfg file. Check its existance or name. Name Must \"be ConfigMS.cfg\".\n"; }
if (Param("RTPPort") == Param("MGCPPort"))
{
mapData["Error"] = "RTP port is same as MGCP port. Please change one of them.\n";
}
if (Param("Error") != "")
{
cout << "\n" + Param("Error");
//system("pause");
exit(-1);
}
}
string CFG::Param(string name_)
{
return mapData[name_];
}
If I rely on file input i have [OuterIP,10.77.1.68] key value pair in my map, but function CFG::Param("OuterIP") returns empty string; And I have no idea how to work around this problem;

I've compiled you code with small modifications and it works.
rafix07 told us the program exits if there is no MGCPort and RTPPort values, and he is right, but you told explicitly that the function returns an empty string. Are you sure there isn't another empty OuterIP parameter in the file?
BTW my modifications are removing the path, reading just the file and commenting out the exit(-1) thing. (As well as adding a main function.)
#include <regex>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class CFG
{
public:
static void Init(char* path_);
static string Param(string name_);
static void ParseConfigFile();
private:
static void GetPathEXE(string path_);
static map<string, string> mapData;
};
void CFG::ParseConfigFile()
{
ifstream file;
file.open("ConfigMS.cfg");
if (file.is_open())
{
string file_line;
cmatch results;
regex reg3("(.*)=(.*)", std::regex_constants::ECMAScript);
std::cout<<"Parsing cfg file"<<endl;
while (getline(file, file_line) && (file_line.substr(0, 3) != "***"))
{
std::cout<<file_line<<endl;
std::regex_match(file_line.c_str(), results, reg3);
mapData.insert(std::pair<string,string>(results.str(1),results.str(2) ));
mapData[string(results.str(1))] =string( results.str(2));
std::cout<<"key: "<<results.str(1)<<" val: "<<results.str(2)<<endl;
}
//mapData["OuterIP"] = "10.77.1.68";
std::cout<<"Config loaded\n";
for (auto it : mapData)
{
std::cout<<it.first<<"="<<it.second<<endl;
}
if (Param("OuterIP") == "") mapData["Error"] = "IP for receiving messages not set in *.cfg file.\n";
//else if (data["sipName"] == "") error = "sipName for receiving messages not set in *.cfg file.\n";
}
else { mapData["Error"] = "Could not open *.cfg file. Check its existance or name. Name Must \"be ConfigMS.cfg\".\n"; }
if (Param("RTPPort") == Param("MGCPPort"))
{
mapData["Error"] = "RTP port is same as MGCP port. Please change one of them.\n";
}
if (Param("Error") != "")
{
cout << "\n" + Param("Error");
//system("pause");
//exit(-1);
}
}
string CFG::Param(string name_)
{
return mapData[name_];
}
map<string, string> CFG::mapData;
int main ()
{
CFG::ParseConfigFile ();
cout << "Param: " << CFG::Param("OuterIP") << std::endl;
return 0;
}
This is the program as I've compiled with:
g++ main.cc -o regex -std=c++11
This is the configuration file:
OuterIP=10.0.0.1
And these are the results:
Parsing cfg file
key: val:
key: val:
OuterIP=10.0.0.1
key: OuterIP val: 10.0.0.1
Config loaded
=
OuterIP=10.0.0.1
RTP port is same as MGCP port. Please change one of them.
Param: 10.0.0.1
As you can see, the last line is the cout in main.
So your code works. You have to remove the exit(-1) from the class. It doesn't have sense anyway.

Related

How to output the line im checking inside of a file onto the console

I am trying to create a program that makes a file called hardware id txt when non is present, but if it is it will look inside of it and find the hardware id, if it matches then it will print something, right now i am trying to output whats in the file first to test, no errors but the hardware id does not appear in console, i checked the file and can confirm the hardware id is inside of it.
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
HW_PROFILE_INFO hwProfileInfo; // unless we have a very good reason, this should
// not be global
if(GetCurrentHwProfile(&hwProfileInfo) != NULL)
{ // update info was a success. NOW we have a GUID and can do stuff with
// hwProfileInfo
printf("Hardware GUID: %s\n", hwProfileInfo.szHwProfileGuid);
printf("Hardware Profile: %s\n", hwProfileInfo.szHwProfileName);
std::ofstream hwidfile { "hardwareid2.txt" };
if (!(hwidfile << hwProfileInfo.szHwProfileGuid))
{ // will fail if can't write for any reason, like file didn't open
std::cout << "File write failed\n";
return -1;
}
}
else
{
std::cout << "GetCurrentHwProfile failed\n";
return -1;
}
getchar();
}
int check()
{
HW_PROFILE_INFO hwProfileInfo;
if(GetCurrentHwProfile(&hwProfileInfo) != NULL) {
string line;
ifstream checkhwid("hardwareid2.txt");
while(getline(checkhwid, line)) {
cout << line;
}
checkhwid.close();
}
}

"Not a directory" when writing kernel configurations

I am trying to toggle IPv6 on Linux systems using this function in Qt. The problem is that it fails opening the file and simply reports "Not a directory".
bool toggle_ipv6(const bool &enabled) {
const std::vector<std::string> ipv6_kernel_option_files = {
"/proc/sys/net/ipv6/conf/all/disable_ipv6"
"/proc/sys/net/ipv6/conf/default/disable_ipv6"
"/proc/sys/net/ipv6/conf/lo/disable_ipv6"
};
for (const auto &filename: ipv6_kernel_option_files) {
QFile kernel_option_file( filename.c_str() );
if ( kernel_option_file.open(QIODevice::WriteOnly) ) {
QTextStream stream(&kernel_option_file);
stream << (enabled ? "0" : "1");
kernel_option_file.close();
} else {
const std::string error_message = kernel_option_file.errorString().toStdString();
qDebug().nospace().noquote() << '[' << QTime::currentTime().toString() << "]: " << error_message.c_str();
return false;
}
}
return true;
}
I've tried searching the web but I can't find any other issue pertaining to QFile and this particular error message. How can I fix this?
Commas are missing in vector initialization:
const std::vector<std::string> ipv6_kernel_option_files = {
"/proc/sys/net/ipv6/conf/all/disable_ipv6"
"/proc/sys/net/ipv6/conf/default/disable_ipv6"
"/proc/sys/net/ipv6/conf/lo/disable_ipv6"
};
Hence the vector has only one element, which is a string made of the three paths, concatenated:
"/proc/sys/net/ipv6/conf/all/disable_ipv6/proc/sys/net/ipv6/conf/default/disable_ipv6/proc/sys/net/ipv6/conf/lo/disable_ipv6"
Considering that
"/proc/sys/net/ipv6/conf/all/disable_ipv6"
is a file, not a directory, it can't contain the rest of the path.
Use commas to separate the paths in vector initialization:
const std::vector<std::string> ipv6_kernel_option_files = {
"/proc/sys/net/ipv6/conf/all/disable_ipv6",
"/proc/sys/net/ipv6/conf/default/disable_ipv6",
"/proc/sys/net/ipv6/conf/lo/disable_ipv6"
};

is there an example of protobuf with text output?

I want to use protobuf and to create the serialization output file in text format for testing and for a replacement of json. I can't figure out how to write it on my own and am looking for examples.
Here is the one on binary output :
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, '\n');
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << "Unknown phone type. Using default." << endl;
}
}
}
// Main function: Reads the entire address book from a file,
// adds one person based on user input, then writes it back out to the same
// file.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << ": File not found. Creating a new file." << endl;
} else if (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
// Add an address.
PromptForAddress(address_book.add_people());
{
// Write the new address book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
Can I just do some minor changes in this one to output in text format or something else needs to be done? Please either suggest the changes required or any link where code exists (in any language).
The debug string output is guaranteed to be valid text-serialized format, but does not care about whether the protocol message is actually valid:
std::string s = msg.DebugString(); // or ShortDebugString
If you want to validate, use TextFormat::PrintToString:
#include <google/protobuf/text_format.h>
if (std::string s; google::protobuf::TextFormat::PrintToString(msg, &s)) {
std::cout << "Your message: " << s;
} else {
std::cerr << "Message not valid (partial content: "
<< msg.ShortDebugString() << ")\n";
}
Tools for JSON interop are available in json_util.h.
This code will serialise protobuf messages to JSON and deserialise JSON to protobuf messages.
This is lifted straight out of production code (which I own and hereby grant you licence to use, but please credit me).
This is linked against protobuf 3.
Header:
struct pretty_json_type {
void operator()(google::protobuf::util::JsonOptions& opts) const {
opts.add_whitespace = true;
}
};
static constexpr pretty_json_type pretty_json{};
struct compact_json_type {
void operator()(google::protobuf::util::JsonOptions& opts) const {
opts.add_whitespace = false;
}
};
static constexpr compact_json_type compact_json{};
struct include_defaults_type {
void operator()(google::protobuf::util::JsonOptions& opts) const {
opts.always_print_primitive_fields = true;
}
};
static constexpr include_defaults_type include_defaults{};
template<class...Options>
auto json_options(Options&&...options)
{
google::protobuf::util::JsonOptions opts;
using expand = int [];
void(expand{
0,
((options(opts)),0)...
});
return opts;
}
std::string as_json(const google::protobuf::Message& msg,
google::protobuf::util::JsonOptions opts = json_options(pretty_json,
include_defaults));
std::string as_json(const google::protobuf::Message* msg,
google::protobuf::util::JsonOptions opts = json_options(pretty_json,
include_defaults));
google::protobuf::Message& from_json(google::protobuf::Message& msg,
const char* first,
std::size_t size);
inline
decltype(auto) from_json(google::protobuf::Message& msg,
const std::string& json)
{
return from_json(msg, json.data(), json.length());
}
Implementation
std::string as_json(const google::protobuf::Message& msg,
google::protobuf::util::JsonOptions opts)
{
namespace pb = google::protobuf;
namespace pbu = google::protobuf::util;
auto buffer = msg.SerializeAsString();
std::string result;
pb::io::ArrayInputStream zistream(buffer.data(), buffer.size());
auto resolver = std::unique_ptr<pbu::TypeResolver> {
pbu::NewTypeResolverForDescriptorPool("",
pb::DescriptorPool::generated_pool())
};
auto status = google::protobuf::util::BinaryToJsonString(resolver.get(),
"/" + msg.GetDescriptor()->full_name(),
buffer,
std::addressof(result),
opts);
if (!status.ok())
{
std::ostringstream ss;
ss << status;
throw std::runtime_error(ss.str());
}
return result;
}
std::string as_json(const google::protobuf::Message* msg,
google::protobuf::util::JsonOptions opts)
{
return as_json(*msg, opts);
}
google::protobuf::Message& from_json(google::protobuf::Message& msg,
const char* first,
std::size_t size)
{
namespace pb = google::protobuf;
namespace pbu = google::protobuf::util;
auto resolver = std::unique_ptr<pbu::TypeResolver> {
pbu::NewTypeResolverForDescriptorPool("", pb::DescriptorPool::generated_pool())
};
auto zistream = std::make_unique<pb::io::ArrayInputStream>(first,
size);
auto binary_buffer = std::string {};
binary_buffer.reserve(size);
auto zostream = std::make_unique<pb::io::StringOutputStream>(std::addressof(binary_buffer));
auto status = pbu::JsonToBinaryStream(resolver.get(),
"/" + msg.GetDescriptor()->full_name(),
zistream.get(), zostream.get());
zistream.reset();
zostream.reset();
if (msg.ParseFromString(binary_buffer))
{
return msg;
}
throw std::runtime_error("invalid message");
}
To convert a message to JSON in three lines of code, do this -
#include <google/protobuf/util/json_util.h>
static std::string ProtoToJson(const google::protobuf::Message& proto)
{
std::string json;
google::protobuf::util::MessageToJsonString(proto, &json);
return json;
}

finding a string in a file using fstream in c++

This is my code
/*
Asks the user for their ID, depending on the ID depends on the results. It either goes to maintanance
or it asks the user to return DVD's or check DVD's out and changes the stock of the DVD's.
Cody Close
*/
#include <iostream>
#include <fstream>
#include <conio.h>
#include <sstream>
#include <string>
using namespace std;
void custID();
void sales();
void returns();
void discounts();
void maint();
void createAcc(string* filename, string* newID);
bool checkID(string* filename, string* search);
int main()
{
//Declares all the variables for the program
int mainID= 99959, menuChoice;
bool close = false;
bool done = false;
string vidId;
//Declares and input file and opens a file
fstream inFile;
inFile.open("dayin00.dat");
do{
do{
cout << "accountID: " << endl;
cin >> mainID;
stringstream out;
out << mainID;
mainid = out.str();
checkID("IDlist.txt", mainid);
}while(mainid.length() < 5 || mainid.length() > 9);
if(mainID!= 99959)
{
do
{
cout << "MENU:" << endl;
cout << "(1)Purchase\n(2)Return\n(3)Exit" << endl;
cin >> menuChoice;
switch(menuChoice)
{
case 1:
case 2:
case 3:
done = true;
}
}while(done == false);
}else{
maint();
}
close = true;
}while(close == false);
return 0;
}
void maint()
{
int maintChoice;
cout << "\n(1)Summary\n(2)Withdrawl\n(3)Close Down\n(4)Back to >main\n(0)Help" << endl;
cin >> maintChoice;
switch (maintChoice)
{
case 1:
case 2:
case 3:
case 4:
default:
cout << "1 for summary, 2 for withdrawl, 3 to close down, 4 to >go back to main" << endl;
}
}
void createAcc(string* filename, string* newID)
{
fstream newFile;
newFile.open(filename);
newFile << newID;
}
void checkID(string* filename, string* ID)
{
fstream infile;
infile.open("IDlist.txt");
string word;
infile >> word;
while (!infile.eof()){
if(word == ID)
{
cout << "ID FOUND!" << endl;
}else{
createAcc(infile, ID);
}
}
}
The text file only contains the ID 99959. How do I check if the ID the user types in already exists in the text file and if it doesn't, then it goes to createAcc(),setting up a new account using the ID that the user has entered.
The code opens file with users ID in read mode, reads it line by line and tries to finde ID. If ID not found in file, it opens file in write mode and add user ID in file.
#include <iostream>
#include <fstream>
#include <stdexcept>
void createAcc(const std::string& filename, const std::string& id)
{
std::ofstream os(filename);
if (os)
os << id;
else
throw std::runtime_error("Open file error: " + filename);
}
bool isStringContainsID(const std::string& line, const std::string& id)
{
if (line.find(id) == std::string::npos)
return false;
else
return true;
}
bool isFileContainsID(const std::string& filename, const std::string& id)
{
std::ifstream is(filename);
if (!is)
throw std::runtime_error("Open file error: " + filename);
std::string line;
while (is)
{
std::getline(is, line);
if (isStringContainsID(line, id))
return true;
}
return false;
}
int main() {
std::string id("99959");
std::string file_name("IDlist.txt");
if (isFileContainsID(file_name, id))
std::cout << "ID FOUND!" << std::endl;
else
createAcc(file_name, id);
return 0;
}
Note that all users ID should have the same length in string representation, otherwise the code can find shorter ID in file that contains larger ID with shorter ID as sub-string.

C++ error in program

I'm getting this error on my program and I don't understand why. The code essentially has to check for tags stored in a set which is declared as a global variable. If it's a valid tag it stores it in the stack if not returns a error message. Then it checks (if its a valid tag)if the closing tags are in order. This is all for the is_well_formed method. For the print_well_formed_file method it essentially checks if the given file is well formed if it is it'll display the file.:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
What can I do to fix this error ?
This is part of the code:
bool is_well_formed(ifstream& ifs, string& error_msg) {
// your code goes here
string fname, line;
Token tok;
Lexer lexer;
tags.insert("blue");
tags.insert("red");
tags.insert("cyan");
tags.insert("white");
tags.insert("yellow");
tags.insert("magenta");
tags.insert("dim");
tags.insert("underline");
tags.insert("bold");
while (getline(cin, fname)) {
// tries to open the file whose name is in string fname
string name = fname.substr(1, fname.length() - 2);
cout << "Name" + name;
ifs.open(name.c_str());
if (ifs.fail()) {
cerr << "ERROR: Failed to open file " << fname << endl;
ifs.clear();
} else {
while (getline(ifs, line)) {
lexer.set_input(line);
while (lexer.has_more_token()) {
tok = lexer.next_token();
string tmpTok = tok.value;
switch (tok.type) {
case TAG:
// If it has /, remove / from tmpTok
if (tok.value[0] == '/') {
tmpTok = tmpTok.substr(1, tmpTok.length() - 1);
}
if (tags.find(tmpTok) == tags.end()) {
// Check whether the encountered tag is valid
error_return("Tag " + tmpTok + " is invalid!");
} else {
// Valid Tag encountered
stack < string > tagstack;
tagstack.push(tmpTok);
// Check if the tags are formed properly
if (tok.value[0] == '/') {
// Remove / from tmpTok
string closingTag = tmpTok;
string openingTag = tagstack.top();
tagstack.pop();
if (closingTag.compare(openingTag) != 0) {
error_return(
closingTag + "doesn't match"
+ openingTag);
} //else
// return true; // if the file is well formed
}
}
break;
case IDENT:
cout << "IDENT: " << tok.value << endl;
break;
case ERRTOK:
error_return("Syntax error on this line\n");
//cout << "Syntax error on this line\n";
break;
case ENDTOK:
break;
}
}
}
}
}
return true; // if the file is well-formed
}
void print_well_formed_file(ifstream& ifs) {
//Check if file is well formed.
string line;
Lexer command;
if (is_well_formed(ifs, line)) { //if well formed display
command.set_input(line);
display(command);
}
}
void display(Lexer cmd_lexer) {
string file_name;
if (!parse_input(cmd_lexer, file_name)) {
error_return("Syntax error: display <filename>");
return;
}
ifstream ifs(file_name.c_str());
string error_msg;
if (ifs) {
if (!is_well_formed(ifs, error_msg)) {
error_return(error_msg);
} else {
ifs.clear(); // clear EOF flag
ifs.seekg(0, ios::beg); // go back to the very beginning
print_well_formed_file(ifs);
}
} else {
error_return("Can't open " + file_name + " for reading");
}
ifs.close();
}
Example of user input:
validate <file name>
display <file name>
exit
string name = fname.substr(1, fname.length() - 2);
Will throw this kind of an exception if fname's length is <= 1 . I bet, this is the case. The simplest(not the best) solution is to skip such lines.