【问题标题】:Initializing a char with an int in C在 C 中用 int 初始化 char
【发布时间】:2016-06-19 21:22:12
【问题描述】:

我是 C 编程新手,想创建一个将文本放在 int 之前的 char。

char charPin[] = ("PIN%d",pin);

我想要它,这样我就可以将charPin 传递给外部函数。我在行首收到一个无效的初始化程序。

【问题讨论】:

  • 检查 sprintf_s 函数。
  • pinint 吗?如果pin 的值为42,您是否希望charPin 的值为"PIN42"?如果是这样,请更新您的问题以明确表示。向我们展示pin 的声明,并告诉我们对于给定的pin 值,您希望charPin 具有什么值。如果不先明确说明您要完成的工作,您将无法解决问题。
  • 我认为这个问题不应该被否决

标签: c char


【解决方案1】:

对于不完整的数组,您需要一个常量初始化器,以便编译器可以在运行时确定大小。因此,很难将变量用于引脚号。

如果您可以使用固定引脚,则以下工作:

#define STRINGIZE(x)    #x
#define CONCAT(a,b)     STRINGIZE(a##b)

static const char p10[] = CONCAT(PIN, 10);

int main(void)
{
    printf("%s\n", p10);
    return 0;
}

# 产生用引号括起来的参数,连接运算符## 将两个参数连接成一个。它们是预处理器运算符,这就是它不适用于变量的原因。

一个更有用的例子是仅参数化引脚号并使用宏来生成其余文本:

#define PIN(n)   STRINGIZE(PIN, n)

// usage:
... PIN(10) ...

这样,您只需更改单个宏定义即可更改文本,例如对于不同的语言:

#define PIN(n)   STRINGIZE(Anschluss, n)

如果你需要一个变量,你必须付出更多的努力。但是,如果这是您想要获取的文本的示例,那么动态生成名称以及您想要输出的其余文本可能会更容易,而不是存储到某个数组中。

最好的代码取决于你没有提供的上下文。

【讨论】:

    【解决方案2】:

    你的陈述

    char charPin[] = ("PIN%d",pin);
    

    正在尝试使用表达式("PIN%d",pin) 初始化一个未指定长度的char 数组。该表达式看起来像 Pythonesque,但它在 C 中的语法上是有效的:括号围绕涉及逗号 (,) 运算符的表达式执行它们的普通分组功能。在实际允许该表达式的上下文中进行评估,结果将具有与pin 相同的类型和值。这根本不是您想要的,幸运的是,问题是编译器拒绝的类型,而不是编译器生成代码以执行您实际告诉它执行的意外事情的类型。

    char 数组的初始化程序可以采用以下两种形式之一:

    • 字符串或 UTF-8 文字,或
    • 用大括号括起来的单个元素数组。

    这些都不适合您的目的,因此您必须将所需内容与声明分开来填充数组。此外,这意味着您必须为数组声明一个明确的大小。您需要为文本部分(您知道其大小)、整数部分(其大小是可变的,在限制内)和单字节字符串终止符留出空间。

    如果您愿意做出非常合理的假设,即 pin 的数据类型 (int?) 不超过 64 位,那么 20 个字符就足够了,最多可能有 19 个十进制数字加上一个符号,因此 24 个字符对于整个字符串应该足够了。通常最好在代码中避免使用幻数,因此您可以像这样声明 charPin

    #define PIN_BUFFER_SIZE 24
    
    // ...
    
    char charPin[PIN_BUFFER_SIZE];
    

    有几种方法可以填充数组内容,但最直接的方法是使用sprintf()snprintf()。假设我们对大小计算并不完全有信心,或者文本部分是可变的。然后,我们可能会在charPin 中声明比我们认为需要的更多的空间,但最终我们要确保我们不会覆盖数组的边界。 snprintf() 就是为此目的:

    int result = snprintf(charPin, PIN_BUFFER_SIZE, "PIN%d", pin);
    

    这是基本答案,但细心的程序员不会就此罢休。假设我们希望在我们对所需空间的假设错误时收到警报,而不是仅仅让数据被截断,我们希望测试函数的返回值并处理它指示的任何错误。我们还想检查一般错误代码,就像通常我们应该为每个可以发出错误信号的函数调用所做的那样:

    if (result >= PIN_BUFFER_SIZE) {
        fprintf(stderr, "PIN truncated\n");
        exit(EXIT_FAILURE);  // or handle it some less-drastic way
    } else if (result < 0) {
        // should not happen, but we're being thorough
        fprintf(stderr, "Internal I/O error\n");
        exit(EXIT_FAILURE);  // or handle it some less-drastic way
    }
    

    【讨论】:

      【解决方案3】:

      您正在寻找的是sprintf 函数。 首先,您必须声明一个足够大的数组来存储结果(which might not be easy,因此在我的示例中,我使用了 50 个字符的固定大小),然后使用格式化数据初始化它的函数。您不必使用strlen 检查结果字符串的长度,因为sprintf 已经返回它。

      size_t arraySize = 50;
      char charPin[arraySize];
      int resultSize = sprintf(charPin, "PIN%d", pin);
      

      如果 sprintf 失败,resultSize 将为负值。你可以处理它

      if (resultSize < 0) {
          // react to failure here
      }
      

      现在要打印结果,您可以使用printf("%s", charPin);

      如果您尝试使用常量值初始化 char 数组,您可以将 PIN 码(在我的示例中为 52)写入字符串文字中。

      char charPin[] = "PIN52";
      

      【讨论】:

      • snprintf 不能用于初始化数组。
      • 那么在我的示例中我在做什么? en.wikipedia.org/wiki/Initialization_(programming) - 初始化并不意味着单行赋值,数组可以使用任意数量的操作进行初始化,它仍然被认为是“初始化”。
      • 在初始化resultSize 时,您不会初始化数组,而是写入数组。该标准非常清楚什么是初始化。使用您的代码输入静态变量。
      • printf 有意返回 int,而不是 size_t
      • 术语“初始化”是标准中定义明确的术语,并且有自己的部分 (6.7.9)。而且也没有初始化的“内联”。请使用标准术语。 An - 重复一遍 - 您的代码在需要 常量表达式 的地方不起作用。让空间浪费超过 300% 的未使用内存开销。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 2021-04-16
      相关资源
      最近更新 更多