String to Int without atoi/isdigit - c

How can I convert a string to an array without using atoi, atol, isdigit, anything like that?
Assume I have a const char *str and a int *converted_val as parameters.
Here's what I have:
const char *c;
for(c = str; (*c != '\0') && isdigit(*c); ++c){
*converted_value = *converted_value*10 + *c - '0';
}
return true;
but once again, I can't do it without isdigit. And I'm not sure how to handle strings that are large (for instance: "10000000000000000")

int yetAnotherAtoi(char *str)
{
int res = 0; // Initialize result
// Iterate through all characters of input string and
// update result
for (int i = 0; str[i] != '\0'; ++i) {
if (str[i]> '9' || str[i]<'0')
return -1; # or other error...
res = res*10 + str[i] - '0';
}
// return result.
return res;
}

Substitute isdigit(*c) by *c >= '0' && *c <= '9':
const char *c;
....
for( c = str; *c != '\0' && *c >= '0' && *c <= '9'; ++c) {
*converted_value = (*c - '0') + *converted_value*10;
}
return true;
Note that ASCII signs '0' to '9' are in ascending order.
You are limited to the range of the integral datatype of converted_value.

Change:
int *converted_val
to
long int *converted_val
to have more space for larger values. You might also consider adding code to check if the input string is going to overflow your output variable.

if you want string to integer without use function in Visual Studio you can do like below code:
#include "stdafx.h"
#include<iostream>
#include<string>
#include<conio.h>
using namespace std;
int main()
{
std::string str ;
getline(cin, str);
int a = 0;
for (int i = 0 ; i<str.length(); i++) {
a = (int)(str[i] - 48) + a * 10;
}
cout << a;
_getch();
return 0;
}

Related

Convert string of lower case to upper case? In C

My professor gave me some exercises in C language... In one of them I have to pass a string as an argument to a function, this function will verify the existence of lower case letters in the array and convert it into upper case letter;
Actually there's a function to do such a thing, but I can't use string.h.
Does anyone have an idea to do it?
void converterup(char palavra[])
{
int i;
for(i = 0; i < 10; i++)
{
if(palavra[i] != 'a')
{
palavra[i] == 'A';
}
}
Would be something like this?
you need to include <ctype.h> before using function toupper, then use it like in example below (I edited your code, need to adjust it for your needs):
for(i = 0; i < 10; i++){
palavra[i] = toupper(palavra[i]);
}
this loop will convert 10 first characters to their upper ascii equivalents
or if you cannot use standard functions, you can use function like this:
char myUpperChar(char x){
const int delta = 'a' - 'A'; //'a' has ascii code 97 while 'A' has code 65
if(x <= 'z' && x >= 'a'){
x -= delta;
}
return x;
}
If a character is between 'a' and 'z', you could just add ('A' - 'a') to it to convert it to upper.
char input, output;
int diff = 'A' - 'a';
output = input;
if ('a' <= input && input <= 'z')
output += diff;
return output;
I guess your professor is expecting something more basic without external functions, like this.
char str[] = "hello";
int len = sizeof(str) / sizeof(char);
int i;
for(i = 0; i < len; i++) {
int ascii = str[i];
if(ascii >= 97 && ascii <= 122) {// 97 => 'a' and 122 => 'z' in ascii
str[i] = (char) (ascii - 32); // 32 is the ascii substraction of lower
} // and upper letters 'a' - 'A'
}
Then output would be:
HELLO
function will verify the existence of lower case letters in the
array and convert it into upper case letter;
I can't use string.h.
Then you have to do conversion yourself. Take a look at the ASCII chart.
Then you can notice that small and capital letters are 0x40 apart.
0x40 happens to be space ' ';
Loop through your array and convert only the small letters
arr[i] <= 'z' && arr[i] >= 'a'
remember that small and capital letters are ' ' apart.
arr[i] = arr[i] - ' ' ;
advance to next character in the array by increasing the index i++ and stop when you encounter the end of the string arr[i]=='\0'.
#include <stdio.h>
void converterup(char arr[])
{
size_t i = 0;
if(arr == NULL) return;
while(arr[i]) // loop till the '\0'; this is equivalent to `arr[i]!='\0'`
{
if(arr[i] <= 'z' && arr[i] >= 'a'){
arr[i] = arr[i] - ' ' ;
}
i++;
}
}
int main(void)
{
char str[] = "Hello World!";
converterup(str);
printf("%s",str);
return 0;
}
Test:
HELLO WORLD!
Check out my code guys, is it acceptable?
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
void strupr(char palavra[])
{
int i;
for(i = 0;palavra[i] > 60 && palavra[i] < 122; i++)
{
printf("%c", palavra[i] - 32);
}
}
int main(void)
{
setlocale(LC_ALL, "");
char palavra[10];
printf("Insira uma palavra maiúsculas: "); gets(palavra);
printf("Valor com conversão: ");
strupr(palavra);
return 0;
}

Writing my own atoi function

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);
}
}

checking if character is upper or lower case in alphanumeric

I have this C code. If I input a LOL123 it should display that it is uppercase. And lol123 it is in lowercase. How do I use isalpha in excluding non-numerical input when checking isupper or is lower?
#include <stdio.h>
#define SIZE 6
char input[50];
int my_isupper(char string[]);
int main(){
char input[] = "LOL123";
int m;
m= isupper(input);
if( m==1){
printf("%s is all uppercase.\n", input);
}else
printf("%s is not all uppercase.\n", input);
return 0;
}
int my_isupper(char string[]){
int a,d;
for (a=0; a<SIZE); a++){
d= isupper(string[a]) ;
}
if(d != 0)
d=1;
return d;
}
For upper-case function just loop trough the string and if a lowercase character is encountred you return false like value. And don't use standard library functions names to name your own functions. Use isUpperCase instead.
Live Demo: https://eval.in/93429
#include <stdio.h>
#include <string.h>
int isUpperCase(const char *inputString);
int main(void)
{
char inputString1[] = "LOL123";
char inputString2[] = "lol123";
printf("%s is %s\n", inputString1, isUpperCase(inputString1)?"upper-case":"not upper-case");
printf("%s is %s\n", inputString2, isUpperCase(inputString2)?"lower-case":"not upper-case");
return 0;
}
int isUpperCase(const char *inputString)
{
int i;
int len = strlen(inputString);
for (i = 0; i < len; i++) {
if (inputString[i] >= 'a' && inputString[i] <= 'z') {
return 0;
}
}
return 1;
}
int my_isalpha_lower(int c) {
return ((c >= 'a' && c <= 'z')); }
int my_isalpha_upper(int c) {
return ((c >= 'A' && c <= 'Z')); }
int isdigit(int c) {
return (c >= '0' && c <= '9'); }
while (*s) {
if (!is_digit(*s) && !my_isalpha_lower(*s))
{
//isnot lower but is alpha
}
else if (!is_digit(*s) && !my_alpha_upper(*s))
{
//is not upper but is alpha
}
s++;
}
char c = ...;
if (isalpha(c))
{
// do stuff if it's alpha
} else {
// do stuff when not alpha
}
You have a lot to learn, besides using a name of a standard function your design also is completely flawed. You only memorize the case of the last character that you encounter in your for loop, so the result that you return is not at all what you think.
Some more observations:
Don't use the name of a standard function for your own.
Arrays decay to pointers when then are used as function parameters. You have no way to automatically detect the size of the array.
You expect your return from isupper to be a logical value. Testing that again with ==1 makes not much sense.
You have two different variables called input, one in file scope, one in main.
Fairly simple:
#include <ctype.h>
/**
* Will return true if there's at least one alpha character in
* the input string *and* all alpha characters are uppercase.
*/
int allUpper( const char *str )
{
int foundAlpha = 0;
int upper = 1;
for ( const char *p = str; *p; p++ )
{
int alpha = isalpha( *p );
foundAlpha = foundAlpha || alpha;
if ( alpha )
upper = upper && isupper( *p );
}
return foundAlpha && upper;
}

C code to convert hex to int

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;
}

C program to remove repeated char from a string

I came across a interview question that asked to remove the repeated char from a given string, in-place.
So if the input was "hi there" the output expected was "hi ter". It was also told to consider only alphabetic repititions and all the
alphabets were lower case. I came up with the following program. I have comments to make my logic clear. But the program does not work as expectd for some inputs. If the input is "hii" it works, but if its "hi there" it fails. Please help.
#include <stdio.h>
int main()
{
char str[] = "programming is really cool"; // original string.
char hash[26] = {0}; // hash table.
int i,j; // loop counter.
// iterate through the input string char by char.
for(i=0,j=0;str[i];)
{
// if the char is not hashed.
if(!hash[str[i] - 'a'])
{
// hash it.
hash[str[i] - 'a'] = 1;
// copy the char at index i to index j.
str[j++] = str[i++];
}
else
{
// move to next char of the original string.
// do not increment j, so that later we can over-write the repeated char.
i++;
}
}
// add a null char.
str[j] = 0;
// print it.
printf("%s\n",str); // "progamin s ely c" expected.
return 0;
}
when str[i] is a non-alphabet, say a space and when you do:
hash[str[i] - 'a']
your program can blow.
ASCII value of space is 32 and that of a is 97 so you are effectively accessing array hash with a negative index.
To solve this you can ignore non-alphabets by doing :
if(! isalpha(str[i]) {
str[j++] = str[i++]; // copy the char.
continue; // ignore rest of the loop.
}
This is going to break on any space characters (or anything else outside the range 'a'..'z') because you are accessing beyond the bounds of your hash array.
void striprepeatedchars(char *str)
{
int seen[UCHAR_MAX + 1];
char *c, *n;
memset(seen, 0, sizeof(seen));
c = n = str;
while (*n != '\0') {
if (!isalpha(*n) || !seen[(unsigned char) *n]) {
*c = *n;
seen[(unsigned char) *n]++;
c++;
}
n++;
}
*c = '\0';
}
This is code golf, right?
d(s){char*i=s,*o=s;for(;*i;++i)!memchr(s,*i,o-s)?*o++=*i:0;*o=0;}
...
// iterate through the input string char by char.
for(i=0,j=0;str[i];)
{
if (str[i] == ' ')
{
str[j++] = str[i++];
continue;
}
// if the char is not hashed.
if(!hash[str[i] - 'a'])
{
...
#include <stdio.h>
#include <string.h>
int hash[26] = {0};
static int in_valid_range (char c);
static int get_hash_code (char c);
static char *
remove_repeated_char (char *s)
{
size_t len = strlen (s);
size_t i, j = 0;
for (i = 0; i < len; ++i)
{
if (in_valid_range (s[i]))
{
int h = get_hash_code (s[i]);
if (!hash[h])
{
s[j++] = s[i];
hash[h] = 1;
}
}
else
{
s[j++] = s[i];
}
}
s[j] = 0;
return s;
}
int
main (int argc, char **argv)
{
printf ("%s\n", remove_repeated_char (argv[1]));
return 0;
}
static int
in_valid_range (char c)
{
return (c >= 'a' && c <= 'z');
}
static int
get_hash_code (char c)
{
return (int) (c - 'a');
}
char *s;
int i = 0;
for (i = 0; s[i]; i++)
{
int j;
int gap = 0;
for (j = i + 1; s[j]; j++)
{
if (gap > 0)
s[j] = s[j + gap];
if (!s[j])
break;
while (s[i] == s[j])
{
s[j] = s[j + gap + 1];
gap++;
}
}
}

Resources