มีวิธีเพิ่มหรือแก้ไขข้อความที่ส่งโดยการยืนยันหรือไม่? ฉันต้องการใช้สิ่งที่ต้องการ
assert(a == b, "A must be equal to B");
แล้วคอมไพเลอร์เพิ่มบรรทัด , เวลาและอื่น ๆ ...
เป็นไปได้ไหม?
มีวิธีเพิ่มหรือแก้ไขข้อความที่ส่งโดยการยืนยันหรือไม่? ฉันต้องการใช้สิ่งที่ต้องการ
assert(a == b, "A must be equal to B");
แล้วคอมไพเลอร์เพิ่มบรรทัด , เวลาและอื่น ๆ ...
เป็นไปได้ไหม?
คำตอบ:
การแฮ็กที่ฉันเคยเห็นคือการใช้ตัว&&
ดำเนินการ เนื่องจากตัวชี้ "เป็นจริง" หากไม่ใช่ค่าว่างคุณสามารถทำสิ่งต่อไปนี้ได้โดยไม่ต้องแก้ไขเงื่อนไข:
assert(a == b && "A is not equal to B");
เนื่องจากassert
แสดงเงื่อนไขที่ล้มเหลวมันจะแสดงข้อความของคุณด้วย หากยังไม่เพียงพอคุณสามารถเขียนmyAssert
ฟังก์ชันหรือมาโครของคุณเองเพื่อแสดงสิ่งที่คุณต้องการ
assert(("A must be equal to B", a == b));
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
printf
จะส่งคืนค่าที่ไม่ใช่ศูนย์หากมันพิมพ์อะไรออกมาดังนั้นคุณสามารถทำอะไรบางอย่างเช่นassert(a == b && printf("a (%i) is not equal to b (%i)", a, b))
แม้ว่าในตอนนั้นคุณควรเขียนกระดาษห่อตัวยืนยันของคุณเอง
อีกทางเลือกหนึ่งคือการย้อนกลับตัวถูกดำเนินการและใช้ตัวดำเนินการลูกน้ำ คุณต้องมีวงเล็บพิเศษเพื่อไม่ให้เครื่องหมายจุลภาคเป็นตัวคั่นระหว่างอาร์กิวเมนต์:
assert(("A must be equal to B", a == b));
(คัดลอกมาจากความคิดเห็นด้านบนเพื่อการมองเห็นที่ดีขึ้น)
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
นี่คือมาโครยืนยันเวอร์ชันของฉันซึ่งยอมรับข้อความและพิมพ์ทุกอย่างออกมาอย่างชัดเจน:
#include <iostream>
#ifndef NDEBUG
# define M_Assert(Expr, Msg) \
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
# define M_Assert(Expr, Msg) ;
#endif
void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
if (!expr)
{
std::cerr << "Assert failed:\t" << msg << "\n"
<< "Expected:\t" << expr_str << "\n"
<< "Source:\t\t" << file << ", line " << line << "\n";
abort();
}
}
ตอนนี้คุณสามารถใช้สิ่งนี้ได้
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
และในกรณีที่ล้มเหลวคุณจะได้รับข้อความดังนี้:
ยืนยันล้มเหลว: MyFunction: ต้องการอาร์กิวเมนต์ที่ไม่ใช่ค่าว่าง
คาดว่า: ptr! = nullptr
ที่มา: C: \ MyProject \ src.cpp บรรทัด 22
สวยและสะอาดอย่าลังเลที่จะใช้ในรหัสของคุณ =)
x == y
สมมติว่าสภาพยืนยันของคุณคือ จากนั้นนิพจน์จะขยายเข้าไปif( !(x == y))
และนี่คือที่ตรวจสอบเงื่อนไขและ #Expr จะขยายเป็นสตริงลิเทอรั"x == y"
ลซึ่งเราจะใส่ลงในข้อความแสดงข้อผิดพลาด
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
คุณสามารถใช้สิ่งนั้นโดยตรงหรือคัดลอกโค้ดของ Boost โปรดทราบว่า Boost assert เป็นส่วนหัวเท่านั้นดังนั้นคุณสามารถคว้าไฟล์เดียวนั้นได้หากคุณไม่ต้องการติดตั้ง Boost ทั้งหมด
เนื่องจากคำตอบของ zneak ทำให้โค้ดค่อนข้างซับซ้อนวิธีการที่ดีกว่าคือการแสดงความคิดเห็นเพียงข้อความสตริงที่คุณกำลังพูดถึง เช่น .:
assert(a == b); // A must be equal to B
เนื่องจากผู้อ่านข้อผิดพลาดยืนยันจะค้นหาไฟล์และบรรทัดต่อไปจากข้อความแสดงข้อผิดพลาดพวกเขาจะเห็นคำอธิบายทั้งหมดที่นี่
เพราะในตอนท้ายของวันนี้:
assert(number_of_frames != 0); // Has frames to update
อ่านได้ดีกว่านี้:
assert(number_of_frames != 0 && "Has frames to update");
ในแง่ของการแยกวิเคราะห์รหัสของมนุษย์เช่น การอ่าน ยังไม่แฮ็คภาษา
assert เป็นการรวมมาโคร / ฟังก์ชัน คุณสามารถกำหนดแมโครของคุณเอง / ฟังก์ชั่นการใช้__FILE__
, __BASE_FILE__
, __LINE__
ฯลฯ ที่มีฟังก์ชั่นของคุณเองที่จะใช้ข้อความที่กำหนดเอง
สำหรับ vc ให้เพิ่มรหัสต่อไปนี้ใน assert.h,
#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )