如何在 C 中打印字符串或整数?

How do I print either string or integer in C?

下面是sturct token_t。它有两个东西

value之所以是union,是因为token可以是数字也可以是字符串。 主要问题是我无法设计一个合适的函数来为我打印出这个令牌。查看我的 void print_token(token_t* token) 函数。我知道这很糟糕。只是因为 printf() 只打印 %d (十进制)或 %s (字符串)我无法打印出我的令牌。无论值是什么,我都希望我的函数打印令牌。

// ===========================================================================
typedef enum token_type_t 
{
    ID,  // Identifier
    STR, // String
    WHS, // Whitespace 
    LPR, // Left Parenthesis
    RPR, // Right Parenthesis
    LCB, // Left Curly Bracket
    RCB, // Right Curly Bracket
    LSB, // Left Square Bracket
    RSB, // Left Square Bracket
    EOF, // End Of File
    EQL, // Equal Sign
    SEM, // Semicolon
} token_type_t;

typedef union token_value_t 
{
    char* str_value;
    int int_value;
} token_value_t;

typedef struct token_t 
{
    token_type_t  type;
    token_value_t value;    
} token_t;
// ===========================================================================


// Here's the problem. I want this function to print the token no matter what type 
// the value is, I want it to be dynamic. Is there any way to do that?
void print_token(token_t* token)
{
    printf("Token { type: %d, value: %s }\n", token->type, token->value);
}

How do I print either string or integer in C?

根据类型使用不同的printf()

void print_token(const token_t* token) {
  printf("Token { type: %d, value: ", token->type);
  switch (token->type) {
    case ID: printf("%d",      token->value.int_value); break;
    case STR: printf("\"%s\"", token->value.str_value); break;
    // TBD code for other cases
  }
  printf(" }\n");
}

一种解决方案是只打印一个字符串,但有条件地将整数转换为字符串:

例如:

void print_token( const token_t* token )
{
    char buf[21] ;
    printf( "Token { type: %d, value: %s }\n", 
            token->type, 
            token->type == ID ? itoa( token->value.int_value, buf, 10 ) :
                                token->value.str_value );
}

请注意 itoa() 不是标准函数 - 如果为此必须 implement your own,您可能会认为这是禁止的。

您没有指定哪些令牌类型是整数,哪些是字符串,因此如果 ID 可能不是唯一的整数,则条件可能更复杂,例如:

void print_token( const token_t* token )
{
    char buf[21] ;
    printf( "Token { type: %d, value: %s }\n", 
            token->type, 
            token->type == ID ||
            token->type == EOF ? itoa( token->value.int_value, buf, 10 ) :
                                 token->value.str_value );
}

如果整数类型多于字符串类型,最好交换测试。

如果只是一种标记类型中的一两个,其余是另一种标记类型,并且您有合适的整数到字符串函数,则上述解决方案很简洁,但如果更多,可能会变得很麻烦比这两种类型的少数。在这种情况下,请考虑以下解决方案。

switch/case 使用 case“fall-through”cases 和默认值可能更容易维护并且不需要整数到字符串函数:

void print_token( const token_t* token ) 
{
    printf( "Token { type: %d, value: ", token->type ) ;
    switch (token->type) 
    {
        // Stack all the integer token cases here
        case ID :
        case EOF : 
            printf("%d", token->value.int_value) ; 
        break ;
    
        // Everything is a string
        default:
            printf( "\"%s\"", token->value.str_value ) ; 
        break;
    }
    printf(" }\n");
}

同样,如果字符串标记多于整数,您可以交换显式大小写和默认值。