我如何添加自己的关于 C 中的 assert() 错误的消息?

问题描述 投票:0回答:1

我需要获得断言失败的输出,如下所示:

Assertion failed!
Program: C:\...\assert-test.exe
File: C:\...\assert-test.c, Line 21
Expression: denominator != 0.0

任何人都可以向我解释如何删除默认错误消息并创建自己的错误消息吗? 这就是我的代码的样子:

#if defined(_STDC_LIB_EXT1_) || defined(_MSC_VER)
    #define __STDC_WANT_LIB_EXT1_ 1
    #define SCANF scanf_s
#else
    #define SCANF scanf
#endif

#ifdef NDEBUG
    #define M_Assert(expr) \
        __M_Assert(buffer, __FILE__, __LINE__, #expr)
#else
    #define M_Assert(expr);
#endif // NDEBUG

#include <stdio.h>
#include <assert.h>


int main() {
    double numerator = 0.0, denominator = 0.0;
    printf("--- Quotient of two numbers ---\n\nEnter the nominator: ");
    if (SCANF("%lf", &numerator) < 1) {
        printf("invalid input\n"); return 1;
    }
    printf("denominator: ");
    if(SCANF("%lf", &denominator) < 1) {
        printf("invalid input\n"); return 1;
    }

    M_Assert(denominator != 0);

    printf ("quotient is %f\n", numerator / denominator);
    return
}

void __M_Assert(char *buffer, char *file, int line, char *expr) {
    if(!expr) {
        buffer[MAX_PATH];
        GetModuleFileName(NULL, buffer, MAX_PATH);
        std::cerr << "Assssertion failed!\n"
        << "/n"
        << "Programm: \t" << buffer << "\n"
        << "File: \t" << file << ", Line " << line << "\n"
        << "\n"
        << "Expression: \t" << expr << "\n";
        abort();
    }
}

所以我尝试定义 NDEBUG 来停用所有断言调用,然后定义我自己的断言宏,但没有任何效果

c assert ndebug
1个回答
0
投票
宏的基本问题是,一旦传递的

expr

 参数被字符串化(使用 
#
 运算符),它就不再是可测试的布尔表达式。相反,它是一个传递给断言函数的字符串文字(类型为 
const char*
),并且永远不会是 
NULL
(这是 
!expr
 测试在代码中实际检查的内容)。

您可以通过添加额外的

int

(或 
bool
,如果包含 
<stdbool.h>
 标头)参数来实现执行您想要的操作的函数,并在宏中使用 
expr 参数的 value
调用该函数。在宏中使用这些参数时,通常最好将这些参数括在括号中。

另请注意,您不需要

buffer

 参数,因为它可以声明为局部变量(如注释中所述)。

这是断言函数的可能实现。

#include <stdio.h> #include <stdbool.h> #include <Windows.h> #define M_Assert(expr) \ MyAssert(__FILE__, __LINE__, (expr), #expr) void MyAssert(const char* file, int line, bool test, const char* expr); int main(void) { double numerator = 0.0, denominator = 0.0; printf("--- Quotient of two numbers ---\n\nEnter the nominator: "); if (scanf("%lf", &numerator) < 1) { printf("invalid input\n"); return 1; } printf("denominator: "); if (scanf("%lf", &denominator) < 1) { printf("invalid input\n"); return 1; } M_Assert(denominator != 0); printf("quotient is %f\n", numerator / denominator); return 0; } void MyAssert(const char* file, int line, bool test, const char* expr) { if (!test) { char buffer[MAX_PATH]; GetModuleFileName(NULL, buffer, MAX_PATH); printf("Assertion failed!\n\n" "Program: \t%s\n" "File: \t%s\n" "Line: \t%d\n" "Expression:\t%s\n", buffer, file, line, expr); abort(); } }
我还对代码进行了一些“清理”,通过解决您问题的评论中提出的观点,例如不使用以双下划线开头的标识符,不使用 

scanf_s

 函数(尽管您的赋值可能会迫使您这样做),并使用 
printf
 而不是 C++ 
std::cerr
 输出流。

© www.soinside.com 2019 - 2024. All rights reserved.