将结果或错误返回给函数的调用者

时间:2018-01-30 08:27:51

标签: c error-handling

在C中的错误处理和SO上的几个答案的所有示例中,所有程序都只退出状态代码。我不是在寻找任何一种。

错误是输入和输出的一部分,例程可以返回结果或错误。我希望函数返回错误的正确详细信息而不是异常退出或成功的结果。

以下不是可行的,但我正在寻找类似的东西,以指示函数返回的结果或错误。

struct Error {
    int code;
    char *message;
};

int div(int x, int y) {
    if( y == 0){
        struct Error *error = {0, "Division by zero!"};
        return error;
    } else {
        return x / y;
    }
}

int main() {
    printf("%d", div(4, 2));
    printf("%d", div(4, 0));
}

3 个答案:

答案 0 :(得分:4)

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int red= new Random().nextInt(255); int green= new Random().nextInt(255); int blue= new Random().nextInt(255); ThemeColors.setNewThemeColor(MainActivity.this, red, green, blue); } }); - > struct Error *error =,然后返回struct Error error =类型。

但是因为你有一个结构,按值返回通常不是一个好主意。此外,数学函数的返回值很可能是数学结果。因此,比返回错误更好的方法是使用可选参数:

struct Error

答案 1 :(得分:1)

对于它的所有缺陷,Zed Shaw以艰难的方式学习C'有一个很好的部分" C错误处理问题"你可能会感兴趣。

我认为解决这个问题的一种方法是使用调试宏来包装全局的“错误”。 C提供的价值。

以下' dbg.h'代码取自Zed Shaw的书:

dbg.h:

#ifndef __dbg_h__
#define __dbg_h__

#include <stdio.h>
#include <errno.h>
#include <string.h>

#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n",\
        __FILE__, __LINE__, ##__VA_ARGS__)
#endif

#define clean_errno() (errno == 0 ? "None" : strerror(errno))

#define log_err(M, ...) fprintf(stderr,\
        "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__,\
        clean_errno(), ##__VA_ARGS__)

#define log_warn(M, ...) fprintf(stderr,\
        "[WARN] (%s:%d: errno: %s) " M "\n",\
        __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)

#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n",\
        __FILE__, __LINE__, ##__VA_ARGS__)

#define check(A, M, ...) if(!(A)) {\
    log_err(M, ##__VA_ARGS__); errno=0; goto error; }

#define sentinel(M, ...)  { log_err(M, ##__VA_ARGS__);\
    errno=0; goto error; }

#define check_mem(A) check((A), "Out of memory.")

#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__);\
    errno=0; goto error; }

#endif

在您要检查的代码中,您可以执行以下操作:

#include <stdio.h>
#include "dbg.h"

int div(int x, int y) {
    check ( y != 0, "Division by zero!");
    return x / y;
error:
    log_err("Div by zero error.");
    return 0;
}

int main() {
    printf("%d", div(4, 2));
    printf("%d", div(4, 0));
}

这样你的错误就会被“dbg.h&#39;”中的代码捕获和处理。 现在这有一个明显的问题,当调用div(x,0)时:div返回0.问题是div()必须返回一个int,并且所有的int都可以由div(x,y)的某个有效组合产生对于整数x和y。

一种解决方案是将div包装在另一个函数中:

#include <stdio.h>
#include <stdlib.h>
#include "dbg.h"

char *div_interface(int x, int y) {
    check ( y != 0, "Division by zero!");
    char *buffer = malloc(100);
    sprintf(buffer, "%d", (x / y));
    return buffer;
error:
    log_err("Div by zero error.");
    char *err_ret= strdup("Div by zero error.");
    return err_ret;
}

int main() {
    char *div_1 = div_interface(4, 2);
    printf("%s\n", div_1);
    free(div_1);
    char *div_2 = div_interface(4, 0);
    printf("%s\n", div_2);
    free(div_2);
}

尽管如此,这并不是特别优雅!然后调用者必须从char *转换为int ...

答案 2 :(得分:0)

当函数返回int时,不能返回结构。但是你可以返回不同的整数然后处理它。

#include <stdio.h>
#include <stdlib.h>

typedef enum
{
  ERR_NONE,
  ERR_DIV_BY_ZERO
} err_code_t;

typedef struct 
{
    err_code_t code;
    const char *message;
} err_t;

int division (int x, int y, err_t* err) 
{
  int result;

  if( y == 0)
  {
    if(err != NULL)
    {
      err->code = ERR_DIV_BY_ZERO;
      err->message = "Division by zero";
    }
    result = 0;
  } 
  else 
  {
    result = x / y;
  }

  return result;
}

void error_handler (const err_t* err)
{
  fprintf(stderr, "Error %d: %s", err->code, err->message);
  exit(EXIT_FAILURE);
}

int main() 
{
  err_t err;
  int result;

  result = division(4, 2, NULL); // NULL meaning don't give any error information
  printf("%d\n", result);

  result = division(4, 0, &err);
  if(err.code != ERR_NONE)
  {
    error_handler(&err);
  }
  printf("%d\n", result);
}

我知道有时结果可能小于零,但它只是一个粗略的例子。