summaryrefslogtreecommitdiff
path: root/ex4-2.c
blob: 8a5757520777e73ccd5209f910571f365ea1e86b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>

/*static int _strlen(char s[]) {
    int i;
    for (i=0; s[i] != '\0'; i++) {}
    return i;
}*/

/*static int _isspace(char s) {
    return s == ' ' || s == '\t';
}*/

static int _isdigit(char s) {
    return '0' <= s && s <= '9';
}

static int _abs(int a) {
    if (a >=0) {
        return a;
    } else {
        return -1 * a;
    }
}

static int _intval(char s) {
    return s - '0';
}

static int _isupper(char s) {
    return 'A' <= s && s <= 'Z';
}

static char _tolower(char s) {
    static int diff = 'A' - 'a';
    if (_isupper(s)) {
        return s - diff;
    } else {
        return s;
    }
}


static int _atoi_internal(char s[], int n) {
    if (s == NULL || *s == '\0' || !_isdigit(*s)) {
        return n;
    }
    __attribute__((musttail)) // Functional programinng enabler :) 
    return _atoi_internal(s + 1, (10 * n) + _intval(*s));
}
/**
 * Converts a string to an integer
 * string must be null terminated
 * overflow isn't detected, int is the limit
 */ 
int _atoi(char s[]) {
    int i = 0;
    int sign = (s[i] == '-') ? -1 : 1;
    if (s[i] == '+' || s[i] == '-')
        i++;
    return _atoi_internal(s + i, 0) * sign;
}

/**
 * Converts a string to a double
 * 
 * string must be null terminated.
 * overflow isn't detected, and double precision is the limit.
 */
double _atof(char s[]) {
    double val, power, ee;
    int i = 0;
    int sign = (s[i] == '-') ? -1 : 1;
    if (s[i] == '+' || s[i] == '-')
        i++;
    for (val = 0.0; _isdigit(s[i]); i++)
        val = 10.0 * val + _intval(s[i]);
    if (s[i] == '.')
        i++;
    for (power = 1.0; _isdigit(s[i]); i++) {
        val = 10.0 * val + _intval(s[i]);
        power *= 10.0;
    }
    ee = 1.0;
    if (_tolower(s[i]) == 'e') {
        i++;
        int exponent = _atoi(s + i);
        if (exponent >= 0) {
            for (int j=0;j<_abs(exponent);j++) ee *= 10.0;
        } else {
            for (int j=0;j<_abs(exponent);j++) ee /= 10.0;
        }
    }
    return (sign * val / power) * ee;

}

void testb(char s[]) {
    printf("atoi s = [%s] result = [%d]\n", s, _atoi(s));
}

void test(char s[]) {
    printf("atof s = [%s] result = [%lf]\n", s, _atof(s));
}

int main(void) {
    test("");
    test("gibber");
    test("\0");
    test("1");
    test("1.0");
    test("99.0");
    test("-10.0");
    test("+11.0");
    test("++11.0");
    test("-11111111111111111111111111111111111111111111111111111111111111111111111111111111111.1");

    testb("gibber");
    testb("");
    testb("\0");
    testb("1");
    testb("1.5");
    testb("+2.6");
    testb("-7.8");
    testb("--7.8");
    
    test("+11.0e5");
    test("2.75345e3");
    test("2.75345e-3");
    test("2.75345E-3");
}