Function to parse automaticly files .txt after 24 hour in c++ - c++

I have a project and I'm new to C++
Well I have to parse a file.txt that contains transaction informations in an ATM. And there is files named as the date of the transactions.
For example the file (20211102.txt) is a file that has all the informations, created in 02/11/2021.
So after midnight another file is being created .
!! My Objectif is : Every day I have to parse the file from the day before.
I have tried a function that generate the date of yesterday.
I have to use it But I don"t know how
-Here is the function of parsing the file
void parse()
{
ifstream file1("20211120.jrn");
string str;
if(file1.is_open())
{
while (getline(file1, str))
{
cout << str << "\n";
}
file1.close();
cout << "PARSING FIRST JOURNAL" << endl;
}
else
cout <<"File not found " << endl;
file1.close();
}
I hope it's clear .
Thank you in advance.

As discussed in this question, you can do something like:
#include <chrono>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <string>
#include <iostream>
std::string return_current_time_and_date() {
using namespace std::chrono_literals;
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now - 24h);
std::stringstream ss;
ss << std::put_time(std::localtime(&in_time_t), "%Y%m%d");
return ss.str();
}
where some things have been adapted for your use case (i.e. format and so the date is of yesterday). See operation here.
As to running it every day you'd have to have some scheduler run it for you. I am not that familiar with this on windows, but this website seems to offer good advice on how you can set up such a job. Alternatively this question, might be of use.

Related

My program will not open text file. Ofstream CPP

I'm currently new to C++ and I've been watching a tutorial series https://www.youtube.com/watch?v=_bYFu9mBnr4, but I'm having a big issue. My C++ code will not open a file no matter what I do, I've looked online and tried renaming it, the full path, everything I can think of. Here's my code,
#include <iostream>
#include <fstream>
#include <cstring>
#include <cerrno>
#include <filesystem>
int main()
{
std::ofstream file;
file.open("hello.txt");
if (!file.is_open())
{
std::cerr << "Error: " << strerror(errno) << '\n';
std::cout << std::filesystem::current_path() << std::endl;
}
file << "hello!";
file.close();
return 0;
}
Sorry about this question, it may have been a dumb issue. Turns out IT WAS my antivirus. Avast kept blocking it, it was just looking out for me. I decided to change my antivirus afterwards and it now works fine!

How to write to file outside working directory?

I'm trying to figure out how to write to a file outside the working directory. This is the code I currently have.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string sp{};
std::fstream ss("C:\\Users\\onion\\AppData\\Roaming\\MetaQuotes\\Terminal\\some numbers\\MQL5\\Files\\testnew.txt", std::ios::in | std::ios::out);
if (!ss.is_open()) std::cout << "Failed" << '\n';
else
{
while (ss.is_open())
{
std::getline(ss, sp);
std::cout << sp << '\n';
ss << "new data";
if (ss.eof())break;
}
}
}
I can read the file perfectly fine, but I cant write to it? Could it be that Metatrader itself is limiting my ability to write to a file or does a file have to be in the working directory to be able to write to it? or am I just doing it wrong?

After convert string to const *json, when pasing json object, shows failed: (IsObject()), how to solve this?

After convert string strjson to const char* json, when interate, shows
failed: (IsObject()), function FindMember,failed, I don't understand why showed this, I think this the json object is correct format.
//
// main.cpp
// rapid
//
// Created by Shi Yan on 10/7/17.
// Copyright © 2017 Shi Yan. All rights reserved.
//
#include <iostream>
#include "rapidjson.h"
#include "document.h"
#include <fstream>
using namespace std;
using namespace rapidjson;
void readjson(){
ifstream handle("meta_Books.json");
if(handle.is_open()){
//cout<<"open success"<<endl;
const char* json;
string strjson;
int i=1;
while(getline(handle,strjson)){
if(i>4)
break;
cout<<strjson<<endl;
cout<<strjson.length()<<endl;
i++;
json=strjson.c_str();
cout<<"*********************"<<endl;
cout<<*json<<endl;
StringStream s (json);
Document document;
document.ParseStream(s);
Value::ConstMemberIterator itr = document.FindMember("asin");
cout<<itr->name.GetString()<<" = "<< itr->value.GetString()<<endl;
}
}
}
int main() {
readjson();
return 0;
}
I think the format of json object , so why failed?
As you can see , the getline() method works well, because the output of string is an complete string
The assertion error means that FindMember() is being called on a Value that does not represent a JSON object (IsObject() is false).
Since there is only 1 FindMember() in the code you showed, that implies that document.IsObject() is false when document.FindMember() fails. Either the JSON you are parsing does not start with an object in its root, or the parse failed. Neither condition of which you are testing for in your code.
If I had to guess (and please don't make people guess!), the failing JSON document likely contains an unencoded line break in it (that is not illegal inside of JSON string values). That would cause std::getline() to exit prematurely, thus causing parsing issues.
The 1st screenshot you showed supports that conclusion, showing that strjson is being split between 2 separate "lines" when the error occurs.
Rather than using std::getline() to read the file line-by-line, risking errors on embedded line breaks, I suggest you try using RapidJSON's BasicIStreamWrapper class to read the file document-by-document instead. ParseStream() has a kParseStopWhenDoneFlag flag that allows parsing multiple root documents from a single input stream:
kParseStopWhenDoneFlag 
After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
For example:
#include <iostream>
#include <fstream>
#include "rapidjson.h"
#include "document.h"
#include "istreamwrapper.h"
using namespace std;
using namespace rapidjson;
void readjson()
{
ifstream handle("meta_Books.json");
if (!handle.is_open())
{
// handle error...
cout << "error opening file" << endl;
}
else
{
BasicIStreamWrapper<ifstream> s(handle);
for(int i = 1; i <= 4; ++i)
{
Document document;
ParseResult pr = document.ParseStream<kParseStopWhenDoneFlag>(s);
if (!pr)
{
// handle error...
cout << "error parsing document " << i << endl;
}
else if (!document.IsObject())
{
cout << "document " << i << " is not an object" << endl;
}
else
{
Value::ConstMemberIterator itr = document.FindMember("asin");
if (itr != document.MemberEnd())
cout << "asin = " << itr->value.GetString() << endl;
else
cout << "asin not found" << endl;
}
}
}
}
int main()
{
readjson();
return 0;
}

How to interact synchroniously with a process in Boost.Process 0.5

This is a question about Boost.Process 0.5, not any later or earlier
version, Boost now contains a Boost.Process library with a different syntax and features.
Suppose I have a simple program that ask for a number and return another number, namely:
// ask.x, simple program with IO
#include<iostream>
int main(){
double n;
std::cout << "number?" << std::endl;
std::cin >> n;
std::cout << n + 1 << std::endl;
}
Now I want to interact with this program programmaticaly by means of Boost.Process 0.5 (http://www.highscore.de/boost/process0.5/boost_process/tutorial.html). When I try to use the library I don't get the expected behavior, the number is never sent to the program. (reading the first line is ok). I tried to write a generalization of the example described in http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.synchronous_i_o but I failed.
MWE, the first half is a lot of necessary boilerplate, also where I think I make the mistake.
#include <boost/process.hpp> // version 0.5
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <string>
#define ALSOSEND // for fully interactive case
using namespace boost;
int main() {
// Boilerplate code, see input only example here https://stackoverflow.com/questions/12329065/how-to-bind-program-termination-with-end-of-stream-in-boost-process-0-5
process::pipe pi = boost::process::create_pipe();
process::pipe po = boost::process::create_pipe();
{
iostreams::file_descriptor_sink sink(
pi.sink,
iostreams::close_handle
);
iostreams::file_descriptor_source source(
po.source,
boost::iostreams::close_handle
);
process::execute(
process::initializers::run_exe("./ask.x"),
process::initializers::bind_stdout(sink)
#ifdef ALSOSEND
, process::initializers::bind_stdin(source)
#endif
);
}
iostreams::file_descriptor_source fdsource(pi.source, iostreams::close_handle);
iostreams::stream<iostreams::file_descriptor_source> is(fdsource);
iostreams::file_descriptor_sink fdsink(po.source, iostreams::close_handle);
iostreams::stream<iostreams::file_descriptor_sink> os(fdsink);
// actual interaction with the process
std::string line;
std::getline(is, line);
assert(line == "number?");
std::cout << "sending: " << "5" << std::endl;
os << "5" << std::endl; // RUN GETS STUCK HERE
std::getline(is, line);
assert(line == "6");
}
Obviously I don't understand the logic of sinks and sources. I also tried using a single pipe for sink and source but it didn't work.
How can I make the program both read and write from and to the executed project?
I cannot find an example which both input and output are interleaved.
EDIT to show the working example with an earlier version of the library
This how it used to be done in Boost.Process GSOC2010 (not 0.5 as
in the question above), note that the actual interaction with the
program is the same as above.
#include <boost/filesystem.hpp> // quasibug in process GSOC2010 needs to include filesystem BEFORE
#include <boost/process.hpp> // version GSOC2010 (not 0.5)
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <string>
using namespace boost;
int main() {
// boiler plate code
std::vector<std::string> args;
process::context ctx;
ctx.process_name = "askprocess";
ctx.streams[process::stdout_id] = boost::process::behavior::pipe();
ctx.streams[process::stdin_id ] = boost::process::behavior::pipe();
process::child c = create_child("./ask", args, ctx);
process::pistream is(c.get_handle(process::stdout_id));
process::postream os(c.get_handle(process::stdin_id ));
// actual interaction with the process
std::string line;
std::getline(is, line);
assert(line == "number?");
std::cout << "sending: " << "5" << std::endl;
os << "5" << std::endl; // RUN GETS STUCK HERE
std::getline(is, line);
assert(line == "6");
}
Seems to be a typo in the following line:
iostreams::file_descriptor_sink fdsink(po.source, iostreams::close_handle);
Must be:
iostreams::file_descriptor_sink fdsink(po.sink, iostreams::close_handle);

How can I write some trace in my log file in C++

I want to write the date of the execution and the end of execution of a file in my log file.
I can't install anything, just use standard module ( I execute my code in command line with linux ).
I want something like this :
[TRACE] 2014-07-24 14:18:50,2014-07-24 14:18:52
I have this result for the moment :
[TRACE] , Start date of execution : Aug 25 2014 : 10:43:02
End date of execution : Mon Aug 25 10:43:06 2014
here my code :
#include <iostream>
#include <string>
#include <fstream>
#include <ctime>
using namespace std;
void startDateExecution(fstream& file) {
if(fichier)
{
file << "[TRACE]" << " , " << "Start date of execution : " << __DATE__ << " : " << __TIME__ << endl;
}
else
cerr << "Unable to open file" << endl;
}
void endDateExecution(fstream& file) {
time_t result = time(NULL);
file << "End date of execution : " << asctime(localtime(&result)) << endl;
file.close();
}
void displayDate(fstream& file) {
startDateExecution(file);
endDateExecution(file);
}
int main(){
fstream file("trace.log", ios::out | ios::trunc);
displayDate(file);
return 0;
}
You can use log4cpp library. It has lots of other features too. There are sample programs available on the following website.
http://log4cpp.sourceforge.net/
You just need to instantiate the appender based on the needs. I have used RollingFileAppender in my project where I needed the log file to be divided after some threshold (i.e. file size reaches 1MB). Then you need to set the pattern in which you want the logs to be written.
Hope this helps.
As many have commented, __DATE__ and __TIME__ refer to the time of compilation, not execution.
You'll need to retrieve the current time both at the start and at the end of the execution; you'll use the same method, whichever one you use, in both cases.
Here's an example of how you can format time using strftime.
std::string format(time_t when)
{
char timestr[256] = {0};
const char* my_format = "%m/%d/%y # %H:%M:%S";
std::strftime(timestr, sizeof(timestr), my_format, std::localtime(&when));
return timestr;
}
You would use it like this:
int main()
{
time_t start = std::time(NULL);
// Do stuff
time_t end = std::time(NULL);
std::cout << "Start: " << format(start) << std::endl
<< "End: " << format(end) << std::endl;
}
Read the documentation for strftime to learn how to specify your own format.