I have used macros in following way in my .cpp file named Test.cpp which is present in the location c:\Test\Test.cpp
Inside test.cpp
#define FILE_NAME strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__
#define S1(x) #x
#define S2(x) S1(x)
#define LOCATION FILE_NAME " : " S2(__LINE__)
//#define LOCATION __FILE__" : " S2(__LINE__) Working but giving the whole file path where as i need only Filename:Line number
Inside Function
{
::MessageBox(NULL,LOCATION,"Test",MB_OK); //Here i am getting only Filename .
}
Please help me in writing a MACRO so that i can get both Filename(Not the full path , only Filename) and Line number in my application .
You try to concatenate string literal with the result of strrchr. This is not feasible. You will need a helper function, something like
std::string get_location(const std::string& file, int line)
{
std::ostringstream ostr;
size_t bspos = file.find_last_of('\\');
if (bspos != std::string::npos)
ostr << file.substr(bspos + 1) << " : " << line;
else
ostr << file << " : " << line;
return ostr.str();
}
#define LOCATION (get_location(__FILE__, __LINE__))
Related
I need to remove a file from a directory based on the input of user and pass it into a function that perform the file remover process
/* Class 3 veus 3:45PM*/
#include <string>
#include <iostream>
#include <stdio.h>
#include <cstdio>
void remove_file(std::string file);
int main() {
std::string file_name;
std::cin >> file_name;
remove_file(file_name);
}
void remove_file(std::string file) {
if(remove("C:\\MAIN_LOC\\" + file + ".txt") == 0) {
std::cout << "`" << file << "`" << " Item deleted successfully" << std::endl;
} else {
std::cout << "[Error] File not found";
}
}
Ok now the thing is I got several error on remove function: function "remove" cannot be called with the given argument list. I'm not sure what the error mean so I'd like for an explanation.
remove takes a C string, but your expression "C:\\MAIN_LOC\\" + file + ".txt" is a C++ string. Use the c_str method to convert to a C string
remove(("C:\\MAIN_LOC\\" + file + ".txt").c_str())
use the function with c string instead:
void remove_file(std::string file)
{
std::string x = "C:\\MAIN_LOC\\" + file + ".txt";
if(remove(x.c_str()) == 0)
{
....
}
#include <iostream>
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define (__FILE__ ": " STR(__LINE__))
int main()
{
std::cout << FILE_LOCATION << std::endl;
return 0;
}
output:
main.cpp : __LINE__Var+1
Why line no doesn't shown?
I think you have to define your FILE_LOCATION macro, I cannot see the code where you define it in your snippet.
But wouldn't the code below do it?
#define FILE_LOCATION __FILE__ ": " STR(__LINE__)
I currently read the book Effective C++ from Scott Meyers. It says I should prefer inline functions over #define for function-like macros.
Now I try to code an inline function to replace my exception macro. My old macro looks like this:
#define __EXCEPTION(aMessage) \
{ \
std::ostringstream stream; \
stream << "EXCEPTION: " << aMessage << ", file " <<__FILE__ << " line " << __LINE__; \
throw ExceptionImpl(stream.str()); \
}
My new inline function is this:
inline void __EXCEPTION(const std::string aMessage)
{
std::ostringstream stream;
stream << "EXCEPTION: " << aMessage << ", file " <<__FILE__ << " line " << __LINE__;
throw ExceptionImpl(stream.str());
}
As probably some people already expect, now the __FILE__ and __LINE__ macros are useless, because they refer always to the C++-file with the definition of the inline function.
Is there any way to circumvent this behaviour or should I stick with my old macro? I read this threads here, and I already suspect that there is probably no way of my second example to work fine:
Behavior of __LINE__ in inline functions
__FILE__, __LINE__, and __FUNCTION__ usage in C++
Don't use __ (double underscore) as it's reserved. Having an inline function is better.
However, here you need a mix of macro and the function, hence you can do following:
#define MY_EXCEPTION(aMessage) MyException(aMessage, __FILE__, __LINE__)
inline void MyException(const std::string aMessage,
const char* fileName,
const std::size_t lineNumber)
{
std::ostringstream stream;
stream << "EXCEPTION: " << aMessage << ", file " << fileName << " line " << lineNumber;
throw ExceptionImpl(stream.str());
}
I see this is an old question but I think that the approach of printing the line in the exception macro is fundamentally flawed and I think I have a better alternative. I assume that the macro is used similar to the following code:
try {
/// code
throw;
}
catch (...) { __EXCEPTION(aMessage); }
With this approach the macro prints the location where the exception was catch'ed. But for troubleshooting and debugging the location where it was throw'n is usually more useful.
To get that information, we can attach the __FILE__ and __LINE__ macros to the exception. However, we still can't get completely rid of macros, but we get at least the exact throw location:
#include <iostream>
#include <exception>
#include <string>
#define MY_THROW(msg) throw my_error(__FILE__, __LINE__, msg)
struct my_error : std::exception
{
my_error(const std::string & f, int l, const std::string & m)
: file(f)
, line(l)
, message(m)
{}
std::string file;
int line;
std::string message;
char const * what() const throw() { return message.c_str(); }
};
void my_exceptionhandler()
{
try {
throw; // re-throw the exception and capture the correct type
}
catch (my_error & e)
{
std::cout << "Exception: " << e.what() << " in line: " << e.line << std::endl;
}
}
int main()
{
try {
MY_THROW("error1");
} catch(...) { my_exceptionhandler(); }
}
There is one additional improvement possible if we are willing to use boost::exception: We can get rid of macro definitons at least in our own code. The whole program gets shorter and the locations of code execution and error handling can be nicely separated:
#include <iostream>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_error_msg, std::string> error_message;
struct error : virtual std::exception, virtual boost::exception { };
struct my_error: virtual error { };
void my_exceptionhandler()
{
using boost::get_error_info;
try {
throw;
}
catch(boost::exception & e)
{
char const * const * file = get_error_info<boost::throw_file>(e);
int const * line = get_error_info<boost::throw_line>(e);
char const * const * throw_func = get_error_info<boost::throw_function>(e);
std::cout << diagnostic_information(e, false)
<< " in File: " << *file << "(" << *line << ")"
" in Function: " << *throw_func;
}
}
int main()
{
try {
BOOST_THROW_EXCEPTION(my_error() << error_message("Test error"));
} catch(...) { my_exceptionhandler(); }
}
Please consider that there is another difference between using the #define function-like macro in your case in comparison to inline functions. You could have used streaming operators and parameters in your macro's invocation to be composed as your message's text:
__EXCEPTION( "My message with a value " << val )
But most times I've needed something like this, it was to check on a certain condition (like an assertion). So you could extend #iammilind's example with something like:
#define MY_EXCEPTION_COND( cond ) \
if (bool(cond) == false) \
{ \
std::string _s( #cond " == false" ); \
MyException(_s, __FILE__, __LINE__); \
}
Or something a little more specialized where the values are also printed:
template <typename T>
inline void MyExceptionValueCompare(const T& a,
const T& b,
const char* fileName,
const std::size_t lineNumber)
{
if (a != b)
{
std::ostringstream stream;
stream << "EXCEPTION: " << a << " != " << b << ", file " << fileName << " line " << lineNumber;
throw ExceptionImpl(stream.str());
}
}
#define MY_EXCEPTION_COMP( a, b ) MyExceptionValueCompare(a, b, __FILE__, __LINE__)
Another approach you may want to take a look at is Microsoft's usage of their __LineInfo class in the Microsoft::VisualStudio::CppUnitTestFramework namespace (VC\UnitTest\Include\CppUnitTestAssert.h). See https://msdn.microsoft.com/en-us/library/hh694604.aspx
With std::experimental::source_location, you might do:
#include <experimental/source_location>
void THROW_EX(const std::string_view& message,
const std::experimental::source_location& location
= std::experimental::source_location::current())
{
std::ostringstream stream;
stream << "EXCEPTION: " << message
<< ", file " << location.file_name()
<< " line " << location.line();
throw ExceptionImpl(stream.str());
}
I am exploring a large code-base and i am not a gdb fan. I would like add a
LOG(INFO) << __PRETTY_FUNCTION__ in the first line of each function in the code-base. But that's very tedious. Does anyone know a hack to make all function calls to print a LOG message with its function name?
I do something similar to:
#include <iostream>
class LogScope
{
public:
LogScope(const char* scope, const char* file, int line = 0)
: m_scope(scope), m_file(file), m_line(line)
{
std::clog << "[Begin] " << m_scope << ", " << m_file << ", " << m_line << std::endl;
}
~LogScope() {
std::clog << "[End] " << m_scope << ", " << m_file << ", " << m_line << std::endl;
}
private:
const char* m_scope;
const char* m_file;
int m_line;
};
#define NAME_AT_LINE_2(Name, Line) Name##_##Line
#define NAME_AT_LINE_1(Name, Line) NAME_AT_LINE_2(Name, Line)
#define NAME_AT_LINE(Name) NAME_AT_LINE_1(Name, __LINE__)
#define LOG_SCOPE \
::LogScope NAME_AT_LINE(log_scope)(__FUNCTION__, __FILE__, __LINE__)
void f() {
LOG_SCOPE;
}
int main() {
LOG_SCOPE;
f();
}
Seems a duplicate of Automatically adding Enter/Exit Function Logs to a Project
However, You can consider using gprof that has the capability to generate a runtime call tree. You can have dot graphs, which might be easier to read.
In Pascal Lazarus/Delphi, we have a function QuotedStr() that wraps any string within single quotes.
Here's an example of my current C++ code:
//I need to quote tblCustomers
pqxx::result r = txn.exec( "Select * from \"tblCustomers\" ");
Another one:
//I need to quote cCustomerName
std::cout << "Name: " << r[a]["\"cCustomerName\""];
Similar to the above, I have to frequently double-quote strings. Typing this in is kind of slowing me down. Is there a standard function I can use for this?
BTW, I develop using Ubuntu/Windows with Code::Blocks. The technique used must be compatible across both platforms. If there's no function, this means that I must write one.
C++14 added std::quoted which does exactly that, and more actually: it takes care of escaping quotes and backslashes in output streams, and of unescaping them in input streams. It is efficient, in that it does not create a new string, it's really a IO manipulator. (So you don't get a string, as you'd like.)
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::string in = "\\Hello \"Wörld\"\\\n";
std::stringstream ss;
ss << std::quoted(in);
std::string out;
ss >> std::quoted(out);
std::cout << '{' << in << "}\n"
<< '{' << ss.str() << "}\n"
<< '{' << out << "}\n";
}
gives
{\Hello "Wörld"\
}
{"\\Hello \"Wörld\"\\
"}
{\Hello "Wörld"\
}
As described in its proposal, it was really designed for round-tripping of strings.
Using C++11 you can create user defined literals like this:
#include <iostream>
#include <string>
#include <cstddef>
// Define user defined literal "_quoted" operator.
std::string operator"" _quoted(const char* text, std::size_t len) {
return "\"" + std::string(text, len) + "\"";
}
int main() {
std::cout << "tblCustomers"_quoted << std::endl;
std::cout << "cCustomerName"_quoted << std::endl;
}
Output:
"tblCustomers"
"cCustomerName"
You can even define the operator with a shorter name if you want, e.g.:
std::string operator"" _q(const char* text, std::size_t len) { /* ... */ }
// ...
std::cout << "tblCustomers"_q << std::endl;
More info on user-defined literals
String str = "tblCustomers";
str = "'" + str + "'";
See more options here
No standard function, unless you count std::basic_string::operator+(), but writing it is trivial.
I'm somewhat confused by what's slowing you down - quoted( "cCustomerName" ) is more characters, no? :>
You could use your own placeholder character to stand for the quote, some ASCII symbol that will never be used, and replace it with " just before you output the strings.
#include <iostream>
#include <string>
struct quoted
{
const char * _text;
quoted( const char * text ) : _text(text) {}
operator std::string () const
{
std::string quotedStr = "\"";
quotedStr += _text;
quotedStr += "\"";
return quotedStr;
}
};
std::ostream & operator<< ( std::ostream & ostr, const quoted & q )
{
ostr << "\"" << q._text << "\"";
return ostr;
}
int main ( int argc, char * argv[] )
{
std::string strq = quoted( "tblCustomers" );
std::cout << strq << std::endl;
std::cout << quoted( "cCustomerName" ) << std::endl;
return 0;
}
With this you get what you want.
What about using some C function and backslash to escape the quotes?
Like sprintf_s:
#define BUF_SIZE 100
void execute_prog() {
//Strings that will be predicted by quotes
string param1 = "C:\\users\\foo\\input file.txt", string param2 = "output.txt";
//Char array with any buffer size
char command[BUF_SIZE];
//Concating my prog call in the C string.
//sprintf_s requires a buffer size for security reasons
sprintf_s(command, BUF_SIZE, "program.exe \"%s\" \"%s\"", param1.c_str(),
param2.c_str());
system(command);
}
Resulting string is:
program.exe "C:\users\foo\input file.txt" "output.txt"
Here is the documentation.