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);
}
Related
I tried to write a solution from exercise 2-3. After compilation, it returns random numbers on output. I don't really understand where this issue is coming from.
Any help appreciated.
StackOverflow keeps asking for more details. The purpose of the program is listed in the code bellow.
More delails.
Purpose of the code:
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.
/*
* 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.
*/
#include <stdio.h>
#include <math.h>
int hti(char s)
{
const char hexlist[] = "aAbBcCdDeEfF";
int answ = 0;
int i;
for (i=0; s != hexlist[i] && hexlist[i] != '\0'; i++)
;
if (hexlist[i] == '\0')
answ = 0;
else
answ = 10 + (i/2);
return answ;
}
unsigned int htoi(const char s[])
{
int answ;
int power = 0;
signed int i = 0;
int viable = 0;
int hexit;
if (s[i] == '0')
{
i++;
if (s[i] == 'x' || s[i] == 'X')
i++;
}
const int stop = i;
for (i; s[i] != '\0'; i++)
;
i--;
while (viable == 0 && i >= stop)
{
if (s[i] >= '0' && s[i] <= '9')
{
answ = answ + ((s[i] - '0') * pow(16, power));
}
else
{
hexit = hti(s[i]);
if (hexit == 0)
viable = 1;
else
{
hexit = hexit * (pow(16, power));
answ += hexit;
}
}
i--;
power++;
}
if (viable == 1)
return 0;
else
return answ;
}
int main()
{
char test[] = "AC";
int i = htoi(test);
printf("%d\n", i);
return 0;
}
answ is not initialized in htoi. Initialize it to zero.
The following program gives the result as 0 instead of the expected decimal equivalent of the hexadecimal string constant.
#include <stdio.h>
int my_htoi(char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(char str[]) {
int i, num = 0;
for (i = 0; i != '\0'; ++i) {
if (str[i+1] == 'x' || str[i+1] == 'X') {
i = i + 1;
continue;
}
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
}
}
return num;
}
While the following program runs fine and outputs the correct decimal equivalent of the hexadecimal string constant.
#include <stdio.h>
#include <string.h>
int my_htoi(char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(char str[]) {
int i, num = 0;
for (i = 0; i < strlen(str); ++i) {
if (str[i+1] == 'x' || str[i+1] == 'X') {
i = i + 1;
continue;
}
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
}
}
return num;
}
The only difference is in the way we find the qualifying condition for the loop. Why does it not work with the null byte checking?
Wrong code: i != '\0' checks if the index is 0.
for(i = 0; i != '\0'; ++i) {
Should be the below to check if the element str[i] is the null character.
for(i = 0; str[i] != '\0'; ++i) {
Other issues exists unneeded increment, int overflow (better to use unsigned here), wrong x detection - consider "0x0x0x1", leading - or +, char str[] --> const char str[], ...
There are some problems in your code:
the loop index i is compared to '\0' instead of str[i], causing immediate termination of the loop with a return value of 0.
the test for x is incorrect: it would cause "1x2" to convert to 2 instead of 1.
you accept letters beyond f and convert them to digits. The function should instead stop parsing at the first character that is not a hex digit.
Here is a corrected version:
#include <stdio.h>
int my_htoi(const char[]);
int main(void) {
printf("%d", my_htoi("0xABC"));
return 0;
}
int my_htoi(const char str[]) {
int i = 0, num = 0;
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
i += 2;
for (; str[i] != '\0'; ++i) {
if (str[i] >= '0' && str[i] <= '9') {
num = num * 16 + (str[i] - '0');
} else if (str[i] >= 'a' && str[i] <= 'f') {
num = num * 16 + (str[i] - 'a' + 10);
} else if (str[i] >= 'A' && str[i] <= 'F') {
num = num * 16 + (str[i] - 'A' + 10);
} else {
break;
}
}
return num;
}
My code should find hex numbers in a user input (followed or not by 0x), copy them in an array as a string and, every time it finds a non 1-9 a-f A-F character or EOF, it should execute the htoi function converting the characters in the string into a decimal number, proceeding from right to left and using a multiplier to account for the position. It doesn't do what it's supposed to do. It generates numbers that have nothing to do with the decimal equivalent of my hex numbers.
#include <stdio.h>
#include <string.h>
#include <math.h>
int htoi(char num[]);
int main()
{
int c,i = 0;
char num[1000];
while ((c = getchar()) != EOF)
{
if ((c > '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'a' && c <= 'f'))
{
num[i] = c;
i++;
}
else if (c == '0')
{
if ((c = getchar) == 'x' || c == 'X')
{
num[i] = '\0';
printf("%d", htoi(num));
i=0;
}
else
{
num[i] = c;
i++;
}
}
else
{
num[i] = '\0';
if (num[0] != '\0')
{
printf("%d", htoi(num));
}
i=0;
}
}
num[i] = '\0';
if (num[0] != '\0')
{
printf("%d", htoi(num));
}
i=0;
return 0;
}
int htoi(char num[])
{
int c,i, dig;
int dec;
int multiplier = 1;
for (i = strlen(num)-1; i >= 0; i--)
{
c = num[i];
if (c > '0' && c <= '9')
{
dig = c - '0';
}
else if (c > 'a' && c <= 'f')
{
dig = c - 'a' + 10;
}
else if (c > 'A' && c <= 'F')
{
dig = c - 'A' + 10;
}
dec = dec + dig * multiplier;
multiplier * 16;
return dec;
}
}
Three problems:
multiplier * 16; just throws away the result. You'd want multiplier *= 16
return dec returns immediately with the current value of dec. You should have that after the loop.
The variable dec is uninitialized, which means it will have an indeterminate value. Using it without initialization, like you do, will lead to undefined behavior.
There are other problems as well, some of which would have been caught by the compiler leading to errors or warnings. The three above was just what I found after a quick glance.
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;
}
I am writing a program where I am taking string as an input, here I need to remove spaces , ignore alphabets and use only numerals.
I am able to achieve removing spaces and alphabets, but i can only use single digits and not multiple digits.
Example:Input string:"adsf 12af 1 a123c 53c2m34n"
Here I need to use the input as "12 1 123 54234" required for my application.
It will be great some one could share the logic or the sample code for the same.
Thanks in advance
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int pullOut(const char *str, int array[], int *size){
const char *p = str, *endp;
int pull, count = 0, max = *size, num;
do{
endp=strchr(p, ' ');
if(endp == NULL)
endp=strchr(p, '\0');
for(num=pull=0; p != endp; ++p){
if(isdigit(*p)){
num = num * 10 + *p - '0';
pull = 1;
}
}
if(pull && count < max)
array[count++] = num;
while(*p == ' ')
++p;//skip sapce
}while(*endp != '\0');
return *size = count;
}
int main(void){
char input[] = "adsf 12af 1 a123c 53c2m34n abc def";
int i, arr[128] = { 0 }, arr_num = sizeof(arr)/sizeof(int);
pullOut(input, arr, &arr_num);
for(i = 0; i < arr_num ; ++i)
printf("%d\n", arr[i]);
return 0;
}
int i = 0;int j = 0;
while (input[i])
{
if (input[i] == ' ' || (input[i] >= '0' && input[i] <= '9'))
newString[j++] = input[i];
i++;
}
newString[j] = '\0';
If you do this, you'll copy only numerics and space into newString. I let you do all the memory alloc stuff.
here is your func:
void remove_func(char *str)
{
int i;
i = 0;
while(str[i])
{
if(str[i] >= '0' && str[i] <= '9')
{
putchar(str[i]);
i++;
}
else if(str[i] == ' ' && str[i + 1] != ' ')
{
putchar(str[i]);
i++;
}
else
i++;
}
}
What about this one:
char * getNumbers(const char *src, char *dst)
{
int j=0,i=0;
while (i < strlen(src))
{
if (src[i] >= '0' && src[i] <= '9')
{
dst[j++]=src[i++];
}
else
{
// skip duplicates spaces
if (j > 0 && src[i] == ' ' && dst[j-1] != ',') dst[j++]=',';
i++;
}
}
// remove the trailing ',' if exists
if (j > 0 && dst[j-1] == ',') j--;
dst[j]='\0';
return dst;
}
char src[] = "adsf 12af 1 a123c 53c2m34n";
char dst[sizeof(src)];
getNumbers(src, dst);
printf("'%s' -> '%s'\n", src, dst);
output:
'adsf 12af 1 a123c 53c2m34n' -> '12,1,123,53234'