本题要求实现一个函数,将一组数字型字符串,转换成double型的浮点数。
函数接口定义:
函数接口如下:
double myatof(char s[]);
其中s[ ]是输入的数字型字符串,函数返回一个double类型的浮点数。
裁判测试程序样例:
主函数中通过键盘输入一组字符串,调用myatof函数进行转换并打印输出 。
#include "stdio.h"
#define N 20
double myatof(char s[]);
int main()
{
double num;
char s[N];
while(1)
{
scanf("%s",s);
if (s[0]=='q') break;
num=myatof(s);
printf("%f\n",num);
}
return 0;
}
/* 请在这里填写答案 */
输入样例:
输入多个数字型的字符串,每个字符串之间换行符隔开。字符串可能包括空格符、正负符号、小数点以及其它非数字字符。 对输入的字符串进行转换时,首先跳过行首的空格字符,直到遇上数字、小数点或正负符号才开始做转换,而再遇到其它非数字字符时或字符串结束时才结束转换,并将结果返回。 当输入字符'q'时,程序结束。 例如:
6.348
-2.98
.525
q
输出样例:
double型浮点数,显示小数点后六位。 当为正数时,浮点数第一位不显示'+'。 当为负数时,浮点数第一位显示'-'. 如:
6.348000
-2.980000
0.525000
我的完全错误但结果相同的代码:
double myatof(char s[])
{
int i,j=1,flag_dot=-1;
int start=0,end=-5;
char *a = s;
double result,item=0;
for(i=0;a[i]!='\0';i++) //去除空格
{
if(a[i]!=' '&&flag_dot==0)
{
start = i;
flag_dot = 1;
}
if(!(a[i]>='0'&&a[i]<='9' || a[i]=='.' || a[i] == '-'))
{
end = i-1;
break;
}
}
if(end==-5) //记录尾端
{
end = i-1;
}
flag_dot = -1;
a = a+start;
end -= start;
if(a[0]=='.') //开始列出 小数, 负数,整数的情况
{
for(i=1;i<=end;i++)
{
item = item*10+(a[i]-48);
j *= 10;
}
result = item/j;
return result;
}
else if(a[0]>='0'&&a[0]<='9')
{
for(i=0;i<=end;i++)
{
if(a[i]=='.')
{
flag_dot = i;
break;
}
}
if(flag_dot==-1)
{
for(i=0;i<=end;i++)
{
item = item*10+(a[i]-48);
}
result = item;
return result;
}
else
{
for(i=0;i<=end;i++)
{
if(a[i]!='.')
item = item*10+(a[i]-48);
}
for(i=flag_dot+1;i<=end;i++)
{
j*=10;
}
result = item/j;
return result;
}
}
else if(a[0]=='+'||a[0]=='-')
{
for(i=1;i<=end;i++)
{
if(a[i]=='.')
{
flag_dot = i;
break;
}
}
if(flag_dot==-1)
{
for(i=1;i<=end;i++)
{
item = item*10+(a[i]-48);
}
if(a[0]=='-')
result = -item;
else
result = item;
return result;
}
else
{
for(i=1;i<=end;i++)
{
if(a[i]!='.')
item = item*10+(a[i]-48);
}
for(i=flag_dot+1;i<=end;i++)
{
j*=10;
}
result = item/j;
if(a[0]=='-')
result = -result;
return result;
}
}
}
参考了同学后自己写的代码:
double myatof(char *str)
{
char *ch = str;
int flag=1,i;
int point=0;
int pow=1;
double sum = 0;
while(!(*ch>='0'&&*ch<='9'||*ch=='+'||*ch=='-'||*ch=='.')&&*ch!='\0')
ch++;
if(*ch=='\0') return 0;
if(*ch == '-') //判断负号
{
flag = -1;
ch++;
}
if(*ch == '+')
{
ch++;
}
while(*ch>='0'&&*ch<='9')
{
sum=sum*10+(*ch-'0');
ch++;
}
if(*ch=='.')
{
ch++;
while(*ch>='0'&&*ch<='9')
{
sum=sum*10+(*ch-'0');
ch++;
pow*=10;
}
}
if(sum==0)
return 0;
return flag*sum/pow;
}
总结:为什么我最开始写的那么繁琐?
区别就在于,我以为必须分情况写,以去除空格后的开头字符是什么来划分。是'+' '-' ,还是数字 ,还是 '.' 。
而其中涉及一些近似的操作,我是采用的复制+微调。可实际上,在上述代码中,仅仅用了两个标志变量,就解决了问题。
最关键的是,后来的这个代码可读性就很好,把每一步都分开了,一旦有问题也很容易修改。
在最初代码提交时,一直答案错误。是,一旦将代码复杂化,就容易产生各种各样的隐形错误。而很多时候,我们自己是难以看出来的。
那么这也就给了我一些启发,一旦遇到那些感觉过程贼复杂,代码贼繁琐的。不要长时间死扣,不停的补充各种额外情况。不如先想想,有没有什么地方可以优化,比如没必要读完在处理,而是边读边处理等等。看似复杂的问题,往往都有一些经过思考可以发现的简单解法。