summaryrefslogtreecommitdiffstats
path: root/main.c
blob: bf4573637e9d3c82c3aae760582b1838df3fdc69 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*	Copyright (C) 2021 Gentoo-libre Install

	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/*
Exercise 2ยท3. Write the function htoi (s ), which converts a string of hexa-
decimal digits (including an optional 0x or 0X) into its equivalent integer value.
The allowable digits are 0 through 9, a through f, and A through F.
*/

//function to calculate square roots
unsigned long powq(int number, int power)
{
unsigned long result = 1;//result int, 1 by default
if (!power){return 1;}//if to the power of 0, return 1
while(power)//loop until all powers have been calculated
	{
	result *= number;//Effectively result=number*number*(number is repeated as many times as the "power" int
	--power;//--power since a power has been calculated
	}
return result;
}


//htoi(): converts a string of hex encoded in ASCII to an integer value. (No negative input num handling, no invalid char handling (treats invalid chars like a '0') and ignores overflows)
unsigned long long htoi(char s[])
{
unsigned long long result = 0;//result is by default; 0
int power = 0;//power is by default; 0
while(s[power] != '\0'){++power;}//increment power for however many non-null chars in the string.
--power;//We need 1 less than the number of non-null chars.

int i = 0;//loop variable
while(s[i] != '\0')//loop until a NULL char
{
if (s[i] >= '0' && s[i] <= '9')//if char is a number, add as such
	{
	result += ((s[i] - '0') * powq(16,power));//result = result + ([char converted to number] * (16^[e.g. 3...2... etc])
	goto skip;//no need to check if the chars any other, since we already did so and calculated
	}

if (s[i] >= 'A' && s[i] <= 'F')//check for digit
	{
	result += ((s[i] - 55) * powq(16,power));//result = result + ([char converted to number] * (16^[e.g. 3...2... etc])
	goto skip;//no need to check if the chars any other, since we already did so and calculated
	}

if (s[i] >= 'a' && s[i] <= 'f')//check for digit
	{
	result += ((s[i] - 87) * powq(16,power));//result = result + ([char converted to number] * (16^[e.g. 3...2... etc])
	goto skip;//no need to check if the chars any other, since we already did so and calculated
	}


skip: ++i;//increment i to read the next char
--power;//Deincrement the power. E.g. ([charvalue]*(16^3))+([nextcharvalue]*(16^2)) etc
}

if (s[0] == '-'){return -result;}//handle negative numbers

return result;//return the converted number
}

int main(int argc, char *argv[])
{
bool negative = false; //handle negative numbers
if (!argv[1]){goto stdinMode;}

	if (argv[1][1] == '-')
	{
	printf("Usage (stdin mode): %s\n", argv[0]);
	printf("Ctrl+D to exit\n");
	printf("Usage (cli args mode): %s [hexnum]\n", argv[0]);
	printf("Licence: AGPLv3\n");
	return 0;
	}
if (argv[1][0] == '-'){negative = true;}//handle negative numbers

//strip out invalid chars from the input string
int x,y;//counter variables
for (x=0; argv[1][x] != '\0'; ++x)
	{
	if ( ((argv[1][x]>=1)&&(argv[1][x]<='/')) || ((argv[1][x] >=':')&&(argv[1][x]<='@')) || ((argv[1][x]>='G')&&(argv[1][x]<='`')) || ((argv[1][x]>='g')&&(argv[1][x]<=127)) )//if input[i] is an invalid character (dirty but only option)
		{
		y=x;//point to overwite equals y
		while(argv[1][y] != '\0'){argv[1][y++] = argv[1][y+1];}//shift all characters above left, overwriting the character
		--x;//deincrement x, since the string was just shrunk by one and the one just above could indeed be a matching char
		}
	}


if (negative){printf("-%llu\n", htoi(argv[1])); return 0;}
printf("%llu\n", htoi(argv[1]));
return 0;

stdinMode: ;

int size = 10;
char *input = malloc(size*sizeof(char));
if (!input){printf("Malloc failed!\n"); return 1;}

int i;
nextnum: i=0;
char c;
while ((c=getchar())!='\n')
{
if (c==EOF){free(input); exit(0);}//exit if EOF
if (i==size-1){size+=4; input=realloc(input,size*sizeof(char)); if (!input){printf("Realloc failed!\n"); return 1;}}//realloc input array if input is about to overflow it
input[i]=c;
++i;
}
input[i] = '\0'; //add NULL char for htoi


//strip out invalid chars from the input string
if (input[0] == '-'){negative = true;}//handle negative numbers
int j;//another counter variable
for (i=0; input[i] != '\0'; ++i)
	{
	if ( ((input[i]>=1)&&(input[i]<='/')) || ((input[i] >=':')&&(input[i]<='@')) || ((input[i]>='G')&&(input[i]<='`')) || ((input[i]>='g')&&(input[i]<=127)) )//if input[i] is an invalid character (dirty but only option)
		{
		j=i;//point to overwite equals j
		while(input[j] != '\0'){input[j++] = input[j+1];}//shift all characters above left, overwriting the character
		--i;//deincrement i, since the string was just shrunk by one and the one just above could indeed be a matching char
		}
	}

if (negative){printf("Decimal: -%llu\n", htoi(input)); negative = false; goto nextnum;}
printf("Decimal: %llu\n", htoi(input));
goto nextnum; //process another number

//never reached, but left in case of the removal of nextnum
free(input);

return 0;
}