7

エラーコードのいくつかの定義を含むCプログラムがあります。このような:

#define FILE_NOT_FOUND -2
#define FILE_INVALID -3 
#define INTERNAL_ERROR -4
#define ... 
#define ... 

定義の名前をその値で出力することは可能ですか? このような:

PRINT_NAME(-2);

// output
FILE_NOT_FOUND
4

8 に答える 8

6

要するに、いいえ。これを行う最も簡単な方法は次のようになります (注意: これは、ゼロ/ヌルに割り当てられたエラーを決して持たないことを前提としています):

 //Should really be wrapping numerical definitions in parentheses. 
#define FILE_NOT_FOUND  (-2)
#define FILE_INVALID    (-3) 
#define INTERNAL_ERROR  (-4)

typdef struct {
  int errorCode;
  const char* errorString;
} errorType;

const errorType[] = {
  {FILE_NOT_FOUND, "FILE_NOT_FOUND" },
  {FILE_INVALID,   "FILE_INVALID"   },
  {INTERNAL_ERROR, "INTERNAL_ERROR" },
  {NULL,           "NULL"           },
};

// Now we just need a function to perform a simple search
int errorIndex(int errorValue) {
  int i;
  bool found = false;
  for(i=0; errorType[i] != NULL; i++) {
    if(errorType[i].errorCode == errorValue) {
      //Found the correct error index value
      found = true;
      break;
    }
  }
  if(found) {
    printf("Error number: %d (%s) found at index %d",errorType[i].errorCode, errorType[i].errorString, i);
  } else {
    printf("Invalid error code provided!");
  }
  if(found) {
    return i;
  } else {
    return -1;
  }
}

楽しみ!

さらに、タイピングをさらに節約したい場合は、プリプロセッサ マクロを使用してさらにすっきりさせることができます。

#define NEW_ERROR_TYPE(ERR) {ERR, #ERR}
 const errorType[] = {
      NEW_ERROR_TYPE(FILE_NOT_FOUND),
      NEW_ERROR_TYPE(FILE_INVALID),
      NEW_ERROR_TYPE(INTERNAL_ERROR),
      NEW_ERROR_TYPE(NULL)
    };

これで、マクロ名を 1 回入力するだけで済み、タイプミスの可能性が減ります。

于 2012-04-05T16:46:30.827 に答える
4

このようなことができます。

#include <stdio.h>

#define FILE_NOT_FOUND -2
#define FILE_INVALID -3 
#define INTERNAL_ERROR -4

const char* name(int value) {
#define NAME(ERR) case ERR: return #ERR;
    switch (value) {
        NAME(FILE_NOT_FOUND)
        NAME(FILE_INVALID)
        NAME(INTERNAL_ERROR)
    }
    return "unknown";
#undef NAME
}

int main() {
    printf("==== %d %s %s\n", FILE_NOT_FOUND, name(FILE_NOT_FOUND), name(-2));
}
于 2015-12-16T20:26:57.650 に答える
3

いいえ、それは不可能です。これは何を印刷しますか?

#define FILE_NOT_FOUND   1
#define UNIT_COST        1
#define EGGS_PER_RATCHET 1

PRINT_NAME(1);
于 2012-04-05T16:35:36.793 に答える
2

ちょっと..。

#define ERROR_CODE_1 "FILE_NOT_FOUND"
#define ERROR_CODE_2 "FILE_FOUND"

#define PRINT_NAME(N) ERROR_CODE_ ## N

また:

static char* error_codes(int err) {
   static char name[256][256] = {

   };
   int base = .... lowest error code;
   return name[err - base];
}

#define PRINT_NAME(N) error_code(N)
于 2012-04-05T16:39:07.283 に答える
1

自動的ではありません。名前はコンパイル中に失われ、定数のみがコードに残ります。

しかし、あなたはこのようなものを作ることができます:

const char * a[] = {"","","FILE_NOT_FOUND","FILE_INVALID"};

定義値の絶対値をインデックスとして使用してアクセスします。

于 2012-04-05T16:50:53.447 に答える
1

代わりに列挙を使用することを選択しないのはなぜですか?

enum errors {FILE_NOT_FOUND = -2, FILE_INVALID = -3, INTERNAL_ERROR = -4};

FILE *fp = fopen("file.txt", "r");


if(fp == NULL) {
    printf("Error\n");
    exit(FILE_NOT_FOUND);
}
于 2012-04-05T16:45:52.997 に答える
1

これには C99 の指定された初期化子を使用しますが、エラー コードが負の場合は少し注意が必要です。

まず、正の値のバージョン:

#define CODE(C) [C] = #C

static
char const*const codeArray[] = {
CODE(EONE),
CODE(ETWO),
CODE(ETHREE),
};

enum { maxCode = (sizeof codeArray/ sizeof codeArray[0]) };

これにより、必要な長さの配列が割り当てられ、正しい位置に文字列ポインターが配置されます。標準では重複する値が許可されていることに注意してください。最後の値は、実際に配列に格納されているものになります。

エラー コードを出力するには、インデックスが より小さいかどうかを確認する必要がありますmaxCode

エラー コードが常に負の場合は、印刷する前にコードを無効にする必要があります。しかし、おそらく逆の方法で行うことをお勧めします。コードを正にして、その符号の戻り値をチェックします。負の場合、エラー コードは値の否定になります。

于 2012-04-05T18:53:10.310 に答える
0

これは私がCで行う方法です:

< MyDefines.h >

#pragma once 

#ifdef DECLARE_DEFINE_NAMES
// Switch-case macro for getting defines names
#define BEGIN_DEFINE_LIST  const char* GetDefineName (int key) { switch (key) {
#define MY_DEFINE(name, value)  case value: return #name;
#define END_DEFINE_LIST } return "Unknown"; }

#else

// Macros for declaring defines
#define BEGIN_COMMAND_LIST /* nothing */
#define MY_DEFINE(name, value)  static const int name = value;
#define END_COMMAND_LIST /* nothing */

#endif

// Declare your defines
BEGIN_DEFINE_LIST

MY_DEFINE(SUCCEEDED,       0)
MY_DEFINE(FAILED,         -1)
MY_DEFINE(FILE_NOT_FOUND, -2)
MY_DEFINE(INVALID_FILE,   -3)
MY_DEFINE(INTERNAL_ERROR  -4)
etc...

END_DEFINE_LIST

< MyDefineInfo.h >

#pragma once
const char* GetDefineName(int key);

< MyDefineInfo.c >

#define DECLARE_DEFINE_NAMES
#include "MyDefines.h"

これで、宣言された switch-case マクロを次のような場所で使用できます。

< WhereEver.c >

#include "MyDefines.h"
#include "MyDefineInfo.h"

void PrintThings()
{
    Print(GetDefineName(SUCCEEDED));
    Print(GetDefineName(INTERNAL_ERROR));
    Print(GetDefineName(-1);
    // etc.
}
于 2015-12-16T17:22:02.080 に答える