// 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)