I'm using boost::asio to read from a serial port. I continuously read from the serial port and print it out through std::cout. But some strange things happens.
I'm using TimeoutSerial class from here. My code goes like this:
#include <iostream>
#include "TimeoutSerial.h"
using namespace std;
int main(){
TimeoutSerial serial;
serial.open("/dev/ttyACM0", 9600 );
serial.setTimeout(boost::posix_time::seconds(1));
char c = '0';
while(true){
try{
serial.read( &c, 1 );
cout << c;
}catch( std::runtime_error err ){
cout << "Error: " << err.what()<< endl;
}
}
return 0;
}
I get no output and I have no idea why. When I change cout << c; to cout << c << endl; I get the output I want but each character is on a new line which is undesirable.
So can anyone tell me why is this happening?
std::cout is buffered by default, so you need to flush it to display it on your terminal. Using std::endl does this implicitly, as will std::flush(). Change your loop to
while(true) {
try {
serial.read( &c, 1 );
cout << c;
std::flush( std::cout );
} catch ( std::runtime_error err ) {
cout << "Error: " << err.what() << endl;
}
}
Related
I am currently trying to run simple tests with the Stockfish chess engine in C++ to get the best possible move. I am starting Stockfish as a child process and want to use the input and output streams to pass on the desired UCI commands, which I am exchanging with the parent process via a pipe. However, when I run the code, Stockfish just starts and nothing else happens. Typing in the UCI commands in the CLI then works, but that's obviously not the goal. What am I doing wrong?
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
void sig_handler(int sig) {}
int main() {
int fd1[2];
if (pipe(fd1) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid == 0) {
execl("./stockfish", "./stockfish", nullptr);
close(fd1[1]);
char position[60];
read(fd1[0], position, 60);
close(fd1[0]);
cout << "position " << position << endl;
cout << "go" << endl;
sleep(5000);
cout << "stop" << endl;
string move;
cin >> move;
exit(0);
}
else {
close(fd1[0]);
cout << "Parent process" << endl;
string line = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
write(fd1[1], line.c_str(), strlen(line.c_str()) + 1);
close(fd1[1]);
signal(SIGINT, &sig_handler);
wait(NULL);
cout << "Parent done" << endl;
}
return 0;
}
Thanks to #TedLyngmo and some research about the Boost library, it was very easy to implement:
#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
using namespace std;
namespace bp = boost::process;
int main() {
bp::ipstream is;
bp::opstream os;
bp::child c("./stockfish", bp::std_in < os, bp::std_out > is);
os << "uci" << endl;
os << "isready" << endl;
os << "position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" << endl;
os << "go depth 30" << endl;
string line;
string move_string;
while (getline(is, line)) {
if (!line.compare(0, 8, "bestmove")) {
move_string = line;
break;
}
}
// Delete the "bestmove" part of the string and get rid of any trailing characters divided by space
move_string = move_string.substr(9, move_string.size()-9);
vector<string> mv;
boost::split(mv, move_string, boost::is_any_of(" "));
cout << "Stockfish move: " << mv.at(0) << endl;
return 0;
}
I want to use Rtmidi to get input from launchpad.
However, despite connecting the launchpad, 0 pods are available.
"MidiInDummy: This class providers no functionality."
There's also this phrase, so something seems to be wrong.
Source:
//Source : http://www.music.mcgill.ca/~gary/rtmidi/index.html#probing
#define __WINDOWS_MM__
#include <iostream>
#include <cstdlib>
#include "RtMidi.h"
int main()
{
RtMidiIn* midiin = 0;
RtMidiOut* midiout = 0;
// RtMidiIn constructor
try {
midiin = new RtMidiIn();
}
catch (RtMidiError& error) {
error.printMessage();
exit(EXIT_FAILURE);
}
// Check inputs.
unsigned int nPorts = midiin->getPortCount();
std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n";
std::string portName;
for (unsigned int i = 0; i < nPorts; i++) {
try {
portName = midiin->getPortName(i);
}
catch (RtMidiError& error) {
error.printMessage();
goto cleanup;
}
std::cout << " Input Port #" << i + 1 << ": " << portName << '\n';
}
// RtMidiOut constructor
try {
midiout = new RtMidiOut();
}
catch (RtMidiError& error) {
error.printMessage();
exit(EXIT_FAILURE);
}
// Check outputs.
nPorts = midiout->getPortCount();
std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n";
for (unsigned int i = 0; i < nPorts; i++) {
try {
portName = midiout->getPortName(i);
}
catch (RtMidiError& error) {
error.printMessage();
goto cleanup;
}
std::cout << " Output Port #" << i + 1 << ": " << portName << '\n';
}
std::cout << '\n';
// Clean up
cleanup:
delete midiin;
delete midiout;
return 0;
}
Output:
MidiInDummy: This class provides no functionality.
There are 0 MIDI input sources available.
MidiOutDummy: This class provides no functionality.
There are 0 MIDI output ports available.
How can I solve this problem?
Oh, I solved it.
https://www.music.mcgill.ca/~gary/rtmidi/#compiling
https://github.com/thestk/rtmidi/issues/85
keyword : __WINDOWS_MM__, winmm.lib
I want to know how can i read the standard input just for 5 seconds like you just have 5 seconds to write.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
Like that the user have all the time he want to write. Did getline or read have any option to force the getline to stop after 5sec ?
Thank you
A possible solution is to use poll() and write your own getline() function (tested on xubuntu 18.04 with g++ 7.5.0):
Here the implementation of my getline_timeout(int, std::string):
std::string getline_timeout(int ms, std::string def_value)
{
struct pollfd fds;
fds.fd = STDIN_FILENO;
fds.events = POLLIN;
int ret = poll(&fds, 1, ms);
std::string val;
if (ret > 0 && ((fds.revents & POLLIN) != 0)) {
//cout << "has data" << endl;
std::getline(std::cin, val);
} else {
//cout << "timeout / no data" << endl;
val = def_value;
}
return val;
}
#include <iostream>
#include <string>
#include <poll.h>
#include <unistd.h>
std::string getline_timeout(int ms, std::string def_value);
int main(int argc, char *argv[])
{
std::cout << "What's your name ? " << std::flush;
// Ask for the name
std::string mystr = getline_timeout(5000, "John Doe");
std::cout << "Hello " << mystr << std::endl;
std::cout << "What is your favorite team ? " << std::flush;
// Ask for the team
mystr = getline_timeout(5000, "Gryffindor");
std::cout << "I like " << mystr << " too!" << std::endl;
return 0;
}
The API getline() can not do what you want.
There are two way you can try:
- multi thread can work
- single thread with multiplexing IO like select/poll/epoll/iocp
In fact, they work same : setting a timer and wait for I/O input or timeout.
When using a FIFO on a single process, it looks like after both ends have been opened and one is then closed, it is not possible to reuse the FIFO. Any attempt to reopen the closed end fails or the returned file descriptor is useless.
Is it possible to work around this behavior, or do we have to keep both ends of the FIFO open until we are absolutely sure we don't need it anymore?
Here is some test code that shows and attempt to reopen a closed write end of a FIFO:
#include <iostream>
#include <cstdio>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
using namespace std;
int main(int argc, const char **argv)
{
cout << "Creating an instance of a named pipe..." << endl;
mode_t prevMask = umask(0);
if (mknod("my_pipe", S_IFIFO | 0666, 0))
return -1;
umask(prevMask);
cout << "Opening Read end..." << endl;
int fdM = open("my_pipe", O_RDONLY | O_NONBLOCK);
if (fdM == -1)
return -1;
cout << "Opening Write end..." << endl;
int fdS = open("my_pipe", O_WRONLY | O_NONBLOCK);
if (fdS == -1)
return -1;
cout << "Sending data to pipe..." << endl;
const char *data = "Hello my friend!";
ssize_t NbOfBytesWritten = write(fdS, data, strlen(data));
if (NbOfBytesWritten < 0)
return -1;
cout << "Number of bytes sent: " << NbOfBytesWritten << endl;
cout << "Closing Write end..." << endl;
if (close(fdS))
return -1;
cout << "Reopening Write end..." << endl;
fdS = open("my_pipe", O_WRONLY | O_NONBLOCK);
if (fdS == -1)
{
cout << "open() - failed("<< errno << "): " << strerror(errno) << '.';
remove("my_pipe");
return -1;
}
cout << "Sending some more data to pipe..." << endl;
data = "What's up?";
NbOfBytesWritten = write(fdS, data, strlen(data));
if (NbOfBytesWritten < 0)
return -1;
cout << "Number of bytes sent: " << NbOfBytesWritten << endl;
cout << "Reading data from pipe..." << endl;
char buff[128];
ssize_t numBytesRead = read(fdM, buff, 127);
if (NbOfBytesWritten < 0)
return -1;
buff[numBytesRead] = '\0'; // null terminate the string
cout << "Number of bytes read: " << numBytesRead << endl;
cout << "Message: " << buff << endl;
cout << "Closing Write end..." << endl;
if (close(fdS))
return -1;
cout << "Closing Read end..." << endl;
if (close(fdM))
return -1;
cout << "Deleting pipe..." << endl;
if (remove("my_pipe"))
return -1;
return 0;
}
Here is the output:
Creating an instance of a named pipe...
Opening Read end...
Opening Write end...
Sending data to pipe...
Number of bytes sent: 16
Closing Write end...
Reopening Write end...
open() - failed(6): No such device or address.
I also tested similar code trying to reopen a closed read end (While the write end was kept open). In that case the open() function succeed, but the read() function using the file descriptor returned by open() fails with:
Communication error on send. (70)
EDIT:
I'm using CYGWIN.
You code works fine on Linux. I think the issue you are running into is that named pipes on CYGWIN don't work very well and fail to follow POSIX semantics. See FIFO (named pipe) is broken on Cygwin. Likely the same problem you have.
I wanna write in file and then read from it and print the result
Here is my code
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc,char* argv[]){
int x,y;
ofstream fd1(argv[1]);
ifstream fd2(argv[1]);
cin>>x;
fd1<<x;
fd2>>y;
cout<<"just read "<<y<<endl;
fd1.close();
fd2.close();
return 0;
}
What's wrong with it? I input 123 it outputs "just read -1078463800"
Even if you can open both in read & write, this write operation is buffered, which means that it may not be written to disk unless you flush the stream (or you close the file).
Of course the code below works perfectly:
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc,char* argv[]){
int x,y;
ofstream fd1(argv[1]);
cin>>x;
fd1<<x;
fd1.close();
ifstream fd2(argv[1]);
if (fd2.good())
{
cout << "read OK" << endl;
}
fd2>>y;
cout<<"just read "<<y<<endl;
fd2.close();
return 0;
}
The fd2>>y statement is failing because there is nothing to read from the file yet. std::ofstream buffers its output, and you haven't flushed the buffer to the file on disk before trying to then read from the file.
std::ofstream flushes its buffer when:
a new line is written.
its flush() method is called, either directly or when std::flush or std::endl is streamed to it.
Try this:
fd1 << x << flush;
Or:
fd1 << x;
fd1.flush();
On a side note, you really should be checking for errors along the way. The std::ofstream and std::ifstream constructors could fail to create/open the file. The << and >> operators could fail to write/read values. All of those operations can report errors that you can check for. For example:
#include <iostream>
#include <fstream>
int main(int argc, char* argv[])
{
int x, y;
std::ofstream fd1(argv[1]);
std::ifstream fd2(argv[1]);
if (!fd1.is_open())
{
std::cout << "cannot create output file" << std::endl;
}
else if (!fd2.is_open())
{
std::cout << "cannot open input file" << std::endl;
}
else if (!(std::cin >> x))
{
std::cout << "invalid input" << std::endl;
}
else if (!(fd1 << x << std::flush))
{
std::cout << "cannot write to output file" << std::endl;
}
else if (!(fd2 >> y))
{
std::cout << "cannot read from input file" << std::endl;
}
else
{
std::cout << "just read " << y << std::endl;
}
return 0;
}
Alternatively:
#include <iostream>
#include <fstream>
int main(int argc, char* argv[])
{
int x, y;
std::ofstream fd1;
std::ifstream fd2;
fd1.exceptions(std::ofstream::failbit);
fd2.exceptions(std::ifstream::failbit);
std::cin.exceptions(std::ifstream::failbit);
try
{
fd1.open(argv[1]);
fd2.open(argv[1]);
std::cin >> x;
fd1 << x << std::flush;
fd2 >> y;
std::cout << "just read " << y << std::endl;
}
catch (const std::ios_base::failure &e)
{
std::cout << "error! " << e.what() << std::endl;
}
return 0;
}