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.
Use the answer in the question: simultaneous read and write to child's stdio using boost.process,
I refactored the code and hybridized the new method using the Boost library. I've been successful in making a pipes connection with Stockfish, but this is also where I get errors I've never seen before, not even Google helps.
Here is what I have tried:
#include <stdio.h>
#include <time.h>
#include <string>
#include <memory.h>
#include <unistd.h>
#include <iostream>
#include <stddef.h>
#include <execinfo.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fstream>
#include </usr/local/include/backtrace.h>
#include </usr/local/include/backtrace-supported.h>
#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <vector>
#include <iomanip>
#include <stdlib.h>
#include <string.h>
using namespace std;
namespace bp = boost::process;
using boost::system::error_code;
using namespace std::chrono_literals;
string errDetails = "Error Details: ";
void delay(int number_of_seconds) {
int ms = 1000 * number_of_seconds;
clock_t start_time = clock();
while (clock() < start_time + ms)
;
}
static void full_write(int fd, const char* buf, size_t len) {
while (len > 0) {
ssize_t ret = write(fd, buf, len);
if ((ret == -1) && (errno != EINTR)) {
break;
}
buf += (size_t) ret;
len -= (size_t) ret;
}
}
void print_backtrace() {
static const char start[] = "--------BACKTRACE--------\n\n";
static const char end[] = "-------------------------\n\n";
void *bt[1024];
int bt_size;
char **bt_syms;
int i;
bt_size = backtrace(bt, 1024);
bt_syms = backtrace_symbols(bt, bt_size);
full_write(STDERR_FILENO, start, strlen(start));
full_write(STDERR_FILENO, errDetails.c_str(), strlen(errDetails.c_str()));
for (i = 1; i < bt_size; i++) {
size_t len = strlen(bt_syms[i]);
full_write(STDERR_FILENO, bt_syms[i], len);
full_write(STDERR_FILENO, "\n", 1);
}
full_write(STDERR_FILENO, end, strlen(end));
free(bt_syms);
}
void abort_application() {
size_t memLeakCount, staticMemLeakCount;
uint64_t memLeakSize, staticMemLeakSize;
for (int i = 0; i < 3; i++) {
/**
* Delay
*/
delay(1);
}
print_backtrace();
abort();
}
inline bool stockfish_check_exists(const std::string& name) {
struct stat buffer;
return (stat(name.c_str(), &buffer) == 0);
}
int main() {
std::future<std::string> data;
boost::asio::io_service svc;
bp::async_pipe in{svc}, out{svc};
string proc = "";
char command[64];
string output = "";
if (stockfish_check_exists("stockfish")) {
proc = "stockfish"; } else {
errDetails = "Stockfish not found!\n\n";
abort_application();
}
std::string const program_dir = proc;
auto on_exit = [](int code, std::error_code ec) {
std::cout << "Exited " << code << "(" << ec.message() << ")\n";
};
bp::child process(proc, bp::std_in < in, svc);
boost::asio::streambuf recv_buffer;
std::cout << "uci send" << std::endl;
boost::asio::async_write(in, boost::asio::buffer("uci\n"),
[&](boost::system::error_code ec, size_t transferred) {
std::cout << "Write: " << transferred << "\n" << std::endl;
in.close();
}
);
std::cout << "isready send" << std::endl;
boost::asio::async_write(in, boost::asio::buffer("isready\n"),
[&](boost::system::error_code ec, size_t transferred) {
std::cout << "Write: " << transferred << "\n" << std::endl;
in.close();
}
);
cout << "Enter your command: ";
cin >> command;
cout << "Your command is: " << command << endl;
if (strcmp(command, "quit") == 0) {
cout << "Quiting......." << endl;
boost::asio::async_write(in, boost::asio::buffer("quit"),
[&](boost::system::error_code ec, size_t transferred) {
std::cout << "Write: " << transferred << std::endl;
in.close();
cout << "Engine quit!" << endl;
}
);
}
svc.run();
return 0;
}
To make it easier to follow, I left out std::std_out > out at the line:
bp::child process(proc, bp::std_in < in, svc);
so that the engine results are immediately displayed in the Terminal window, so I'll know if I've gone astray. And this is when I discovered the strange thing
When I launch the application, it outputs on Terminal as follows:
[2022-01-14 20:25:55]
duythanh#DuyThanhs-MacBook-Pro:/Volumes/Data/ChessGUI$ ./ChessGUI
uci send
isready send
Enter your command: Stockfish 120122 by the Stockfish developers (see AUTHORS file)
id name Stockfish 120122
id author the Stockfish developers (see AUTHORS file)
option name Debug Log File type string default
option name Threads type spin default 1 min 1 max 512
option name Hash type spin default 16 min 1 max 33554432
option name Clear Hash type button
option name Ponder type check default false
option name MultiPV type spin default 1 min 1 max 500
option name Skill Level type spin default 20 min 0 max 20
option name Move Overhead type spin default 10 min 0 max 5000
option name Slow Mover type spin default 100 min 10 max 1000
option name nodestime type spin default 0 min 0 max 10000
option name UCI_Chess960 type check default false
option name UCI_AnalyseMode type check default false
option name UCI_LimitStrength type check default false
option name UCI_Elo type spin default 1350 min 1350 max 2850
option name UCI_ShowWDL type check default false
option name SyzygyPath type string default <empty>
option name SyzygyProbeDepth type spin default 1 min 1 max 100
option name Syzygy50MoveRule type check default true
option name SyzygyProbeLimit type spin default 7 min 0 max 7
option name Use NNUE type check default true
option name EvalFile type string default nn-ac07bd334b62.nnue
uciok
Unknown command: isready
Contrasting with the code above, the two commands were sent through pipes. is uci and isready, this is fine. The first uci command runs successfully, but the isready command, instead of returning readyok, it returns:
Unknown command: isready
I keep trying to type quit, which sends a quit command to the pipe as the exit engine, and it also fails:
Your command is: quit
Quiting.......
Write: 5
Write: 9
Unknown command: quit
Write: 5
Engine quit!
The program will then exit with the engine. I'm still wondering what was going on at the time, but the clues are really hazy as to what was going on behind the scenes.
Please help me. Any help is highly appreciated. Thank you so much everyone
UPDATE: The error continued when Unknown Command: Quit appeared. I typed these commands in Terminal while running Stockfish directly through Terminal, they work as a result, but my program still can't
You are printing to cout as if the async operations happen immediately. That's not the case. The async operations only happen when the io service runs.
svc.run();
Is at the very end of your code. So no async_ operation ever completes (or even starts) before that.
Other problems:
Your out async pipe is never used (not even connected). It's unclear to me how you intend to communicate with the child process that way.
In fairness, you only every write to the child process, so maybe you're not at all interested in the output. (But then perhaps recv_buffer can be deleted just as well).
Your buffers include the terminating NUL characters. (asio::buffer("uci\n") sends {'u','c','i','\n','\0'}). That's going to mess up the child processes's parsing.
You do in.close() in response to every single async_write completion. This guarantees that subsequent writes never can happen, as you closed the pipe.
Then when you send quit you fail to include the '\n' as well
You are reading into a char[64] with operator>> which makes no sense at all. Maybe you are using c++20 (so width of 64 might be assumed) but you never set a width. Most likely you would want to read into a string instead.
However, doing so cannot accept commands with whitespace (because std::ios::skipws is set by default). So, likely you wanted std::getline instead...
The fact that you include a boatload of C headers makes me think you're porting some C code (badly). That's also exemplified by the strcmp use and others, e.g. no need to use ::stat
Don't use using namespace std; (Why is "using namespace std;" considered bad practice?)
Don't use global variables (errDetails)
Don't use loops to wait for a time delay
No need to manually print backtraces. Instead, use Boost:
void abort_application(std::string const& errDetails) {
std::cerr << errDetails << "\n";
std::cerr << boost::stacktrace::stacktrace{} << std::endl;
std::this_thread::sleep_for(3s);
abort();
}
Existing Stockfish Client: Playing Games
You're in luck: I have a written full demo using stockfish on this site: Interfacing with executable using boost in c++.
This example shows how to correctly await and parse expected replies from the child process(es).
You will note that I chose coroutines for the async version:
Just for completeness, I thought I'd try an asynchronous implementation. Using the default Asio callback style this could become unwieldy, so I thought to use Boost Coroutine for the stackful coroutines. That makes it so the implementation can be 99% similar to the synchronous version
Just for comparison, here's what your code should look like if you didn't use coroutines:
Fixing Up Your Code
Live On Coliru
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <boost/stacktrace/stacktrace.hpp>
#include <chrono>
#include <iomanip>
#include <iostream>
namespace bp = boost::process;
using boost::system::error_code;
using namespace std::literals;
static void abort_application(std::string const& errDetails) {
std::cerr << errDetails << "\n";
std::cerr << boost::stacktrace::stacktrace{} << std::endl;
std::this_thread::sleep_for(3s);
abort();
}
inline static bool stockfish_check_exists(std::string& name) {
return boost::filesystem::exists(name);
}
int main() {
boost::asio::io_service svc;
bp::async_pipe in{svc};
std::string proc = "/usr/games/stockfish";
if (!stockfish_check_exists(proc)) {
abort_application("Stockfish not found!");
}
auto on_exit = [](int code, std::error_code ec) {
std::cout << "Exited " << code << "(" << ec.message() << ")\n";
};
bp::child process(proc, bp::std_in < in, svc, bp::on_exit = on_exit);
std::function<void()> command_loop;
std::string command_buffer;
command_loop = [&] {
std::cout << "Enter your command: " << std::flush;
// boost::asio::streambuf recv_buffer;
if (getline(std::cin, command_buffer)) {
std::cout << "Your command is: " << command_buffer << std::endl;
command_buffer += '\n';
async_write( //
in, boost::asio::buffer(command_buffer),
[&](error_code ec, size_t transferred) {
std::cout << "Write: " << transferred << " (" << ec.message() << ")" << std::endl;
if (command_buffer == "quit\n") {
std::cout << "Quiting......." << std::endl;
// in.close();
std::cout << "Engine quit!" << std::endl;
} else {
command_loop(); // loop
}
});
}
};
std::cout << "uci send" << std::endl;
async_write(
in, boost::asio::buffer("uci\n"sv),
[&](error_code ec, size_t transferred) {
std::cout << "Write: " << transferred << "\n" << std::endl;
std::cout << "isready send" << std::endl;
async_write(in, boost::asio::buffer("isready\n"sv),
[&](error_code ec, size_t n) {
std::cout << "Write: " << n << std::endl;
command_loop(); // start command loop
});
});
svc.run(); // only here any of the operations start
}
Prints, e.g.
Or if Stockfish is in fact installed:
I am building a web scraper that downloads the HTML from a web page, parses it, and displays the time in the various time zones across the US. I got the example code from Rosetta Code. However, they use Boost 1.46.1 for Windows, where as I am using Boost 1.60.0 for Mac OSX. Below is the code that I have modified from the Rosetta Code Example in an effort to get it working.
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/regex.hpp>
#include <boost/asio.hpp>
#include <boost/system/config.hpp>
#include <boost/asio/ip/tcp.hpp>
void GetTime()
{
boost::asio::ip::tcp::iostream s("tycho.usno.navy.mil","http");
cout << s << "\n"; //check to see what downloaded from URL
if(!s){ //if S = Null then nothing downloaded & connection not made
cout << "Error! Not Connected." << endl;
s << "Get /cgi-bin/timer.pl HTTP/1.0\r\n"
<< "host:tycho.usno.navy.mil\r\n"
<< "Acceot:*/*\r\n"
<< "Connection:closer\r\n\r\n";//error information provided
}
int count = 0;
for (string line; getline(s, line);){
boost::smatch matches;
if(boost::regex_search(line, matches, boost::regex("<BR>'(.+\\s+UTC)'<BR>"))){
cout << matches[count];//parse the HTML, if there is a match save it in matches[count]
cout << ">> Matches" << count << "\n";
//++ count;
break;
}
++ count;
cout << "End of For Loop.\n";//to check if the for loop ran
}
cout << "Finale Count: " << count << " End of Void GetTime.\n";//to check if the void was completed
}
The output:
0x7fff5fbff430
Final Count: 0 End of Void GetTime.
RUN FINISHED; exit value 0; real time: 20s; user: 0ms; system: 0ms
Based on the Final Count being "0", I can conclude that the program never enters the for-loop. Are the conditions of the For-Loop and If-statement correct for this application? Or is the problem with the the line boost::asio::ip::tcp::iostream s("tycho.usno.navy.mil","http"); line that is calling up the webpage and placing the HTML in string S?
Looks like you've made mistake in error condition in first if. When I changed
if(!s) //if S = Null then nothing downloaded & connection not made
{
cout << "Error! Not Connected." << endl;
s << "Get /cgi-bin/timer.pl HTTP/1.0\r\n"
<< "host:tycho.usno.navy.mil\r\n"
<< "Acceot:*/*\r\n"
<< "Connection:closer\r\n\r\n";//error information provided
}
to
if(!s)
{
cout << "Error! Not Connected." << endl;
return;
}
s << "Get /cgi-bin/timer.pl HTTP/1.0\r\n"
<< "host:tycho.usno.navy.mil\r\n"
<< "Accept:*/*\r\n"
<< "Connection:closer\r\n\r\n";//error information provided
I got following output:
0x7ffdc0a5d730
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
End of For Loop.
Finale Count: 16 End of Void GetTime.
Which I think is expected output. Note that you also have typo in Accept word in your request.
Below is a simple class which attempts to write an integer to a file. The mode of writing the file is to append characters at the end of the file (In this mode, file should be created if it doesn't exist)
#include <iostream>
#include <fstream>
class TestFileStream
{
private:
std::ofstream* _myFileStream;
bool isFileOpen;
public:
TestFileStream():isFileOpen(false)
{
_myFileStream = new std::ofstream("TestFile.txt", std::ios_base::out | std::ios_base::app );
isFileOpen = _myFileStream->is_open();
if( !isFileOpen )
{
std::cout << "Unable to open log file" << std::endl;
std::cout << "Good State: " << _myFileStream->good() <<std::endl;
std::cout << "Eof State: " << _myFileStream->eof() <<std::endl;
std::cout << "Fail State: " << _myFileStream->fail() <<std::endl;
std::cout << "Bad State: " << _myFileStream->bad() <<std::endl;
}
else
{
std::cout << "Opened log file" << std::endl;
}
}
~TestFileStream()
{
_myFileStream->close();
delete _myFileStream;
_myFileStream = nullptr;
}
void WriteFile( unsigned number )
{
if ( isFileOpen )
{
(*_myFileStream) << "Number: " << number << std::endl;
}
}
};
int main()
{
// Number of iterations can be multiple.
// For testing purpose, only 1 loop iteration executes
for( unsigned iter = 1; iter != 2; ++iter )
{
TestFileStream fileWriteObj;
fileWriteObj.WriteFile( 100+iter );
}
return 0;
}
When I execute the above code, I get following log output:
Unable to open log file
Good State: 0
Eof State: 0
Fail State: 1
Bad State: 0
This seems like trivial task, but I am not able to find out whats causing the failure. Note that this question is most likely related to the following question
Just to summarize the comments, there is nothing wrong about the code you posted (apart from the rather unconventional new ostream ;) )
Note however that opening files may fail for a number of reasons (Permissions, file in use, disk unavailable, the file does not exist, the file exists...). That is why you must always test it.
If you tried to run the above code in an online emulator, then chances are file IO is disabled. Which would explain why you get that the streams fail-bit is set.
I have some code that writes the system time to a file:
std::ofstream file("time.txt");
char *date;
time_t timer;
timer=time(NULL);
date = asctime(localtime(&timer));
while ( true ) {
std::cout << date << ", " << randomNumber << std::endl;
if (file.is_open())
{
file << date;
file << ", ";
file << randomNumber;
file << "\n";
}
}
file.close()
When I let my program run and stop it in-between (its an infinite while loop), I am able to get data written to my file.
However, if I merely change the code to add a Sleep() timer. No data is written to my file. But I do see an output on the screen. Is this expected behavior? How do I ensure that even if I end my program execution mid-way, values are written to the file?
std::ofstream file("time.txt");
char *date;
time_t timer;
timer=time(NULL);
date = asctime(localtime(&timer));
while ( true ) {
**Sleep(100); // wait for 100 milli-seconds**
std::cout << date << ", " << randomNumber << std::endl;
if (file.is_open())
{
file << date;
file << ", ";
file << randomNumber;
file << "\n";
}
}
file.close()
If I close my file right after the sleep timer, it writes the data out. But the main reason I'm adding the timer, is that I want to slow-down how often my file is being written to ...
You need to flush the buffer so the contents are written to the file. Call std::flush or change file << "\n"; to file << std::endl; to flush the stream. When you don't call Sleep in your program, the contents of the buffer are written as soon as the buffer becomes full, however, with Sleep the buffer doesn't become full right away because there is a delay, so you don't see the contents written to the file.