Как вернуть массив символов из функции в C - PullRequest
0 голосов
/ 18 октября 2019

Итак, я пишу функцию для преобразования десятичного числа в шестнадцатеричное арифметическое. Я пишу шестнадцатеричную функцию, которая будет выполнять преобразование, и я буду вызывать ее в main (). Мне нужна шестнадцатеричная функция, чтобы вернуть массив символов шестнадцатеричного числа. Я смотрел видео на YouTube и другие вопросы о возвращении символьных массивов в разных примерах, но не могу заставить его работать в моем коде. Ошибка, которую я продолжаю получать: «конфликтующие типы для шестнадцатеричного» * ​​1001 *

#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;
}

Ответы [ 4 ]

5 голосов
/ 18 октября 2019

Объявите каждый идентификатор перед его использованием

Код в вопросе вызывает функцию hexadecimal в main, но еще не объявил ее. В результате компилятор использует объявление по умолчанию, в котором hexadecimal возвращает int.

Более позднее определение hexadecimal для возврата char конфликтует с этим.

Исправитьдля этого либо переместите все определение hexadecimal до main, либо поместите объявление hexadecimal перед main. Функция может быть объявлена ​​с использованием той же строки, с которой начинается ее определение, за исключением того, что строка заканчивается ; для объявления вместо списка операторов в скобках { ... } для определения.

Tell YourИспользование компилятором современного стандарта 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 и десятью. Это не совсем соответствует C, и в этом нет необходимости, потому что C позволяет легко сделать этот код переносимым. Кроме того, жестко закодированные константы не передают намерение, тогда как использование символьных значений делает. Измените этот код:

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

на:

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

Это делает читателя намного более очевидным, каково намерение. Это все еще не полностью переносимо, потому что стандарт C (5.2.1 / 3 в проект C17 ) не не гарантирует, что символы «A» - «F» имеют последовательные значения вкодировка символов (для цифр от 0 до 9), но это улучшение.

1 голос
/ 18 октября 2019

Вы должны будете сначала передать массив в качестве аргумента или создать массив с помощью вызова malloc, потому что в противном случае массив был бы локальным хранилищем для блока и этого пространства, хотя он может существовать некоторое время, если вообще будет послевозвращаясь из функции, адрес памяти в стеке будет доступен для будущих вызовов для перезаписи, что приведет к повреждению структуры, которую вы намеревались.

0 голосов
/ 18 октября 2019

Большинство несоответствий в коде и соответствующие меры по их устранению были указаны в ответе Эрика. Надеюсь, что вы прочитали и обратили внимание.

Некоторые особенности проблемы.

  • Вы сохраняете целое число в переменной num, но вызываете функцию с массивом неинициализированных символов hexadecimal(hex1)???
  • Не уверен, почему вы объявили другой массив символов char hex[30];
  • В «шестнадцатеричной» функции вы пытаетесь присвоить массив символов для Integer quotient = x;
  • Не уверен, почему вы инициализируете «i» с «1»

Вот предлагаемое исправление ....

#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));

}
0 голосов
/ 18 октября 2019

Прямо сейчас ваша функция возвращает символ, а не массив символов, вы можете попробовать сделать так, чтобы ваша функция выглядела следующим образом:

char* hexadecimal(char x[]) {
  ...
  return hex2;
}

, которая должна возвращать указатель, который указывает на массив, хотя это не тактем не менее, вы можете напечатать его в printf, так как он не будет знать длину.

...