原题: https://www.patest.cn/contests/pat-b-practise/1024
实现思路: 按照前后符号不同可以分4种情况, 分别如下
- input: +1.23400E-03 output: 0.00123400
- input: -1.2E-10 output: -0.00000000012 (一共10个0)
- input: -1.2E+10 output: -12000000000 (一共9个0)
- input: +1.23400E+03 output: 1234.00
首先, 经过我的测试, 明确一点, 并不存在E-0, E+0这种情况.
正如我下面的代码定义的变量一样, 通过循环我们需要拿出: 中间字符串, 第1, 第2个符号,
最后的整数.
事实上具体到代码实现, 我们只需要按照第2个符号的不同, 分2种情况即可.
首先是第2个符号是负号, 也就是E-X, 这种形式, 结果肯定是形如0.00123400这种形式,
可以看到, 唯一需要确定就是中间有多少个0的问题, 通过分析可知, 中间需要end-1个0,
也就是E后面数的绝对值-1
第2种情况是后面的符号是正号的情况, 这种情况稍微有点复杂, 需要分成小数点在中间和
小数点在末尾(也就是无小数点)两种情况. 小数点在末尾我们可以通过2次循环, 第1次把我们
提取出来的中间字符串放进结果数组, 第2次把0添加到小数点之前. 小数点在中间的情况只需
遍历我们提取出来的字符串, 在适当的位置插入小数点即可.
完整C语言实现:
#include <stdio.h>
int main () {
char input[10010]; // 输入字符串
char one; // 第1个符号
char mid[10000]; // 中间数字字符串, 不包括小数点
int mlen = 0; // 中间字符串的长度
char two; // 第2个符号
int end = 0; // 最后的整数
char res[20000]; // 保存最终结果
int rlen; // 结果数组的长度
int pos; // 小数点的位置
char *ptr;
int i;
int temp;
scanf("%s", input);
one = input[0];
ptr = input + 1;
// 把mid[], mlen拿到
while (1) {
if (*ptr == '.') {
ptr++;
continue;
}
mid[mlen] = *ptr;
mlen++;
ptr++;
if (*ptr == 'E') {
two = *(ptr + 1);
ptr += 2; // 这时候指向第2符号后面的第1个数字
break;
}
}
// 把end拿到
while (*ptr != '\0') {
end = end * 10 + (*ptr - '0');
ptr++;
}
// 现在搞res结果数组, 一共分2种情况
if (two == '-') {
res[0] = one;
res[1] = '0';
res[2] = '.';
rlen = 3;
// 在[3, end-1]的地方放出'0'
for (i=1; i<=end-1; i++) {
res[rlen] = '0';
rlen++;
}
for (i=0; i<mlen; i++) {
res[rlen] = mid[i];
rlen++;
}
}
if (two == '+') {
res[0] = one;
rlen = 1;
pos = end + 2; // 小数点的位置
if (pos >= mlen + 1) {
// 小数点在末尾
for (i=0; i<mlen; i++) {
res[rlen] = mid[i];
rlen++;
}
temp = rlen;
for (i=temp; i<pos; i++) {
res[rlen] = '0';
rlen++;
}
} else {
// 小数点在中间
for (i=0; i<mlen; i++) {
res[rlen] = mid[i];
rlen++;
if (rlen == pos) {
res[rlen] = '.';
rlen++;
}
}
}
}
// 打印
for (i=0; i<rlen; i++) {
// 正号不打印
if (res[i] == '+') {
continue;
}
printf("%c", res[i]);
}
return 0;
}