extract.c - OpenLearning
// extract.c
// funtions and types used to extract x,y,z values from a
// string containing a url of the form
// "http://almondbread.cse.unsw.edu.au:7191/tile_x3.14_y-0.141_z5"
// initially by richard buckland
// 13 April 2014
// your name here: Adley Phu

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "extract.h"

#define NEGATIVE 0
#define POSITIVE 1

static unsigned long long myAtoLL (char *message);
static unsigned long long power10 (int exponent);
static int digit (char letter);
static void testExtract (void);

int main (int argc, char *argv[]) {
    testExtract();
    return EXIT_SUCCESS;
}

triordinate extract (char *message) {
    int startX = 0;
    int endX = 0;
    int startY = 0;
    int endY = 0;
    int startZ = 0;
    int endZ = 0;
    int i = 0;
    while (endX == 0) {
        if (message[i] == 'x') {
            startX = i + 1;
        }
        // to prevent being triggered by the first underscore in the url
        if (message[i] == '_' && startX != 0) {
            endX = i - 1;
        }
        i++;
    }
    // actual length of x you have to add 1...
    int lenX = endX - startX + 1;
    // add one byte for the null terminator
    char *x = malloc ((lenX + 1) * sizeof(char));
    i = 0;
    while (i < lenX) {
        x[i] = message[startX + i];
        i++;
    }
    x[lenX] = '\0';
    // ----------------------------------------------------------------
    i = endX + 3;
    startY = i;
    // determine endY
    while (message[i] != '_') {
        i++;
    }
    endY = i - 1;
    int lenY = endY - startY + 1;
    char *y = malloc ((lenY + 1) * sizeof(char));
    i = 0;
    while (i < lenY) {
        y[i] = message[startY + i];
        i++;
    }
    y[lenY] = '\0';
    // -----------------------------------------------------------------
    startZ = endY + 3;
    endZ = strlen(message) - 1;
    int lenZ = endZ - startZ + 1;
    char *z = malloc ((lenZ + 1) * sizeof(char));
    i = 0;
    while (i < lenZ) {
        z[i] = message[startZ + i];
        i++;
    }
    z[lenZ] = '\0';
    triordinate dat;
    dat.x = myAtoD(x);
    dat.y = myAtoD(y);
    dat.z = myAtoL(z);
    return dat;
}

double myAtoD (char *message) {
    int stringLen = strlen(message);
    int sign = POSITIVE;
    int i = 0;
    if (message[0] == '-') {
        sign = NEGATIVE;
    }
    while (message[i] != '.') {
        i++;
    }
    i++;
    // divide by this number later... 12345 / 10000
    unsigned long long exponent = power10(stringLen - i);
    int decimalPoint = i - 1;
    char *mantissaString = malloc (stringLen);
    i = 0;
    if (sign == NEGATIVE) {
        i++;
    }
    int flag = 0;
    while (i < stringLen) {
        // skip the decimal point
        if ((flag && sign != NEGATIVE) || (sign == NEGATIVE && !flag)) {
            mantissaString[i - 1] = message[i];
        }
        else if (sign != NEGATIVE) {
            mantissaString[i] = message[i];
        }
        else if (flag) {
            mantissaString[i - 2] = message[i];
        }

        if (i == decimalPoint - 1) {
            i += 2;
            flag = 1;
        }
        else {
            i++;
        }
    }
    // null-terminate it
    mantissaString[stringLen - 1] = '\0';

    unsigned long long mantissa = myAtoLL(mantissaString);
    double final = (double) mantissa / exponent;
    if (sign == NEGATIVE) {
        final *= -1;
    }
    return final;
}

static int digit (char letter) {
    return letter - '0';
}

static unsigned long long power10 (int exponent) {
    int x = 0;
    unsigned long long power = 1;
    while (x < exponent) {
        power *= 10;
        x++;
    }
    return power;
}

static unsigned long long myAtoLL (char *message) {
    int stringLen = strlen(message);
    unsigned long long num = 0;
    unsigned long long power = power10 (stringLen - 1);
    int i = 0;
    while (i < stringLen) {
        num += power * digit(message[i]);
        power /= 10;
        i++;
    }
    return num;
}

long myAtoL (char *message) {
    // test if negative
    int type = POSITIVE;
    if (message[0] == '-') {
        type = NEGATIVE;
    }
    int stringLen = strlen(message);
    if (type == NEGATIVE) {
        stringLen--;
    }
    long num = 0;
    unsigned long long power = power10 (stringLen - 1);
    int i;
    if (type == NEGATIVE) {
        i = 1;
        stringLen++;
    }
    else {
        i = 0;
    }
    while (i < stringLen) {
        num += power * digit(message[i]);
        power /= 10;
        i++;
    }
    if (type == NEGATIVE) {
        num *= -1;
    }
    return num;
}

void testExtract(void) {
    char* str;
    triordinate dat;

    //random numbers
    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x3.14_y-0.141_z5";
    dat = extract(str);
    assert (dat.x == 3.14);
    assert (dat.y == -0.141);
    assert (dat.z == 5);

    //real urls
    str = "https://almondbread.cse.unsw.edu.au/tile_x0.008384417742490768_y0.6326243951916695_z14";
    dat = extract(str);
    assert (dat.x == 0.008384417742490768);
    assert (dat.y == 0.6326243951916695);
    assert (dat.z == 14);

    str = "https://almondbread.cse.unsw.edu.au/tile_x0.3994787931442261_y0.1260089874267578_z22";
    dat = extract(str);
    assert (dat.x == 0.3994787931442261);
    assert (dat.y == 0.1260089874267578);
    assert (dat.z == 22);

    str = "https://almondbread.cse.unsw.edu.au/tile_x0.3657526969909668_y0.3159613609313965_z15";
    dat = extract(str);
    assert (dat.x == 0.3657526969909668);
    assert (dat.y == 0.3159613609313965);
    assert (dat.z == 15);

    str = "https://almondbread.cse.unsw.edu.au/tile_x-0.23349761962890625_y0.6544036865234375_z16";
    dat = extract(str);
    assert (dat.x == -0.23349761962890625);
    assert (dat.y == 0.6544036865234375);
    assert (dat.z == 16);

    //some edge cases
    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x1.11111111_y1.11111111_z1";
    dat = extract(str);
    assert (dat.x == 1.11111111);
    assert (dat.y == 1.11111111);
    assert (dat.z == 1);

    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x-0.99999999999_y-0.99999999999_z999";
    dat = extract(str);
    assert (dat.x == -0.99999999999);
    assert (dat.y == -0.99999999999);
    assert (dat.z == 999);

    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x0.0000000000000001_y0.0000000000000001_z0";
    dat = extract(str);
    assert (dat.x == 0.0000000000000001);
    assert (dat.y == 0.0000000000000001);
    assert (dat.z == 0);

    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x0.0000000_y0.0000000_z0";
    dat = extract(str);
    assert (dat.x == 0.0000000);
    assert (dat.y == 0.0000000);
    assert (dat.z == 0);

    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x-3.14_y-0.141_z5";
    dat = extract (str);
    assert (dat.x == -3.14);
    assert (dat.y == -0.141);
    assert (dat.z == 5);

    // all negatives
    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x-3.14_y-0.141_z-5";
    dat = extract (str);
    assert (dat.x == -3.14);
    assert (dat.y == -0.141);
    assert (dat.z == -5);

    // really long numbers
    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x3.141231231298_y0.149542812311_z2147483647";
    dat = extract (str);
    assert (dat.x == 3.141231231298);
    assert (dat.y == 0.149542812311);
    assert (dat.z == 2147483647);

    // really long negative numbers
    str = "http://almondbread.cse.unsw.edu.au:7191/tile_x-3.141231231298_y-0.149542812311_z-2147483647";
    dat = extract (str);
    assert (dat.x == -3.141231231298);
    assert (dat.y == -0.149542812311);
    assert (dat.z == -2147483647);

    printf("All tests passed!\n");
}

Download file: extract.c (7.8 KB)

Comments

Chat