Why the code below doesn't produce any output? I expected it to be 42 s. How to fix it?
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
void foo(const char* format, ...)
{
va_list args;
va_start(args, format);
printf(format, args);
va_end(args);
}
int main()
{
foo("%d %s\n", 42, "s");
return 0;
}
http://ideone.com/EsHsRO
Actually, it produces http://codepad.org/k7ld231E.
Why the foo is wrong?
You need to use vprintf instead: int vprintf( const char* format, va_list vlist );
vprintf(format, args);
printf() and friends are for normal use. vprintf() and friends are for when you want to write your own printf()-like functions.
Related
I am implementing a mex script, where at some point I need to call a function from an external library. This function is as simple as printing the provided input, which is though collected as arguments and passed to vprintf(). See below:
void PrintInfo(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
The issue now is that once I call the PrintInfo() function inside my mex script for example:
PrintInfo("Give me %i apples.\n", 3);
I am not able to get any output in the matlab's console prompt, like I do when I used printf() or cout instead. I was trying to figure it out myself but no chance so far, thus I would appreciate if someone could explain me what is the issue and how I can bypass it.
Altering the library's files is not possible, thus I am looking for a solution that can be done on mex script from my side.
Update: For example in the following mex script from the printing functions only the PrintInfo() does not show anything:
#include "mex.h"
// cpp system headers
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdarg>
using namespace std;
void PrintInfo(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
void foo()
{
printf("Vector size is: %i \n", 5);
}
void foo1(const char *format, int sz)
{
printf(format, sz);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
PrintInfo("Vector size is: \n", 10);
foo();
foo1("Vector size is: %i \n", 2);
cout << "Vector size is:" << 4 << endl;
}
I want to have only one function to write logs which would parse ellipsis and send result to the Boost::log, based on severity level. In header file would be defined different macros, which would select a correct severity level. There is the code:
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#define DEBUG(msg, ...) Logger::write_log(debug, msg, ##__VA_ARGS__);
#define INFO(msg, ...) Logger::write_log(info, msg, ##__VA_ARGS__);
#define WARNING(msg, ...) Logger::write_log(warning, msg, ##__VA_ARGS__);
#define ERROR(msg, ...) Logger::write_log(error, msg, ##__VA_ARGS__);
namespace logging = boost::log;
void write_log(auto level, const char *message, ...)
{
char buffer[512];
va_list args;
// Parse ellipsis and add arguments to message
va_start (args, message);
vsnprintf (buffer, sizeof(buffer), message, args);
va_end (args);
BOOST_LOG_TRIVIAL(level) << buffer;
}
int main(int argc, char** argv)
{
DEBUG("Test string %s", "additional string");
return 0;
}
But during compilation I get the next error:
error: 'level' is not a member of 'boost::log::v2s_mt_nt5::trivial'
BOOST_LOG_TRIVIAL(level) << buffer;
Seems that my level argument have an incorrect type. I also tried to use logging::trivial::severity_level level instead of auto level, but this didn't help. How can I fix this error?
UPDATED:
there is working solution:
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#define DEBUG(msg, ...) Logger::write_log(debug, msg, ##__VA_ARGS__);
#define INFO(msg, ...) Logger::write_log(info, msg, ##__VA_ARGS__);
#define WARNING(msg, ...) Logger::write_log(warning, msg, ##__VA_ARGS__);
#define ERROR(msg, ...) Logger::write_log(error, msg, ##__VA_ARGS__);
namespace logging = boost::log;
enum severity_level
{
debug,
info,
warning,
error,
exception
};
src::severity_logger<severity_level> slg;
void write_log(severity_level level, const char *message, ...)
{
char buffer[512];
va_list args;
// Parse ellipsis and add arguments to message
va_start (args, message);
vsnprintf (buffer, sizeof(buffer), message, args);
va_end (args);
BOOST_LOG_SEV(slg, level) << buffer;
}
int main(int argc, char** argv)
{
DEBUG("Test string %s", "additional string");
return 0;
}
Follow boost log example and define:
// severity levels
enum severity_level
{
trace,
debug,
info,
warning,
error,
fatal
};
And you need to make your function to accept proper type:
void write_log(severity_level level, const char *message, ...){ ... }
Another option:
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#define DEBUG(msg, ...) Logger::write_log(logging::trivial::debug, msg, ##__VA_ARGS__);
#define INFO(msg, ...) Logger::write_log(logging::trivial::info, msg, ##__VA_ARGS__);
#define WARNING(msg, ...) Logger::write_log(logging::trivial::warning, msg, ##__VA_ARGS__);
#define ERROR(msg, ...) Logger::write_log(logging::trivial::error, msg, ##__VA_ARGS__);
namespace logging = boost::log;
#define LOG_TRIVIAL(lvl)\
BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
(::boost::log::keywords::severity = lvl))
void write_log(logging::trivial::severity_level level, const char *message, ...)
{
char buffer[512];
va_list args;
// Parse ellipsis and add arguments to message
va_start(args, message);
vsnprintf(buffer, sizeof(buffer), message, args);
va_end(args);
LOG_TRIVIAL(level) << buffer;
}
int main(int argc, char** argv)
{
DEBUG("Test string %s", "additional string");
return 0;
}
My advice: create your own severity. It's just an enum! Follow the source code of that "level" (using your IDE) to see that it's a simple enum. Copy it to your implementation, and change it as necessary. This is how it looks (after changing its name):
enum my_severity_level
{
trace,
debug,
info,
warning,
error,
fatal
};
Take that to your code, and use it as necessary.
That write_log function should be like this:
void write_log(my_severity_level level, const char *message, ...) { ... }
This question already has answers here:
printing Unicode characters C++
(3 answers)
Closed 6 years ago.
So, I'm trying to print some Japanese characters. I tried every possible thing. What am I missing?
#include <windows.h>
#include <string>
template<typename T>
void printW(const T* text) {
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
template<typename T>
void print(const T* text) {
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
int main()
{
//const char* text = "こんにちは\n";
const wchar_t* textL = L"こんにちは\n";
const char16_t* textu = u"こんにちは\n";
const char32_t* textU = U"こんにちは\n";
//printW(text);
printW(textL);
printW(textu);
printW(textU);
}
WinAPI not needed, also you're using the wrong types.
#include <iostream>
#include <string>
int main()
{
std::string text{u8"こんにちは"};
std::cout << text;
}
Live example
If you need to use the WinAPI, minimal modification is needed:
#include <windows.h>
#include <string>
template<typename T>
void print(const T* text) {
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
int main()
{
auto text = u8"こんにちは\n";
print(text);
}
disclaimer: not tested on actual windows machine
My problem seems to be very basic but I could not find a solution for it. I need to write a code which helps debugging by reporting the line and location of exception throwing. The problem is that __LINE__ is an int value and I have problem with its conversion into string in the following code where std::string(line) is used:
#pragma once
#include <stdexcept>
#include <cstring>
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char * msg, const char * file,int line)
:runtime_error(std::string(msg)+" #"+":"+std::string(line)){}
};
#define runtime_error_line(msg) CRuntime_error_line(msg,__FILE__,__LINE__)
Seems std::string(line) cannot convert int to string and other solutions suggested online cannot be implemented inline and I don't know how to call a base constructor in second line!
compiler output:
log.h: In constructor ‘CRuntime_error_line::CRuntime_error_line(const
char*, const char*, int)’: log.h:10:124: error: invalid conversion
from ‘int’ to ‘const char*’ [-fpermissive] CRuntime_error_line(const
char * msg, const char * file,int
line):runtime_error(std::string(msg)+" #"+":"+std::string(line)){}
(Using g++ and linux environment)
edit:
the macro is supposed to be called this way:
throw runtime_error_line("Invalid somethihng ...!");
As is suggested by Borgleader std::to_string is your solution. It will also construct a temporary std::string for you, so there's no need to construct a temporary string from msg:
#pragma once
#include <stdexcept>
#include <cstring>
#include <string> // Add this to support std::to_string
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char* msg, const char* file, int line)
: runtime_error(msg + " #:"s + std::to_string(line)){} // Use std::to_string here
};
#define runtime_error_line(msg) CRuntime_error_line(msg, __FILE__, __LINE__)
Without C++11 you can still do this it's just not as clean:
#pragma once
#include <stdexcept>
#include <cstring>
#include <sstream> // Use to include std::ostringstream
class CRuntime_error_line: public std::runtime_error
{
public:
CRuntime_error_line(const char* msg, const char* file, int line)
: runtime_error(static_cast<std::ostringstream&>(std::ostringstream() << msg << " #:" << line).str()){} // Use std::ostringstream here
};
#define runtime_error_line(msg) CRuntime_error_line(msg, __FILE__, __LINE__)
int this case may be better :
#define STRING_DEFINE1(x) #x
#define STRING_DEFINE(x) STRING_DEFINE1(x)
...
CRuntime_error_line(msg,__FILE__,STRING_DEFINE(__LINE__))
The simplest thing I can think of would be to write a to_string yourself:
#include <sstream>
std::string to_string(int i)
{
std::ostringstream os;
os << i;
return os.str();
}
Then call it as others have suggested.
I was trying to override a C-style function (func) in a library with a C++ style function accepting different arguments, as the code below demonstrates.
I compiled test.cpp into a shared library libtest.so, and compiled main.cpp and linked it with the libtest.so library. This all works, upto the linking step, where I get
undefined reference to 'func(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'.
Can someone explain me why the linker cannot resolve the C++ function? I checked with nm that both functions are indeed in the library. The linker error occurs both with intel and g++ compilers.
test.h:
extern "C" {
int func( char* str, int size );
}
#include <string>
int func( std::string str );
test.cpp:
#include <stdio.h>
#include <string>
#include "test.h"
int func( char *buf, int size )
{
return snprintf( buf, size, "c-style func" );
}
int func( std::string& str )
{
str = "c++-style func";
return str.size();
}
main.cpp:
#include <iostream>
#include <string>
#include "test.h"
int main()
{
char buf[1024];
func( buf, 1024 );
std::cout << buf << "\n";
std::string str;
func( str );
std::cout << str << "\n";
}
You've declared the function in test.h as int func(std::string), but defined it in test.cpp as int func(std::string &). See the difference?