Je concevons une fonction qui convertira une ficelle en float. par exemple. "45.5" = 45.5
Je l'ai jusqu'à présent. Mais cela ne semble pas fonctionner. Gardez à l'esprit, nous ne pouvons utiliser aucune bibliothèque C de bibliothèque C comme Atoi, ATOF ou même POW pour cette affaire. P>
int str2float( char *s ) { int num = 0; int dec = 0; double i = 1.0; int ten = 1; /***** ADD YOUR CODE HERE *****/ for(; *s != '\0'; s++) { if (*s == '.'){ for(; *s != '\0'; s++){ dec = (dec * CONT) + (*s - '0'); i++; } }else{ num = (num * CONT) + (*s - '0'); } } for(;i!=0;i--){ ten *= 10; } dec = dec / (ten); printf("%d", dec); num += dec; return num; }
11 Réponses :
Un problème potentiel est que s code> est incrémenté par la boucle externe avant de vérifier que cela ne pointe pas sur le terminateur NULL.
for(; *s != '\0'; s++)
{
...
for(; *s != '\0'; s++){
...
}
// inner loop is done now since we have *s=='\0' ...
...
// ... but now we're going to increment s again at the end of the outer loop!
}
Voici mon essai:
float stof(const char* s){ float rez = 0, fact = 1; if (*s == '-'){ s++; fact = -1; }; for (int point_seen = 0; *s; s++){ if (*s == '.'){ point_seen = 1; continue; }; int d = *s - '0'; if (d >= 0 && d <= 9){ if (point_seen) fact /= 10.0f; rez = rez * 10.0f + (float)d; }; }; return rez * fact; };
Merci, ça marche. Je devais faire les endroits décimaux jusqu'à 4 pour qu'il affiche la sortie correcte. Merci encore.
@user quand je l'exécute, la sortie est 24.5 code>.
Oui tu as raison! Mon erreur, j'avais un VaR temporaire qui était un Int et non un double qui causait la combinaison.
Quelque chose comme ça devrait le faire: Le code pourrait ne pas être très propre et pas nécessairement le meilleur moyen de le faire, mais vous obtenez l'idée. POW (X, Y) retourne x ^ y et nécessite des maths.h et des lants (s) renvoie la taille de s et nécessite string.h. p> p>
désolé je ne peux pas utiliser SHLEN. Aucune fonction de bibliothèque C.
@ user373466: Vous pouvez implémenter votre propre fonction Strlen. C'est une question de 3 lignes .. :)
Ou vous pouvez définir décimalpointLoc code> initialement à 1000 et sauter
SHLEN code> complètement. EDIT: OOH, il ajoute
'0' code> au lieu de soustraire, alors supposer que cela ne soit pas testé du tout.
Les arguments code> sont également échangés.
double Myatof(char str[]){ int len=0, n=0,i=0; float f=1.0,val=0.0; //counting length of String while(str[len])len++; //cheking for valid string if(!len)return 0; //Extracting Integer part while(i<len && str[i]!='.') n=10*n +(str[i++]-'0'); //checking if only Integer if(i==len) return n; i++; while(i<len) { f*=0.1; val+=f*(str[i++]-'0'); } return(val+n); }
#define ZERO 48 #define NINE 57 #define MINUS 45 #define DECPNT 46 int strtoint_n(char* str, int n) { int sign = 1; int place = 1; int ret = 0; int i; for (i = n-1; i >= 0; i--, place *= 10) { int c = str[i]; switch (c) { case MINUS: if (i == 0) sign = -1; else return -1; break; default: if (c >= ZERO && c <= NINE) ret += (c - ZERO) * place; else return -1; } } return sign * ret; } float _float_fraction(char* str, int n) { float place = 0.1f; float ret = 0.0f; int i; for (i = 0; i < n; i++, place /= 10) { int c = str[i]; ret += (c - ZERO) * place; } return ret; } float strtoflt(char* str) { int n = 0; int sign = 1; int d = -1; int ret = 0; char* temp = str; while (*temp != '\0') { switch (*temp) { case MINUS: if (n == 0) sign = -1; else return -1; break; case DECPNT: if (d == -1) d = n; else return -1; break; default: if (*temp < ZERO && *temp > NINE) return -1; } n++; temp++; } if (d == -1) { return (float)(strtoint_n(str, n)); } else if (d == 0) { return _float_fraction((str+d+1), (n-d-1)); } else if (sign == -1 && d == 1) { return (-1)*_float_fraction((str+d+1), (n-d-1)); } else if (sign == -1) { ret = strtoint_n(str+1, d-1); return (-1) * (ret + _float_fraction((str+d+1), (n-d-1))); } else { ret = strtoint_n(str, d); return ret + _float_fraction((str+d+1), (n-d-1)); } }
Si quelqu'un veut connaître la réponse, il doit accéder à votre blog. De votre blog, vous fournissez un lien vers SkyDrive. De là, vous devez télécharger un fichier zip et l'extraire pour obtenir la solution. N'est-ce pas un peu trop compliqué? Inclure la source dans votre réponse !! Notez que Les réponses de liaison uniquement sont découragées, les réponses doivent donc être le point final d'une recherche pour une solution (contre une autre halte de références, qui tendent à devenir obsolète au fil du temps). Veuillez envisager d'ajouter un synopsis autonome ici, en gardant le lien comme référence.
Je pense que ma solution est plus robuste.
N'hésitez pas à contester mon code. Voici le lien: https://github.com/loverszhaokai/demo/blob/master /str_to_float/src/str_to_float.cc p>
Suivant est le code: p>
C'est une mauvaise idée d'accumuler le résultat en double, car chaque fois que vous ajoutez décimal + = (* str - '0') * déc_num code>, il existe une nouvelle erreur de contournement ajoutée (et des flotteurs binaires sont vraiment pauvres à représenter des pouvoirs négatifs de dix). Si vous conservez des entiers, vous ne diviserez qu'une seule fois et que le résultat sera dans une ULP de la valeur réelle. De plus,
STRUP () CODE> peut échouer et il s'agit d'une overcilleuse juste à cause de l'espace alimentaire - pourquoi pas seulement garder les pointeurs de début et de fin? Enfin, ".123" est parfaitement valide. En fait, j'ai utilisé cela formant beaucoup à un moment donné.
Ceci est ma solution pour Atof code> fonction.
#include<stdio.h>
float my_a2f(char *);
main() {
char ch[20];
float i;
printf("\n enter the number as a string\n");
scanf("%[^\n]", ch);
i = my_a2f(ch);
printf(" string =%s , float =%g \n", ch, i);
}
float my_a2f(char *p) {
// here i took another two variables for counting the number of digits in mantissa
int i, num = 0, num2 = 0, pnt_seen = 0, x = 0, y = 1;
float f1, f2, f3;
for (i = 0; p[i]; i++)
if (p[i] == '.') {
pnt_seen = i;
break;
}
for (i = 0; p[i]; i++) {
if (i < pnt_seen) num = num * 10 + (p[i] - 48);
else if (i == pnt_seen) continue;
else {
num2 = num2 * 10 + (p[i] - 48);
++x;
}
}
// it takes 10 if it has 1 digit ,100 if it has 2 digits in mantissa
for (i = 1; i <= x; i++)
y = y * 10;
f2 = num2 / (float) y;
f3 = num + f2;
return f3;
}
L'exemple de OP "45.5" code> est proposé avec
"float = 45.15" code> ici. Suggérer une critique.
Merci Chux, oui, si nous comptons le nombre de chiffres en num2 et divisez-le en fonction de cela. Ensuite, cela fonctionnera dans la plupart des cas, je mettrai à jour ma réponse. S'il vous plaît vérifier si cela fonctionne.
Mieux vaut utiliser float num, num2, y code> pour éviter le débordement. Mieux vaut utiliser
'0' code> que
48 code>.
F1 code> non utilisé.
#include<stdio.h> #include<string.h> float myAtoF(char *); //int myAtoI(char); void main(int argc,char **argv) { float res; char str[10]; if(argc<2) { printf("Supply a floating point Data\n"); return; } printf("argv[1] = %s\n",argv[1]); // strcpy(str,argv[1]); // printf("str = %s\n",str); res=myAtoF(argv[1]); printf("Res = %f\n",res); } float myAtoF(char *str) { printf("str = %s\n",str); int i,sum,total,index; float res; if(!strchr(str,'.')) { printf("Supply only real Data\n"); return ; } i=0; while(str[i]) { if(!str[i]>='0'&&str[i]<='9') { printf("Wrong Data Supplied\n"); return; } if(str[i]=='.') { index=i; i++; continue; } total=str[i]-48; if(i==0) { sum=total; i++; continue; } sum=sum*10+total; i++; } printf("Integer Data : %d\n",sum); index=(strlen(str)-1)-index; printf("index : %d\n",index); res=sum; for(i=1;i<=index;i++) { res=(float)res/10; } return res; }
double atof(char* num) { if (!num || !*num) return 0; double integerPart = 0; double fractionPart = 0; int divisorForFraction = 1; int sign = 1; bool inFraction = false; /*Take care of +/- sign*/ if (*num == '-') { ++num; sign = -1; } else if (*num == '+') { ++num; } while (*num != '\0') { if (*num >= '0' && *num <= '9') { if (inFraction) { /*See how are we converting a character to integer*/ fractionPart = fractionPart*10 + (*num - '0'); divisorForFraction *= 10; } else { integerPart = integerPart*10 + (*num - '0'); } } else if (*num == '.') { if (inFraction) return sign * (integerPart + fractionPart/divisorForFraction); else inFraction = true; } else { return sign * (integerPart + fractionPart/divisorForFraction); } ++num; } return sign * (integerPart + fractionPart/divisorForFraction); }
Tandis que cet extrait de code peut résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Testez-le strong> p> int str2int (const char *str) {
unsigned char abc;
int ret = 0;
for (abc = 1; abc & 1; str++) {
abc = *str == '-' ?
(abc & 6 ? abc & 6 : (abc & 23) | 20)
: *str == '+' ?
(abc & 6 ? abc & 6 : (abc & 7) | 4)
: *str > 47 && *str < 58 ?
abc | 10
: !(abc & 2) && (*str == ' ' || *str == '\t') ?
(abc & 23) | 1
:
abc & 22;
if (abc & 8) {
ret = ret * 10 + *str - 48;
}
}
return abc & 16 ? -ret : ret;
}
Qu'avez-vous gagné en abusant de l'opérateur ternaire? Les plus profonds vont bien, mais les extérieurs sont inutiles et prennent plus de temps à raison de l'équivalent si code> /
sinon code> chaîne.
L'opérateur ternaire n'est qu'une autre façon d'obtenir le même résultat, avec la même performance et avec une meilleure clarté du code (de cette manière, vous savez que les conditions sont toutes concentrées sur l'attribution d'une valeur à la variable abc Code>, avec un
si code> /
ele code> instruction Vous devez lire tout le bloc pour être sûr de celui-ci). Qu'est-ce que j'aurais gagné sans elle?
Je suppose que nous avons juste différentes idées sur la lisibilité, alors ... Cela ressemble à une personne qui a été écrite par quelqu'un qui vient d'apprendre à utiliser l'opérateur ternaire: p
Eh bien ... Mon code utilise un bitmask, et sans commentaire qui explique comment les drapeaux sont structurés, le code ci-dessus ne peut jamais être vraiment "lisible", je pense, indépendamment de vous écrire le si code> /
sinon code> chaîne.
Vrai. (Commentaire Rembourrage)
#include <stdio.h> #include <math.h> #include<string.h> double myatof(char *num); int main(void) { double res;char str[15]; printf("enter a number in the form of a string:\n"); gets(str); res=myatof(str); printf("Float representation of above number is %f\n",res); return 0; } double myatof(char *str) { int i=0;int len1,len2,j; float num=0.0;float num1=0.0; float num2=0.0; do { if((str[i++]=='.')) { len1=i-1;len2=-((strlen(str)-1)-(i-1)); for(int p=0,q=(len1-1);p<len1,q>=0;p++,q--) { num1+=((str[p]-'0')*pow(10,q)); } for(int r=len1+1,s=-1;r<strlen(str),s>=len2;r++,s--) { num2+=((str[r]-'0')*pow(10,s)); } } }while(str[i]!='\0'); num=num1+num2; printf("%f\t",num1); printf("%f\t",num2); return num; }
Le code ci-dessus ne fonctionnera pas pour -ve (négatif) numéros
Je vous suggère de mettre des déclarations Printf () dans chaque étape du calcul, de sorte que vous puissiez voir comment cela progresse. Vous verrez rapidement ce qui se passe mal.
Je me demande pourquoi votre str2float retourne un entier!
Et je vous suggère de passer à travers elle dans le débogueur. Imo c'est encore mieux que
printf code>.
strtod code> est votre meilleur pari. Vous dites que vous ne pouvez pas utiliser
atof code>, alors ajoutez la tagwork code> device code> si je supposais juste :)
N'oubliez pas de gérer des formes de signalisation et exponentielles de pointe; -1.234, +12.34, 1.0E6 Par exemple, il s'agit de formulaires valides traités par les fonctions standard.
Si les devoirs peuvent être effectués au nom des étudiants par REP-HUNTERS SO, quelle valeur est-elle dedans ces jours-ci?
C'est en fait un problème très difficile. Il est facile d'écrire une solution qui fonctionne pour les valeurs proches de 1, mais la gestion extrêmement grande et extrêmement petite est correctement une tâche que des experts ponctuels flottants et des mathématiciens devraient tenter ...
@David Heffernan: Il y a un dicton: plus ils trichent, mieux nous serons payés.
@David, cela ne triche pas. J'avais tenté ce problème pendant plus de 4 heures et je n'allais nulle part. Cela m'a aidé à comprendre le concept et ne me donnez pas seulement la réponse.