【问题标题】:How to return a character array from a function in C如何从C中的函数返回字符数组
【发布时间】:2020-02-14 22:52:55
【问题描述】:

所以我正在编写一个函数来将十进制数转换为十六进制算术。我正在编写一个将进行转换的十六进制函数,我将在 main() 中调用它。我需要我的十六进制函数来返回十六进制数字的字符数组。我已经观看了 youtube 视频和其他有关在不同示例中返回字符数组的问题,但我无法使其在我的代码中工作。 我不断收到的错误是“十六进制类型冲突”

#include<stdio.h>



int main()
{
    //receiving name from user

    char name[50];
    printf("Enter your name: ");
    scanf("%s", name);

    //recieving integer from user
    char hex1[32];
    int num;
    printf("Enter an integer(1-1,000,000) or type x to exit: ");
    scanf("%d", &num);


    char hex[30];


    printf("Hexadecimal: %s\n", hexadecimal(hex1));

}

char hexadecimal(char x[])
{

    int quotient;
    int temp, i;
    i=1;
    quotient = x;
    char hex2[32];
    memcpy(hex2, x, sizeof(hex2));

    while (quotient != 0)
    {
        temp = quotient%16;

        if(temp<10)
            temp += 48;
        else
            temp += 55;

        hex2[i++] = temp;
        quotient = quotient/16;

    }
    return hex2;
}

【问题讨论】:

  • 贴出的代码无法编译!除其他外,缺少声明:#include &lt;string.h&gt; 公开函数原型:memcpy()
  • 关于:return hex2;char hexadecimal(char x[]) 这试图返回指向数组的指针:hex2[] 但签名期望返回 char,而不是 char *。注意:当引用数组名时,它会降级为数组第一个字节的地址。它正在返回一个局部变量的地址。当函数退出时,局部变量会超出范围。结果是未定义的行为
  • 关于这个函数签名:char hexadecimal(char x[])这个函数在执行之前被调用并且main()开始之前没有签名的原型所以当它被调用时,参数和返回类型将默认为int,这是不正确的。

标签: c arrays function user-defined-functions return-type


【解决方案1】:

您必须首先传入一个数组作为参数,或者使用 malloc 调用创建一个数组,因为否则该数组将成为块和该空间的本地存储,虽然它可能存在一段时间,如果在所有之后从函数返回时,堆栈中的内存地址将可供将来调用覆盖,从而破坏您想要的结构。

【讨论】:

    【解决方案2】:

    在使用前声明每个标识符

    问题中的代码调用main 中的hexadecimal 函数,但尚未声明它。这会导致编译器使用默认声明,其中hexadecimal 返回int

    hexadecimal 的后面定义返回一个char 与此冲突。

    要解决这个问题,要么将 hexadecimal 的整个定义移到 main 之前,要么将 hexadecimal 的声明放在 main 之前。可以使用开始其定义的同一行来声明函数,但该行以 ; 结束声明,而不是括号中的语句列表 { ... } 用于定义。

    告诉你的编译器使用现代标准 C

    二十年来,标准 C 一直要求声明函数。请参阅您的编译器文档以了解如何告诉编译器使用现代 C 标准。如果您使用的是 GCC 或 Clang,您可以使用命令行开关 -std=c17 来请求 2017/2018 C 标准。

    告诉你的编译器提供警告和错误并注意它们

    如果您使用的是 GCC 或 Clang,请使用命令行开关 -Wmost-Wall 启用许多警告消息,并使用 -Werror 将警告变为错误。如果您使用的是其他编译器,请参阅其文档。

    当编译器打印警告消息时,请弄清楚它的含义并在继续之前修复它。

    返回一个字符串,而不是一个字符

    char hexadecimal(char x[]) 声明的函数只返回一个char。你想返回一个字符串。字符串是一个以空字符结尾的字符序列。

    字符串由指向其第一个字符的指针引用。所以用于引用字符串的基本类型是char *。您的函数应声明为char *hexadecimal(char x[])。 (也可以声明为char *hexadecimal(char *x),因为数组参数会自动调整为指针。)

    创建要返回的新对象

    您的函数使用char hex2[32]; 定义了一个数组,并尝试使用return hex2; 返回它。在函数中以这种方式定义的对象具有自动存储持续时间,这意味着 C 实现在函数调用中为其提供内存,并在函数返回时释放该内存。永远不要从其函数中返回自动对象的地址,因为它的内存不再保留供使用(并且因为指针在技术上变得无效)。

    删除 char hex2[32]; 并改为使用:

    char *hex2 = malloc(32 * sizeof *hex2);
    if (!hex2)
    {
        fprintf(stderr, "Error, malloc failed.\n");
        exit(EXIT_FAILURE);
    }
    

    这将尝试使用malloc 分配内存。如果分配失败,它将打印一条消息并终止程序。由于这使用了标准库中的新例程,因此您应该在程序的开头插入它:

    #include <stdlib.h>
    

    这会分配内存但不会释放它。在需要管理内存的大型程序中,应该释放内存。在这种情况下,调用者在使用完内存后应该释放它,就像free(x); 一样,其中x 是一个包含从函数返回的指针值的char *

    用空字符终止字符串

    字符串的结尾用空字符标记。在hexadecimal 函数将它想要的字符放入字符串后,它应该在末尾放置一个空字符,带有:

    hex2[i] = '\0';
    

    确保在分配的空间中有此字符的空间很重要 - 始终将其包括在需要多少空间的计数中。

    使用正确的字符值,而不是硬编码的常量

    不要使用48 表示字符“0”或55 表示A 和10 之间的差异。这不是严格符合 C 语言的,而且没有必要这样做,因为 C 语言可以很容易地使此代码可移植。此外,硬编码常量不能传达意图,而使用字符值则可以。更改此代码:

    if(temp<10)
        temp += 48;
    else
        temp += 55;
    

    到:

    if (temp < 10)
        temp += '0';
    else
        temp += 'A' - 10;
    

    这使读者更清楚其意图是什么。它仍然不是完全可移植的,因为 C 标准(the C17 draft 中的 5.2.1/3)在字符编码中使用了not guarantee the characters “A” through “F” have consecutive values(它对数字“0”到“9”进行了处理),但这是一个改进.

    【讨论】:

    • 那是彻底的:)
    【解决方案3】:

    Eric 的回复中指出了代码中的大部分不一致之处以及纠正它们的适当措施。希望您阅读并注意。

    问题的一些细节。

    • 您将整数存储在变量num 中,但调用函数 带有未初始化的字符数组hexadecimal(hex1)???
    • 不确定为什么要声明另一个字符数组char hex[30];
    • 在“十六进制”函数中,您尝试分配一个字符 数组到整数 quotient = x;
    • 不知道为什么用 '1' 初始化“i”

    这是建议的修复....

    #include <stdio.h>
    #include <string.h>
    
    char * hexadecimal(int num)
    {
      int x;
      int quotient;
      int temp, i;
      i=0;
      quotient = num;
      static char hex2[32];//declaring hex2 as static char array
      while (quotient != 0)
      {
        temp = quotient%16;
       /* You can either use this block of code or the single ternary statement listed below
        if(temp<10)
           temp += '0';
        else
          temp += 'A' - 10;
    
        hex2[i++] = temp;
       */
        hex2[i++] = (temp < 10) ? temp + '0' : temp + 'A' - 10;//you could use this         
        quotient = quotient/16;           //ternary statement or the block above
      }
      hex2[i] = '\0';//terminate the array with NULL character
    
      //Since the result would be in reverse
      //the following will reverse the string hex2 in place
      for(i = 0,x = strlen(hex2)-1;i < x;i++,x--){
        temp = hex2[i];
        hex2[i] = hex2[x];
        hex2[x] = temp;
      }
      return hex2;
    }
    
    int main()
    {
      char name[50];
      printf("Enter your name: ");
      scanf("%s", name);
      int num;
      printf("Enter an integer(1-1,000,000) or type x to exit: ");
      scanf("%d", &num);
    
      printf("Hexadecimal: %s\n", hexadecimal(num));
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-12
      • 2014-04-11
      • 2013-11-22
      • 2013-03-25
      • 2013-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多