2010-11-12 13 views
1

J'essaie de calculer l'exposant d'un nombre. Quand je fais tout en int j'obtiens le résultat correct, mais la sortie doit être flottante, quand j'essaye de convertir avec f dans printf() j'obtiens 0, quand j'utilise% d j'obtiens le bon résultat. Je ne peux pas modifier la partie main() du programme, je ne peux modifier la fonction * powerArgs(). L'entrée du programme est 3, 5.Comment générer un produit flottant de multiplicateurs int?

Divulgation complète, cela fait partie d'une tâche scolaire. Je ne demande pas de code complet. J'apprécierais une réponse plus générale me montrant ce que j'oublie, peut-être quel domaine je devrais étudier plus pour trouver la réponse moi-même.

#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

Non, non, non. Vous ne pouvez pas renvoyer un * pointeur * à 'result' de' powerArgs'. 'result' est une * variable locale * dans cette fonction. Il n'existe pas une fois la fonction terminée. Vous devez renvoyer une valeur int (ou float) * *. –

+2

J'ai en fait un commentaire différent: ne pas nommer, même dans les devoirs, quoi que ce soit parmA, parmB ou des variantes de ceux-ci. Au lieu de cela, nommez votre base de variables et exposant. Les gens lisant votre code plus tard (vous avez inclus) le trouveront beaucoup plus facile à lire s'ils n'ont pas à continuer à chercher pour voir si parmA était la base ou l'exposant et pour voir que vous ne les avez pas échangés. – novalis

+0

Je n'ai pas écrit la partie avec parmA et parmB. La partie main() a été donnée par l'enseignant, et nous devons écrire la fonction appelée pour renvoyer le résultat attendu affiché comme show. C'est pourquoi je ne peux pas simplement sortir en int. Mais j'apprécie le point, j'ai habituellement plus de noms de variables descriptifs, tels que l'interation, la base, le produit. – cyotee

Répondre

3

float et int convertir automatiquement en C - vous pouvez affecter l'un à l'autre, et la seule chose à surveiller est que si vous attribuez un trop grand flotteur à un int, alors vous obtenez un comportement non défini (ou p ossible un résultat non spécifié, j'oublie. De toute façon ce n'est pas bon).

Ainsi, votre fonction powerArgs peut être juste:

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

Ensuite, vous pouvez l'appeler comme powerArgs(parmA, parmB), même si parmA est un entier.

Edit: si vous ne pouvez pas modifier les paramètres d'appel, vous pouvez le faire à la place

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

Si votre professeur vous a vraiment donné le code où la fonction est appelée *powerArgs(int *a, int *b), votre professeur est une menace . Il n'y a aucune raison terrestre pour laquelle une fonction d'exponentiation devrait retourner un pointeur à un flottant. Il y a une solution laide, vous pouvez utiliser:

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

Le problème est, tous les appels à powerArgs partagent le même objet result. static l'empêche de cesser d'exister à la fin de l'appel, mais le partage introduira des problèmes à long terme. Il est bon de faire cela, mais c'est peut-être la meilleure solution au problème que vous avez réglé.

solution C Sneaky:

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

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

Cela retourne un objet de classe FloatWrapper, en valeur, et FloatWrapper surcharge l'opérateur *. Cela signifie que *powerArgs(...) évalue le flottant que la fonction aurait dû renvoyer par valeur en premier lieu, sans nécessitant un pointeur vers un emplacement de stockage spécial.

Par ailleurs, vous pouvez vérifier ce que votre fonction fait quand parmB est 0.

+0

Merci beaucoup. Je vois que je traitais la conversion de type au mauvais moment. Vos exemples montrent les différentes façons dont je pourrais le gérer avec succès.Et merci de ne pas seulement recommander que je change l'appel de fonction, comme je ne peux pas. – cyotee

+0

@cyotee: si cela vous intéresse, je viens de penser à une solution C++ qui permettrait l'appel en tant que '* powerArgs', sans données partagées, et sans fuites de mémoire. Je vais le poster, mais si vous apprenez seulement C, pas C++, ignorez-le ... –

1

D'abord, votre int *powerArgs(int *pA, int *pB) fonction retourne l'adresse d'une variable locale, qui se traduit par un comportement non défini. Utilisez les éléments suivants à la place:

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

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

    return result; 
} 

Ensuite, si vous voulez convertir en float, vous ne devriez pas le faire dans l'appel à printf(), mais plutôt convertir la valeur en floatavant l'appel comme ceci:

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

ITYM '(float) powerArgs (& parmA, & parmB);' –

+0

Merci pour l'aide. Cela clarifie ma compréhension de la façon de le faire correctement. Mais la tâche indique que nous ne pouvons pas modifier main(). Nous pouvons seulement construire la fonction pour produire la sortie désirée en fonction de la façon dont elle est appelée. J'aimerais pouvoir simplement réécrire pour le rendre plus sensible, mais je ne peux pas. – cyotee

1

Lorsqu'une fonction se termine, toutes ses variables locales cessent d'exister (et leurs adresses pointent vers des déchets). Pour faire plaisir à votre professeur qui a créé cette interface très délicate, vous devez trouver un moyen de garder un objet en vie après que la fonction existe.

Vous avez, au moins, 3 options:
a) la réutilisation un des paramètres d'entrée
b) utiliser une variable globale
c) utiliser une variable statique

l'option

a)

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

l'option b)

int global_power; 

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

o ption c)

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

Aucune de ces "solutions" n'est bonne; le moins mauvais est l'option c)