Как вывести число с плавающей точкой целых множителей? - PullRequest
1 голос
/ 12 ноября 2010

Я пытаюсь вычислить показатель числа.Когда я делаю все как int, я получаю правильный результат, но вывод должен быть плавающим, когда я пытаюсь конвертировать с% f в printf (), я получаю 0, когда я использую% d, я получаю правильный результат.Я не могу изменить часть main () программы, я могу только изменить функцию * powerArgs ().Программа вводит 3, 5.

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

#include <stdio.h>
#include <stdlib.h>

int *powerArgs(int *pA, int *pB);

/* MAIN */
int main(int argc, char **argv)
{

    if (argc != 3)
    {
       printf("?Invalid number of arguments\n");
       system("pause");
       exit(1);
    }

    int parmA = atoi(argv[1]);
    int parmB = atoi(argv[2]);
    int idx;

/* Part C: Raise parmA to the power of parmB.  Return pointer to the result */    
/*         Reset the original values after we print the result */
    printf("%d raised to the %d power is %0.1f\n", parmA, parmB, *powerArgs(&parmA, &parmB));

    printf("\n");  

    system("pause");
    exit(0);
}

int *powerArgs(int *pA, int *pB)
{
      int idx, result = *pA;

      for (idx = 1; idx < *pB; idx++)
      {
          result *= *pA;
      }

      return &result;
}      

Ответы [ 3 ]

3 голосов
/ 12 ноября 2010

float и int автоматически преобразуются в C - вы можете назначить одно другому, и единственное, на что следует обратить внимание, это то, что если вы присваиваете слишком большой float для int, то вы получите неопределенное поведение (или, возможно, неопределенный результат, я забыл. В любом случае, это нехорошо).

Итак, ваша powerArgs функция может быть просто:

float powerArgs(float a, int b) {
    // do some stuff and return a value
}

Тогда вы можете назвать его как powerArgs(parmA, parmB), хотя parmA является целым числом.

Редактировать: если вы не можете изменить параметры вызова, вы можете сделать это вместо этого

float powerArgs(int *a, int *b) {
    float base = *a;
    int exponent = *b;
    ...
}

Если ваш профессор действительно установил вам код, где функция называется *powerArgs(int *a, int *b), то ваш профессор - угроза. Нет веской причины, по которой функция возведения в степень должна возвращать указатель на число с плавающей точкой. Вы можете использовать уродливый обходной путь:

float *powerArgs(int *a, int *b) {
    static float result;
    ...
    result = /* the result of the calculation */;
    return &result;
}

Проблема в том, что все вызовы powerArgs используют один и тот же объект result. static останавливает его прекращение существования в конце вызова, но совместное использование создаст проблемы в долгосрочной перспективе. Это не хорошая практика, но это может быть лучшим решением поставленной вами проблемы.

С ++ подлое решение:

struct FloatWrapper {
    float value;
    float operator*() {
        return value;
    }
    FloatWrapper(float f) : value(f) {}
};

FloatWrapper powerArgs(int *a, int *b) {
    ...
    float result = /* whatever */;
    ...
    return result;
}

Возвращает объект класса FloatWrapper по значению, а FloatWrapper перегружает оператор *. Это означает, что *powerArgs(...) вычисляет с плавающей точкой, что функция должна была возвращаться по значению в первую очередь, без , не требуя указателя на какое-либо специальное место хранения.

Кстати, вы можете проверить, что делает ваша функция, когда parmB равно 0.

1 голос
/ 12 ноября 2010

Когда функция завершается, все ее локальные переменные перестают существовать (и их адреса указывают на мусор). Чтобы угодить своему учителю, который придумал этот очень неуклюжий интерфейс, вы должны найти способ поддержать объект после того, как функция существует.

У вас есть, по крайней мере, 3 варианта:
а) повторно использовать один из входных параметров
б) использовать глобальную переменную
в) использовать статическую переменную

вариант а)

int *powerArgs(int *pA, int *pB) {
    /* calculate */
    *pA = CALCULATED_VALUE;
    return pA;
}

вариант б)

int global_power;

int *powerArgs(int *pA, int *pB) {
    /* calculate */
    global_power = CALCULATED_VALUE;
    return &global_power;
}

вариант c)

int *powerArgs(int *pA, int *pB) {
    static int static_power;
    /* calculate */
    static_power = CALCULATED_VALUE;
    return &static_power;
}

Ни одно из этих "решений" не годится; наименее плохой вариант c)

1 голос
/ 12 ноября 2010

Во-первых, ваша int *powerArgs(int *pA, int *pB) функция возвращает адрес локальной переменной, что приводит к неопределенному поведению. Вместо этого используйте следующее:

int powerArgs(int *pA, int *pB)
{
  int idx, result = *pA;

  for (idx = 1; idx < *pB; idx++)
  {
      result *= *pA;
  }

  return result;
}

Далее, если вы хотите преобразовать в float, вы не должны делать это в вызове в printf(), а вместо этого преобразовать значение в float до вызова следующим образом:

printf("%d raised to the %d power is %0.1f\n", parmA, parmB, (float)powerArgs(&parmA, &parmB));
...