How can i disable/ignore cerr output stream in JetBrains CLion? - c++

I have a tool, that makes many cerr outputs.
if i run it over "run configuration"s in Clion i see all the cerr messages in the output window.
How can i disable some output stream in Clion/Intellij?
I use windows 10.

You should redirect the cerr output to a file.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ofstream output("output.txt");
std::streambuf* p_cerrbuffer=std::cerr.rdbuf();
std::cerr.rdbuf(output.rdbuf()); // redirecting to a file
std::cout<<"cout"<<std::endl; // "cout" appears on the standard output.
std::cerr<<"cerr"<<std::endl; // "cerr" appears in the output.txt file
}

Related

text file is not being opened for reading purposes

Before you flag this as a duplicate post and refer me on how to correctly open a text file and print to the console, I have looked at numerous StackOverflow posts about this topic and cannot find a solution for myself.
I am trying to open a text file I created (currently in the same project folder as my main.cpp), read the text, and print it to the console. I go through the if file is open statement fine but the while loop does not go through even once. I will post the function below. Please suggest any changes or ideas on how to correctly call and open/read the text file. (and I would prefer not to call the exact file location of the text file for this to work ex. C://example/textFile.txt/ Though I have not tried this method yet, I'd prefer avoiding it)
Also, I am using CLion IDE from jetbrains, C++17, and Ninja to build.
printing text file to console fucntion
#include <iostream>
#include <iomanip>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdlib.h>
#include "printTest.h"
void printTest::print() {
std::string line; //string that holds the line of a text file
std::ifstream textFile("test.txt", std::ios::in); //file creation
if(textFile.is_open()) //checking if file was opened
{
while(std::getline(textFile, line))
{
//std::getline(textFile, line);
std::cout << line << "\n";
}
} else { //this is always printing i.e. file is not correctly being opened for reading
std::cout <<"Unable to open the text file..." <<std::endl; //Prints if file was not opened
}
textFile.close();
}

Why could file not be opened using ifstream?

I'm trying to create a simple terminal program that generates random Japanese Gojuōn. I have a source file, named "source", which looks something like this:
A I U E O
Ka Ki Ku Ke Ko
...
あ い う え お
か き く け こ
...
Now, I'm trying to read each line of content into a string variable, and print it out onto the screen, but I was not able to open the file. Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream source ("source");
string line;
if (source.is_open())
{
while (getline(source, line))
{
cout << line << "\n";
}
source.close();
}
else cout << "Unable to open file!\n";
}
When I ran the code on terminal, I got "Unable to open file!". The code was in the same directory as the source file.
Are you running from inside your IDE? This is a very common thing when using an IDE.
The current working directory when running from the IDE may not be what you think it is. Try changing the path to the file to be the absolute path so you KNOW it's finding it.

Sending user inputted commands to an arduino in c++ using system() on a linux terminal

Using a c++ program i can successfully send commands to an arduino. The code uses the command:
system("$echo [command] > dev/ttyACM0");
Currently i must manually input the commands into this space, I was wondering if it's possible for a user to input the command, and for it to then be added to the string within system()?
This is an approximation of what I think you want:
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::string command;
if(std::getline(std::cin, command)) { // read user input
std::ofstream ard("/dev/ttyACM0"); // open the device
if(ard) {
ard << command << '\n'; // send the command
}
} // here `ard` goes out of scope and is closed automatically
}
Note that you do not need the unsafe system() command at all here. Just open the device and send the string directly.

Always output to screen and allow redirection

I'm writing a small CLI application and I want to allow the user to redirect to a file while standard cout statements go to the output.txt file I want progress to always to go the screen.
./myApp > output.txt
10% complete
...
90% complete
Completed
Is this possible? How can I do it?
Thanks in advance!!
This will work even if both stdin and stdout have been redirected:
spectras#etherbee:~$ ./term
hello terminal!
spectras#etherbee:~$ ./term >/dev/null 2>&1
hello terminal!
The idea is to open the controlling terminal of the process directly, bypassing any redirection, like this:
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/tty", O_WRONLY);
if (fd < 0 && errno != ENODEV) {
/* something went wrong */
return 1;
}
int hasTTY = (fd >= 0);
if (hasTTY) {
write(fd, "hello terminal!\n", 16);
}
return 0;
}
From man 4 tty:
The file /dev/tty is a character file with major number 5 and
minor number 0, usually of mode 0666 and owner.group root.tty. It is
a synonym for the controlling terminal of a process, if any.
If you're using C++, you might want to wrap the file descriptor into a custom streambuf, so you can use regular stream API on it. Alternately, some implementations of the C++ library offer extensions for that purpose. See here.
Or, if you don't care about getting the error code reliably, you could just std::ofstream terminal("/dev/tty").
Also as a design consideration if you do this, offering a quiet option to let the user turn off the writing to the terminal is a good idea.
Your process cannot know if the shell redirects the standard console output (std::cout) or not.
So you'll need another handle that lets you output to the terminal independently of that redirection.
As #Mark mentioned in their comment you could (ab-)use1 std::cerr to do that, along with some ASCII trickery to overwrite the current output line at the terminal (look at backspace characters: '\b').
1)Not to mention the mess printed at the terminal if the output isn't actually redirected.
You can write your progress indicators to the stderr stream. They will appear on the console if the user redirects stdout to a file.
For example:
fprintf(stderr, "10%% complete\n");
I figured out how to do it, even if the user redirects stderr. The following code gets the name of the current terminal and checks to see if our output is being redirected. It also has a my_write() function that allows you to write to both the terminal and the redirect file, if they've redirected stdout. You can use the my_write() function with the writetoterm variable where-ever you want to write something that you want to always be written to the terminal. The extern "C" has to be there, otherwise (on Debian 9 with GCC 6.3, anyway) the ttyname() function will just return NULL all the time.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <sstream>
using std::string;
using std::fstream;
using std::cout;
using std::endl;
using std::cerr;
using std::stringstream;
void my_write(bool writetoterm, int termfd, string data)
{
if(writetoterm)
{
int result = write(termfd, data.c_str(), data.length());
if(result < data.length()){
cerr << "Error writing data to tty" << endl;
}
}
cout << data;
}
extern "C" {
char* GetTTY(int fd){
//printf("%s", ttyname(fd));
return ttyname(fd);
}
}
int main(int argc, char** argv){
getenv("TTY");
bool writetoterm = false;
struct stat sb = {};
if(!GetTTY(STDOUT_FILENO)){
//not a TTY
writetoterm = true;
}
int ttyfd = open(GetTTY(2), O_WRONLY);
if(ttyfd < 0){
//error in opening
cout << strerror(errno) << endl;
}
string data = "Hello, world!\n";
my_write(true, ttyfd, data);
int num_for_cout = 42;
stringstream ss;
ss << "If you need to use cout to send something that's not a string" << endl;
ss << "Do this: " << num_for_cout << endl;
my_write(writetoterm, ttyfd, ss.str().c_str());
return 0;
}
I found the official std:: method of handling this. There is another type... std::clog. This is specifically for information and always appears on the command line even though the user redirects the output of the program myProgram > out.txt.
Thanks this was great to see all the methods that this can be done.

C++ write to file error with full PATH from GetEnvironmentVariable()

I'm noob in C++ but wanting to learn. I have a little program that writes some info to my \etc\hosts in Windows; I get the %WINDIR% variable via GetEnvironmentVariable(), if I put the full path manually everything is ok, but when I substitute with WINDIR variable my code isn't compiling. I know I don't do something right.
#include <windows.h>
#include <ios>
#include <fstream>
char buffer[1000];
int main() {
GetEnvironmentVariable("WINDIR",(char*)&buffer,sizeof(buffer));
std::ofstream log;
log.open("%s\\system32\\drivers\\etc\\hosts", buffer);
log << "127.0.0.1 domain.com\n" << std::endl;
return 0;
}
I get really ugly errors like:
C:\Documents and Settings\xtmtrx\Desktop\coding\windir.cpp no matching function for call to `std::basic_ofstream<char, std::char_traits<char> >::open(const char[30], char[1000])'
ofstream cannot format the path for you. You need to do that separately, eg:
#include <windows.h>
#include <ios>
#include <fstream>
char buffer[1000] = {0};
int main() {
GetEnvironmentVariable("WINDIR",buffer,sizeof(buffer));
strcat(buffer, "\\system32\\drivers\\etc\\hosts");
std::ofstream log;
log.open(buffer, ios_base::ate);
log << "127.0.0.1 domain.com\n" << std::endl;
return 0;
}
FYI, you should use GetWindowsDirectory(), GetSystemDirectory(), SHGetSpecialFolderPath() or SHGetKnownFolderPath() instead of GetEnvironmentVariable(). And you should use PathCombine() when concantenating paths together so it can ensure the slashes are correct.
open("%s\\system32\\drivers\\etc\\hosts", buffer); open doesn't understand format strings..you are using %s does not make sense. learn here
Try like this:
GetEnvironmentVariable("WINDIR",buffer,sizeof(buffer));
strcat(buffer, "\\system32\\drivers\\etc\\hosts");
std::ofstream log;
log.open(buffer.str().c_str(), ios_base::ate);
You need to concate the string together like this:
LPTSTR windir[MAX_PATH];
LPTSTR fullpath[MAX_PATH];
GetWindowsDirectory(windir, MAX_PATH);
if(PathCombine(fullpath, windir, _T("system32\\drivers\\etc\\hosts")) != NULL) {
std::ofstream log;
log.open(buffer, ios_base::ate);
log << "127.0.0.1 domain.com\n" << std::endl;
}
At first you need to concate the directory and the file part with PathCombine. Then you can open the file and write the content. You should also note that you need admin permissions to change this file and some antivirus programmes may reject the access of the hosts file.