The following is my implementation of the problem: http://www.spoj.com/problems/ACODE/
#include <stdio.h>
#include <string.h>
int main() {
long long int dp[5010] = { 0 }, i, len, ans;
char str[5010];
scanf("%s", str);
while (str[0] != '0') {
len = strlen(str);
dp[0] =1;
for (i = 1; i < len; i++) {
ans = (str[i-1] * 10 + str[i]);
if (str[i] - '0')
dp[i] = str[i];
if (ans >= 10 && ans <= 26) {
if ((i - 2) < 0)
dp[i] += dp[0];
else
dp[i] += dp[i-2];
}
}
scanf("%s", str);
}
printf("%llu\n", dp[len-1]);
return 0;
}
When I run it in my IDE, it gets executed but the output is completely different from expected. Also when I run it on Ideone it shows "time limit exceeded". Please help me in finding my mistake.
There are several errors:
You print the result only once, for the last string. You should, of course, print a result for all strings. Your code currently looks like this:
scanf("%s",str);
while (str[0] != '0') {
// determine solution
scanf("%s", str);
}
printf("%llu\n", dp[len-1]);
The printf should go before the last scanf.
This:
ans = (str[i - 1] * 10 + str[i]);
is a calculation on ASCII codes. You need somethingb like this:
ans = ((str[i - 1] - '0') * 10 + str[i] - '0');
The code
if (str[i] - '0') dp[i] = str[i];
should handle substrings that begin with a zero, but it leaves dp[i] effectively uninitialised (or filled with garbage from a previous string) for such strings.
The principal error is that you attack the problem from the wrong end, though. When you go forward through the string, your algorithm loks like this:
if the next two digits are a number from 10 to 26:
dp[i] = dp[i + 1] + dp[i + 2]
else if the current digit isn't zero:
dp[i] = dp[i + 1]
else:
dp[i] = 0
That code requires knowledge of dp[j] with j > i in order to calculate dp[i]. That means that you can solve the problem by walking through the array backwards. Your solution is then dp[0].
Because you only look forward one or two digits, you don't even need an auxiliary array; it is enough to keep the last two values and swap them accordingly after each iteration.
Here's a solution that does this. It has only been tested for the given cases, but it should give you an idea how to solve your problem. The code doesn't do a lot of checking; it is assumed that the string has only digits.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
unsigned long long poss(const char *str)
{
unsigned long long p1, p2;
size_t len = strlen(str);
size_t i;
if (len == 0) return 0;
i = len - 1;
p1 = 1;
p2 = 1;
if (str[i] == '0') p1 = 0;
while (i-- > 0) {
unsigned long long p = p1;
if (str[i] == '0') p = 0;
if (str[i] == '1') p += p2;
if (str[i] == '2' && str[i + 1] < '7') p += p2;
p2 = p1;
p1 = p;
}
return p1;
}
int main(void)
{
char str[5001];
while(scanf("%s",str) == 1 && str[0] != '0') {
printf("%llu\n", poss(str));
}
return 0;
}
What you need is a recursive function whitch divides if you find somthing in between 10 and 26
long long int count_decodings( const char * str )
{
long long int count = 1;
// only accept digits
// continue while next character greater or equal '0' and less or equal '9'
while ( ( *str >= '0' && *str <= '9' ) )
{
char actChar = *str;
str ++; // increment string pointer ( now str points to character after actChar )
if ( actChar == '1' && ( *str >= '0' && *str <= '9' ) )
{
// if we have 1 followed by somthing from 0 to 9 we have an new case
count += count_decodings( str + 1 ); // continue with next sign and increment count of decodings
}
else if ( actChar == '2' && ( *str >= '0' && *str <= '6' ) )
{
// if we have 2 followed by somthing from 0 to 6 we have an new case
count += count_decodings( str + 1 ); // continue with next sign and increment count of decodings
}
}
return count;
}
int main()
{
char str[5010];
scanf("%s",str);
while(str[0]!=0)
{
long long int count = count_decodings( str );
printf( "%llu\n", count);
scanf("%s", str);
}
return 0;
}
Related
I'm trying to create a function that converts an integer into a string, basically what have I done is the following functions: when we get the numbers from the conversion they are reversed so I need a reverse function to make them in the right way. The intostring uses (I think? I got it from some website) the ascii table to convert the number into the string desired.
The problem is: when I enter the 2-digit number they are reversed the wrong way (I guess my reverse function doesn't work that well) and after a certain number of digit the conversion it's not any more accurate.
reverse function:
char reverse(char *stringa) {
int len = strlen(stringa) - 1;
for(int i = 0; i < len / 2; i++) {
char tmp = stringa[i];
stringa[i] = stringa[len - i];
stringa[len - i] = tmp;
}
}
intostring function:
void intostring(int num, char *str) {
int i = 0;
while (num != 0) {
int rem = num % 10;
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num = num / 10;
}
str[i] = '\0';
reverse(str);
}
The condition i<len/2 in the reverse function is wrong.
For example, if the string is 2-digit long, len will be 1 and len/2 will be 0. Therefore, no swap will occure while the two characters should be swapped.
the condition should be i<=len/2 or i<len-i.
/*
It works clearly . Checked.
*/
void reverse(char source[],char destination[]) {
int x,i;
//start from last char
i = i=(strlen(source)-1
for (x=0;x<strlen(source);x++){
//Insert char at i in source to x in destination
destination[x]=source[i];
destination[x]='\0';
i--;
}
}
There are multiple problems:
the reverse function fails for an empty string. You should not subtract 1 from the length, but adjust the offset inside the loop.
reverse is defined to return a char but does not return anything. Make it return a char * and return stringa.
intostring produces an empty string for num <= 0. You should loop while num > 9 and add the final digit after the loop.
intostring converts the digit into a character for bases up to 36 (assuming ASCII). This is unnecessarily complex since the base is 10. Use a simpler conversion: str[i++] = '0' + rem;
it may be useful for intostring to return a pointer to the destination array.
Here is a modified version:
#include <string.h>
char *reverse(char *str) {
size_t len = strlen(str);
for (size_t i = 0; i < len / 2; i++) {
char tmp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = tmp;
}
return str;
}
char *intostring(int num, char *str) {
int i = 0;
if (num >= 0) {
while (num > 9) {
str[i++] = '0' + num % 10;
num = num / 10;
}
str[i++] = '0' + num;
} else {
while (num < -9) {
str[i++] = '0' - num % 10;
num = num / 10;
}
str[i++] = '0' - num;
str[i++] = '-';
}
str[i] = '\0';
return reverse(str);
}
Here is an alternative approach for the reverse function using 2 index variables:
#include <string.h>
char *reverse(char *str) {
size_t i = 0;
size_t j = strlen(str);
while (j --> i) {
char c = str[j];
str[j] = str[i];
str[i++] = c;
}
return str;
}
The reverse function condition is worng.
If the integer in 32 then the string will be
s[0] = '2', s[1] = '3', s[2] = '\0' before string reversal.
so in reverse function the following swap operation has to be applied as
if number = 32 then len = 2
i = 0 then len - i - 1 = 1
so 0 and 1 will be swaped.
void reverse(char *stringa){
int len = strlen(stringa);
for(int i = 0; i < len / 2; i++){
char tmp = stringa[i];
stringa[i] = stringa[len - i - 1];
stringa[len - i - 1] = tmp;
}
}
void intostring(int num, char *str)
{
int i = 0;
if(num == 0){
str[i++] = '0';
str[i] = '\0';
}
else if(num > 0){
while(num != 0){
int rem = num % 10;
str[i++] = '0' + rem;
num = num/10;
}
str[i] = '\0';
}
else{
while(num != 0){
int rem = num % 10;
/*
(-5/2) => -2
-2 * 2 => -4
so a%b => -1
(5/-2) => -2
-2 * -2 => 4
so a%b => 1
*/
rem = abs(rem); // as the rem value is negative
str[i++] = '0' + rem;
num = num/10;
}
str[i++] = '-';
str[i] = '\0';
}
reverse(str);
}
Your reverse function is wrong. You can make it correct (and readable) like below:
void reverse(char *stringa) {
int i = 0; //Forwarding moving index
int j = strlen(stringa) - 1; // the end index
int tmp; // Edited to get the code compiled
for (; i < j; i++, j--) {
tmp = stringa[i];
stringa[i] = stringa[j];
stringa[j] = tmp;
}
}
So here is the problem:
Input a string contains of numbers from 0 to 9 (maximum length is 15)
If the left most character divisible by 3, remove it from the string
If the right most character divisible by 3, remove it from the string
If the string does not match the above two conditions, and if the summary of the left most character and the right most character is divisible by 3, remove them from the string.
Keep doing so until the string is NULL or not meet the above conditions.
Example: input: "312248" ---> output: 2.
input: "366936363" ---> output: ""
So here is my code:
#include <stdio.h>
#include <stdbool.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
char* truncateString(char* s)
{
char *p = &s[0];
int n = strlen(s);
p = calloc(n,sizeof(char));
int flag = 1;
do{
for (int i = 0; i < strlen(s); i++)
{
if ((s[0]-'0') % 3 == 0)
{
for(int j = 0; j < strlen(s); j++)
{
s[j] = s[j+1];
}
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if ((s[strlen(s)-1]-'0') % 3 == 0)
{
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if (((s[strlen(s)-1]-'0')+(s[0]-'0')) % 3 == 0)
{
for(int j = 0; j < (strlen(s)-1); j++)
{
s[j] = s[j+1];
p = realloc(p, (strlen(s)-2)*sizeof(char));
}
}
else
{
flag = 0;
}
}
} while (strlen(s) != 0 || flag != 0);
free(p);
return s;
}
int main()
{
char s[100];
gets(s);
printf("Result:%s", truncateString(s));
getch();
return 0;
}
I honestly do not know how to check if the character is divisible by 3 or not, so the code is not running.
I'd consider a re-write that clearly matches the coding goals to fix functional errors.
(s[0]-'0') % 3 == 0 is a fine way to test for divisibility as s[0]-'0' provides the textual char to int value.
It is often useful to put the goals in as comments right where they are used.
strlen() needs to be called just once. Update the length as needed. This avoids repetitive calls to strlen(), each costing O(len).
char* truncateString(char *s) {
char *start = s;
size_t len = strlen(s);
// Keep doing so until the string is "NULL"
while (len > 0) {
char left = s[0] - '0';
bool left_remove = left % 3 == 0;
char right = s[len - 1] - '0';
bool right_remove = right % 3 == 0;
bool right_differ_from_left = len > 1;
// If the left most character divisible by 3, remove it from the string
if (left_remove) {
s++;
len--;
}
// Only consider the 'right' if the string was more than 1.
if (right_differ_from_left) {
// If the right most character divisible by 3, remove it from the string
if (right_remove) {
len--;
s[len] = '\0';
}
// If the string does not match the above two conditions,
// and if the summary of the left most character and
// the right most character is divisible by 3,
// remove them from the string.
if (!left_remove && !right_remove && (left + right) % 3 == 0) {
s++;
len -= 2;
s[len] = '\0';
left_remove = right_remove = true;
}
}
// Keep doing so until the string is ... not meet the above conditions.
if (!left_remove && !right_remove) {
break;
}
}
// Move string to its original beginning.
return memmove(start, s, len + 1);
}
If the coding goals are stable, simplifications exists. Yet notice that this may be faster, it is harder to see it matches the coding goals than the above.
char* truncateString2(char *s) {
char *start = s;
size_t len = strlen(s);
size_t len_at_loop_start;
do {
len_at_loop_start = len;
while (len > 0 && (s[0] - '0') % 3 == 0) {
s++;
len--;
}
while (len > 0 && (s[len-1] - '0') % 3 == 0) {
len--;
}
while (len > 1 && (s[0] - '0' + s[len-1] - '0') % 3 == 0) {
s++;
len -= 2;
}
} while (len < len_at_loop_start);
s[len] = '\0';
return memmove(start, s, len + 1);
}
You are having troubles with reallocation too. Try this, it may make things easier
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (strlen(s) != 0 && flag != 0){
if ((s[0]-'0') % 3 == 0)
s++;
else if ((s[strlen(s)-1]-'0') % 3 == 0)
s[strlen(s)-1] = '\0';
else if (((s[strlen(s)-1]-'0')+(s[0]-'0')) % 3 == 0)
{
s++;
s[strlen(s)-1] = '\0';
}
else
flag = 0;
}
return s;
}
Quick explanation: when you declare s++ you are preciselly removing the first element of the array, and using s[strlen(s)-1] = '\0' removes the last element.
EDIT:
Another solution here, that will work faster. Instead of calling s[strlen(s)-1] each time, you can just keep track of the initial n=strlen(s); Also, removed the -'0', because ASCII codes for numbers start in 48, so they are in the right position for checking divisibility by 3. Thanks to #chux-ReinstateMonica. Here is the code:
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (n != 0 && flag != 0){
if ((s[0]) % 3 == 0){
s++;
n--;
}
else if ((s[n-1]) % 3 == 0)
s[--n] = '\0';
else if (((s[n-1])+(s[0])) % 3 == 0)
{
s++;
n--;
s[--n] = '\0';
}
else
flag = 0;
}
return s;
}
I try to create atoi function, and think I made right code, but when I run it, it shows wrong one. I'm trying to figure it out, but don't know what I made it wrong please check the code and give some help
My code is
#include <stdio.h>
int my_atoi(char *str)
{
int i;
int res;
int sign;
i = 0;
res = 0;
sign = 1;//sign of '-' or '+'
while(str[i] == ' ' || (str[i] >= 9 && str[i] <= 13))
{
i++;
}
if(str[i] == '-')
{
sign = -1;
i++;
}
else if(str[i] == '+')
{
sign = 1;
i++;
}
while(str[i] >= '0' && str[i] <= '9')
{
res = res * 10 + str[i] + '0';
i++;
}
return(res * sign);// to make integer which has value of '-' or '+'
}
int main(void)
{
char str[] = "-2018shiba";
printf("%d\n", my_atoi(str));
return(0);
}
When I run it, it shows -108674
I am seeing multiple mistakes here.
If you want to convert a ASCII character into the corresponding integer you need to subtract '0'. Take a look at the ASCII table: for instance '7' is mapped by decimal value 55. Hence if you want to get 7 then you need to subtract the ASCII of '0' which is 48 (55 - 48 = 7):
int foo = str[i] - '0';
In the very last while loop of my_atoi. The value of an indexed numeral string representation is calculated by multiplying the value of str[i] with the numerical base to the power of the index starting from behind.
For example lets take a look at "1337":
7*10^0 + 3*10^1 + 3*10^2 + 1*10^3 = 7 + 30 + 300 + 1000 = 1337
As you can see, the 7 has the numerical index 0 and so on. Assuming you want to just ignore shiba your code be looking something like this:
#include <stdio.h>
#include <string.h>
// Return base^(exponent)
int my_pow(int base, unsigned int exponent)
{
if (exponent == 0) {
return 1;
} else {
int result = base;
for (int i = 1; i < exponent; i++) {
result *= base;
}
return result;
}
}
int my_atoi(char *str, size_t len)
{
int i;
int res;
int sign;
i = 0;
res = 0;
sign = 1;//sign of '-' or '+'
while(str[i] == ' ' || (str[i] >= 9 && str[i] <= 13))
{
i++;
}
if(str[i] == '-')
{
sign = -1;
i++;
}
else if(str[i] == '+')
{
sign = 1;
i++;
}
// Store the index where the number string starts
int j = i-1;
// Find the ending index of the number string
i = len;
while (str[i] < '0' || str[i] > '9') {
i--;
}
int num_end = i;
// Now start at the ending
while(i > j)
{
if (str[i] >= '0' && str[i] <= '9') {
res += my_pow(10, num_end-i) * (str[i] - '0');
} else {
// If a character unequal to a digit is found then skip it
num_end--;
}
i--;
}
return(res * sign);// to make integer which has value of '-' or '+'
}
int main(void)
{
char str[] = "-2018shiba";
printf("%d\n", my_atoi(str, strlen(str)));
char str2[] = "-20X18shiba";
printf("%d\n", my_atoi(str2, strlen(str2)));
return(0);
}
I am trying to convert a string of numerical characters to their corresponding integral form. Please suggest what is wrong with the code. I would like to stick with pointers. I understand that the pointer str points to the first character in my string. So, each time I call my function in the loop, I want the pointer to increment by 1, and add the value of the character to one node in my array. For some reason, though I am unable to do so. Here is the code.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
int ctoi(char *c);
int main (void)
{
char *str;
int A[20];
int i = 0;
str = (char*) malloc(20 * sizeof(char));
printf("Input the string. ");
scanf("%s", str);
while(str != '\0')
{
A[i] = ctoi(str);
i++;
str++;
}
for(i = 0; i < strlen(str); i++)
printf("%d", A[i]);
getchar();
getchar();
return 0;
}
int ctoi(char *c)
{
int a;
a= *c - '0';
return a;
}
for (i=0;i<strlen(str);i++)
printf("%d", A[i]);
Here strlen will return 0 because you updated str in your previous loop .Replace it with :
for(i=0;i<len;i++)
where len is the length of your input string .Find it before using str in while loop
while(str!='\0') should be `while(*str!='\0')`
. You will get it . But for writing your own atoi function you dont need to store the number in an array
Please try this it works, the myatoi() function was lifted perhaps 20 years ago from the classic "THE C PROGRAMMING LANGUAGE" , get the book.
#include <stdio.h>
main()
{
char temp[99];
strcpy(temp , "34");
printf( "\n %d " , myatoi(temp));
strcpy( temp , "8642");
printf( "\n %d " , myatoi(temp));
}
int myatoi( char s[])
{
int i,n,sign;
// skip white space
for( i=0 ; s[i]==' ' || s[i]=='\n' ||s[i]=='\t';i++) ;
sign=1;
if( s[i]=='+' || s[i]=='-')
sign=( s[i++]=='+' ? 1 : -1 );
for( n=0; s[i]>='0' && s[i]<='9' ; i++)
n=10*n+s[i]-'0' ;
return(sign*n);
}
OP's code needs a few (at least 2) fixes to mostly work. See ***
int main (void)
{
char *str;
int A[20];
int i = 0;
// *** Cast not needed, '* sizeof(char)' not needed
str = malloc(20);
printf("Input the string. ");
scanf("%s", str);
// ***
char *str_original = str;
while(*str != '\0')
{
A[i] = ctoi(str);
i++;
str++;
}
// ***
str = str_original;
for(i = 0; i < strlen(str); i++)
printf("%d", A[i]);
// ***
free(str); // Good to return memory
str = NULL;
getchar();
getchar();
return 0;
}
A simple way to convert a string to an int
int strtoi(const char *s) {
int sum = 0;
char ch;
char sign = *s;
if (*s == '-' || *s == '+') s++;
while ((ch = *s++) >= '0' && ch <= '9') {
sum = sum * 10 - (ch - '0');
}
if (sign != '-') {
sum = -sum;
}
return sum;
}
Notes: This code accumulates the sum on the negative side of 0 to avoid UB when trying to parse the string for INT_MIN. Modified code could skip leading white-space, add text error detection, overflow detection, etc.
Here is my custom atoi funtion, who handle unsigned int with debug gestion:
int my_getnbr(char *str)
{
int nb;
int sign;
int i;
nb = 0;
sign = 0;
i = -1;
if (!str)
return (0);
while (str[++i])
if (str[i] < '0' && str[i] > '9' && str[i] != '-' && str[i] != '+')
return (0);
i = 0;
while (str[i] != '\0' && (str[i] == '-' || str[i] == '+'))
if (str[i++] == '-')
++sign;
while (str[i] && (str[i] >= '0' && str[i] <= '9'))
{
nb = (nb * 10) + (str[i++] - '0');
if (str[i] == ' ')
i++;
}
return (((sign % 2) == 1) ? ((nb) * (-1)) : (nb));
}
tested with that main:
int main()
{
printf("%d\n", my_getnbr("-42"));
printf("%d\n", my_getnbr("-+-+--42"));
printf("%d\n", my_getnbr("-0"));
printf("%d\n", my_getnbr("590310"));
return (0);
}
No leaks, here is the result:
-42
42
0
590310
Firstly
while(str!='\0') should be
while(*str!='\0')
You should compare the content, not the address.
And while printing the returned data, you are doing
for(i=0;i<strlen(str);i++)
printf("%d", A[i]);
str already parsed till the last. So length would probably be 0.
Change your while loop to
while(*str!='\0')
{
A[i]=ctoi(*str);
i++;
str++;
}
And your function to
int ctoi(char c)
{
int a;
a= c-'0';
return a;
}
There are several approaches for a simple atoi replacement without the base conversion flexibility in strtol. The simplest is generally to find the length of the string to convert, and then work backward toward the front of the string preforming the conversion from string to integer as you go. A quick example would be:
/* a quick atoi replacement */
int atoi2 (char *s)
{
int nmax = (1ULL << 31) - 1; /* INT_MAX */
long long n = 0; /* the number to return */
size_t m = 1; /* multiplier for place */
size_t l = 0; /* length of string */
char *p = s;
while (*p++) l++; /* get string length */
p -= 2; /* position at last char */
while (l--) /* for each char in string */
{ /* verify a digit or '-' sign */
if ((*p >= '0' && *p <= '9') || *p == '-')
{
if (*p == '-') { /* if '-' is first char */
if (p == s) n = -n; /* negate value */
}
else { /* otherwise normal conversion */
n += (*p - '0') * m;
if (n > nmax) { /* prevent overflow */
fprintf (stderr, "atoi2() error: conversion > INT_MAX.\n");
exit (EXIT_FAILURE);
}
m *= 10;
}
}
p--;
}
return (int) n;
}
A simple driver program to test could be:
#include <stdio.h>
#include <stdlib.h>
int atoi2 (char *s);
int main (int argc, char **argv) {
if (argc < 1) return 1;
printf ("\n string : %s, conversion : %d\n\n",
argv[1], atoi2 (argv[1]));
return 0;
}
Example Use/Output
$ ./bin/atoi2 321
string : 321, conversion : 321
$ ./bin/atoi2 -321
string : -321, conversion : -321
$ ./bin/atoi2 2147483647
string : 2147483647, conversion : 2147483647
$ ./bin/atoi2 2147483648
atoi2() error: conversion > INT_MAX.
If you have any questions, please do not hesitate to ask.
Here is a custom atoi function that avoids using most of the standard library functions
/*** _atoi - finds the first set of integers in a given string
* #s: string entered
* Return: first number sequence
**/
int _atoi(char *s)
{
int length = 0, negativeCount = 0, count = 0, num = 0;
while (s[length] != '\0')
{
length++;
}
while (count < length)
{
if (s[count] == '-')
{
negativeCount++;
}
if (s[count] >= 48 && s[count] <= 57)
{
/* ascii values for numbers */
for (; s[count] >= 48 && s[count] <= 57; count++)
{
num = (10 * num - (s[count] - 48));
}
break;
}
count++;
}
if (negativeCount % 2 != 0)
{
return (num);
}
else
{
return (-num);
}
}
I am writing this code to convert a hex entry into its integer equivalent. So A would be 10 and B would be 11 etc. This code acts weirdly, in that it seg. faults at random locations and including an extra newline character at times will get it to work. I am trying to debug it, just so I can understand what I am doing wrong here. Can anyone take a look and help me here ? Thanks a lot for your time.
/* Fixed working code for anyone interested */
#include <stdio.h>
#include <stdlib.h>
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
int dec;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
if ( temp[i] == '\0')
{
return ;
}
if (temp[i] == '0' || temp[i] == 'x' || temp[i] == 'X' )
{
printf("0");
answer = temp[i];
}
// compare each temp[i] with all contents in hexchar[]
int j;
int a = temp[i];
for ( j=0; hexchar[j] != '\0'; j++)
{
if ( temp[i] == hexchar[j] )
{
answer *= 16;
answer = answer + 10 + (j/2);
// printf("%d\n",answer );
break;
}
}
}
return answer;
}
main()
{
char *test[] =
{ "bad",
"aabbdd"
"0100",
"0x1",
"0XA",
"0X0C0BE",
"abcdef",
"123456",
"0x123456",
"deadbeef",
"zog_c"
};
int answer=0;
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
printf("main():Number of chars = %d\n",numberOfChars);
int i;
// Go through each character and convert Hex to Integers.
for ( i = 0; i<numberOfChars;i++)
{
// Need to take the first char and then go through it and convert
it.
answer = hextoint(test[i]);
printf("%d\n",answer );
}
}
Let's take a look.
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
printf("In here");
printf("%c\t",temp[i] );
}
return answer;
}
This doesn't seem to even try to do any conversion. It should always return 0, since answer is never assigned any other value. Normally, you'd do something like:
for (i=0; input[i] != '\0'; i++) {
answer *= 16;
answer += digit_value(input[i]);
}
return answer;
Where digit_value (obviously enough) returns the value of an individual digit. One way to do this is:
int digit_value(char input) {
input = tolower(input);
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1; // signal error.
}
Then, looking at main:
main()
{
Depending on the "implicit int" rule is generally poor practice, at least IMO. It's much better to specify the return type.
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
This actually calculates the number of strings, not the number of chars.
for ( i = 0; i<=numberOfChars;i++)
Valid subscripts run from 0 through the number of items - 1, so this attempts to read past the end of the array (giving undefined behavior).
This'll work for any number within the unsigned int range, the nice thing is it does not use any other library functions so it is great for micro-controllers where space is tight.
unsigned int hexToInt(const char *hex)
{
unsigned int result = 0;
while (*hex)
{
if (*hex > 47 && *hex < 58)
result += (*hex - 48);
else if (*hex > 64 && *hex < 71)
result += (*hex - 55);
else if (*hex > 96 && *hex < 103)
result += (*hex - 87);
if (*++hex)
result <<= 4;
}
return result;
}
The problem is with calculating numberOfChars part. sizeof test is actually the size of the pointer, not the total length of all characters in your array, so the number returned in your code would be 1, which makes the for loop go to the second index of test (test[1]) which does not have a \0 at the end. Try using strlen for calculating numberOfChars.
This may not me the most optimal method, but it should work without problem.
unsigned int hex_to_int(const char* hex) {
unsigned int result = 0;
size_t len = strlen(hex);
for (size_t i = 0; i < len; ++i) {
char cur_char = tolower(hex[len - i - 1]);
// direct return if encounter any non-hex character.
if (!(isdigit(cur_char) && (cur_char >= 'a' && cur_char <= 'f'));)
return result;
unsigned int char_val = (isdigit(cur_char) ? cur_char - '0' : 10 + cur_char - 'a');
result += round(pow(16, i)) * char_val;
}
return result;
}