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

bwntbbo3  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(98)

我需要得到一个Assert失败的输出,如下所示:

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来停用所有assert调用,然后定义自己的assert宏,但没有任何效果

uxhixvfz

uxhixvfz1#

宏的基本问题是,一旦传递的expr参数被字符串化(使用#运算符),它就不再是可测试的布尔表达式。相反,它是一个字符串字面量(类型为const char*),传递给assert函数,并且永远不会是NULL(这是!expr测试在代码中实际检查的内容)。
您可以通过添加一个额外的int(或bool,如果您包含<stdbool.h>头部)参数并在调用该函数的宏中使用expr参数的来实现一个函数。在宏中使用这些参数时,通常最好将它们括在括号中。
还要注意的是,你不需要buffer参数,因为它可以被声明为一个局部变量(在注解中也提到了)。
下面是assert函数的一个可能实现。

#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);
        fprintf(stderr,
            "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函数(尽管你的赋值可能会迫使你这样做),使用fprintf而不是 *C++**std::cerr输出流。

相关问题