Ascii to integer using no library functions - c

My teacher gave us an assignment where we create a function that reads ASCII digit characters and converts them to a number without using any library functions such as atoi. Through some research i came up with this in my own file:
#include <stdio.h>
#include <sttdef.h>
int main() {
char testString[] = "123";
int convertedResult = 0;
int i;
for(i = 0; testString[i] != '\0'; i++){
convertedResult = convertedResult*10 + testString[i] - '0';
printf("%i\n",convertedResult);
if (testString[i] == '\0') {
break;
}
}
return 0;
}
While this works on its own i have to use the main file he gave us to call on this specific function.
char *asciiToInteger(char *inputString, int *integerPtr) {
return inputString;
}
I'm a bit confused as to how to proceed from here? attatched picture is main

#include <stdio.h>
#include <stddef.h>
char * asciiToInteger(char *inputString, int *integerPtr){
int convertedResult =0;
for(int i = 0; inputString[i] != '\0'; i++){
convertedResult = convertedResult*10 + inputString[i] - '0';
}
*integerPtr=convertedResult;
return inputString;
}
int main() {
char testString[] = "123";
int integerPtr;
asciiToInteger(testString, &integerPtr) ;
printf("%d\n",integerPtr);
return 0;
}

Your code has a couple of problems:
It assumes the entire string is digits
It checks for the end of string twice
I think a better implementation would be:
#include <stdio.h>
const char *asciiToInteger(const char *inputString, int *value)
{
int result = 0;
while (isdigit((unsigned int) *inputString))
{
result *= 10;
result += *inputString++ - '0';
}
*value = result;
return inputString;
}
This returns a pointer to the first non-converted character, which might be to the end of string marker if the string is all digits. I added const on the strings of course, since this converter is just reading from the strings.

When you get an assignment like this the first step is to make sure you understand what the function is supposed to do. Your question has no such description so that is the place to start.
From the behavior of the main function it seems to be something like:
If the first character in the input string is not a digit return NULL
If the first character in the input string is a digit convert all leading digits to an integer stored in the object pointed to by integerPtr and return a pointer to the character following the converted digits.
Examples:
inputString = "a123b67" --> return NULL
inputString = "123b67" --> *integerPtr = 123 and return a pointer to the 'b' in the input
That could look something like this:
char *asciiToInteger(char *inputString, int *integerPtr) {
if (*inputString < '0' || *inputString > '9')
return NULL; // no leading digit
*integerPtr = 0;
do
{
*integerPtr = *integerPtr * 10 + *inputString - '0';
++inputString;
} while (*inputString >= '0' && *inputString <= '9');
return inputString;
}
Notice that the code above can't handle negative integers.

Related

Long Long overflow

I have been working on a small program that converts strings into integers.
I started the program and I was first trying to save in an array but the program is not working.
Its iterating only once and there is no error.I tried it but I think the error is at when I convert the string by subtracting it by 48 in storing it in the array.You can see the code
Sorry this is an edited message tnow the program is working properly but when I give input -"-91283472332"(as per leetcode) I am getting a wrong answer
you can see for yourself -
#include <stdio.h>
int myAtoi(char *s)
{
int i = 0; // for iterating the character
int isNegative = 0; // for checking if the umber is negative
long long res = 0; // for result
while (s[i] != '\0')
{
printf("%d\n",res);
if (48 <= s[i] && s[i]<= 57)
{
res=(res*10)+(s[i]) - 48;
}
else if (s[i] == 45)
{
isNegative = 1;
}
else if (s[i] == ' ')
{
;
}
else
{
break;
}
i++;
}
if (isNegative)
{
res = res-(res*2);
}
printf("%d",res);
return res;
}
int main()
{
char a[] = "-91283472332";
myAtoi(a);
return 0;
}
Your solution is rather more complex than it needs to be.
We can use pointer arithmetic to iterate over the string, and include a condition for our for loop that automatically terminates at the end of the string or when the current character is no longer a digit.
The result can be built up by multiplying it by ten on each loop and adding the current digit's numeric value to it.
A negative sign can be accommodated by checking the first character. It's it's '-' we can set a flag negative to 1 for true and increment the str pointer past the first character. At the end of the function, we can determine whether to result -result or result based on that flag.
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int my_atoi(char *str) {
int result = 0;
int negative = 0;
if (*str == '-') {
negative = 1;
str++;
}
for (; *str && isdigit(*str); str++) {
result *= 10;
result += *str - '0';
}
return negative ? -result : result;
}
int main(void) {
char foo[] = "3456gfghd";
printf("%d\n", my_atoi(foo));
return 0;
}

How output a numbers with write() (only #include <unistd.h> allowed) [duplicate]

It is possible to convert integer to string in C without sprintf?
There's a nonstandard function:
char *string = itoa(numberToConvert, 10); // assuming you want a base-10 representation
Edit: it seems you want some algorithm to do this. Here's how in base-10:
#include <stdio.h>
#define STRINGIFY(x) #x
#define INTMIN_STR STRINGIFY(INT_MIN)
int main() {
int anInteger = -13765; // or whatever
if (anInteger == INT_MIN) { // handle corner case
puts(INTMIN_STR);
return 0;
}
int flag = 0;
char str[128] = { 0 }; // large enough for an int even on 64-bit
int i = 126;
if (anInteger < 0) {
flag = 1;
anInteger = -anInteger;
}
while (anInteger != 0) { 
str[i--] = (anInteger % 10) + '0';
anInteger /= 10;
}
if (flag) str[i--] = '-';
printf("The number was: %s\n", str + i + 1);
return 0;
}
Here's an example of how it might work. Given a buffer and a size, we'll keep dividing by 10 and fill the buffer with digits. We'll return -1 if there is not enough space in the buffer.
int
integer_to_string(char *buf, size_t bufsize, int n)
{
char *start;
// Handle negative numbers.
//
if (n < 0)
{
if (!bufsize)
return -1;
*buf++ = '-';
bufsize--;
}
// Remember the start of the string... This will come into play
// at the end.
//
start = buf;
do
{
// Handle the current digit.
//
int digit;
if (!bufsize)
return -1;
digit = n % 10;
if (digit < 0)
digit *= -1;
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
//
if (!bufsize)
return -1;
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first.
// Now reverse the string.
//
--buf;
while (start < buf)
{
char a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
Unfortunately none of the answers above can really work out in a clean way in a situation where you need to concoct a string of alphanumeric characters.There are really weird cases I've seen, especially in interviews and at work.
The only bad part of the code is that you need to know the bounds of the integer so you can allocate "string" properly.
In spite of C being hailed predictable, it can have weird behaviour in a large system if you get lost in the coding.
The solution below returns a string of the integer representation with a null terminating character. This does not rely on any outer functions and works on negative integers as well!!
#include <stdio.h>
#include <stdlib.h>
void IntegertoString(char * string, int number) {
if(number == 0) { string[0] = '0'; return; };
int divide = 0;
int modResult;
int length = 0;
int isNegative = 0;
int copyOfNumber;
int offset = 0;
copyOfNumber = number;
if( number < 0 ) {
isNegative = 1;
number = 0 - number;
length++;
}
while(copyOfNumber != 0)
{
length++;
copyOfNumber /= 10;
}
for(divide = 0; divide < length; divide++) {
modResult = number % 10;
number = number / 10;
string[length - (divide + 1)] = modResult + '0';
}
if(isNegative) {
string[0] = '-';
}
string[length] = '\0';
}
int main(void) {
char string[10];
int number = -131230;
IntegertoString(string, number);
printf("%s\n", string);
return 0;
}
You can use itoa where available. If it is not available on your platform, the following implementation may be of interest:
https://web.archive.org/web/20130722203238/https://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/atoi_8c-source.html
Usage:
char *numberAsString = itoa(integerValue);
UPDATE
Based on the R..'s comments, it may be worth modifying an existing itoa implementation to accept a result buffer from the caller, rather than having itoa allocate and return a buffer.
Such an implementation should accept both a buffer and the length of the buffer, taking care not to write past the end of the caller-provided buffer.
int i = 24344; /*integer*/
char *str = itoa(i);
/*allocates required memory and
then converts integer to string and the address of first byte of memory is returned to str pointer.*/

How do I check the first two characters of my char array in C?

This is code to create a similar C library function atoi() without the use of any C runtime library routines.
I'm currently stuck on how to check for the first two digits of the char array s to see whether the input begins with "0x".
If it starts with 0x, this means that I can then convert it in to hexadecimal.
#include <stdio.h>
int checkforint(char x){
if (x>='0' && x<='9'){
return 1;
}
else{
return 0;
}
}
unsigned char converthex(char x){
//lets convert the character to lowercase, in the event its in uppercase
x = tolower(x);
if (x >= '0' && x<= '9') {
return ( x -'0');
}
if (x>='a' && x<='f'){
return (x - 'a' +10);
}
return 16;
}
int checkforhex(const char *a, const char *b){
if(a = '0' && b = 'x'){
return 1;
}else{
return 0;
}
}
//int checkforint
/* We read an ASCII character s and return the integer it represents*/
int atoi_ex(const char*s, int ishex)
{
int result = 0; //this is the result
int sign = 1; //this variable is to help us deal with negative numbers
//we initialise the sign as 1, as we will assume the input is positive, and change the sign accordingly if not
int i = 0; //iterative variable for the loop
int j = 2;
//we check if the input is a negative number
if (s[0] == '-') { //if the first digit is a negative symbol
sign = -1; //we set the sign as negative
i++; //also increment i, so that we can skip past the sign when we start the for loop
}
//now we can check whether the first characters start with 0x
if (ishex==1){
for (j=2; s[j]!='\0'; ++j)
result = result + converthex(s[j]);
return sign*result;
}
//iterate through all the characters
//we start from the first character of the input and then iterate through the whole input string
//for every iteration, we update the result accordingly
for (; s[i]!='\0'; ++i){
//this checks whether the current character is an integer or not
//if it is not an integer, we skip past it and go to the top of the loop and move to the next character
if (checkforint(s[i]) == 0){
continue;
} else {
result = result * 10 + s[i] -'0';
}
//result = s[i];
}
return sign * result;
}
int main(int argc)
{
int isithex;
char s[] = "-1";
char a = s[1];
char b = s[2];
isithex=checkforhex(a,b);
int val = atoi_ex(s,isithex);
printf("%d\n", val);
return 0;
}
There are several errors in your code. First, in C you start counting from zero. So in main(), you should write:
char a = s[0];
char b = s[1];
isithex = checkforhex(a, b);
Then, in checkforhex(), you should use == (two equal signs) to do comparisons, not =. So:
if (a == '0' && b == 'x')
However, as pointed out by kaylum, why not write the function to pass a pointer to the string instead of two characters? Like so:
int checkforhex(const char *str) {
if (str[0] == '0' && str[1] == 'x') {
...
}
}
And in main() call it like so:
isithex = checkforhex(s);

Converting a string to Upper case letters and zeros in C

I am trying to create a function that accepts a string and converts all lowercase letters to uppercase and everything else into zeros then prints the string. Here is what I have:
void upperAndZeros(char* toUpper) {
char *toReturn[(sizeof(toUpper) / sizeof(*toUpper)) + 1];
int i;
for (i = 0; toUpper[i] != '\0'; i++) {
if (toUpper[i] >= 'a' && toUpper[i] <= 'z') {
toReturn[i] = (char) toupper(toUpper[i]); //this is line 127 in the code
} else {
toReturn[i] = (char) 0;
}
}
toReturn[i] = '\0';
printf("The modified string is '%s'", toReturn);
}
But when I go to compile this I get the following error:
127:25 warning: assignment makes pointer from integer without a cast
The error you are getting is because you are trying to char in a char * array here
toReturn[i] = (char) toupper(toUpper[i]);
You want an array of char not char *. Change this line
char *toReturn[(sizeof(toUpper) / sizeof(*toUpper)) + 1];
to
char toReturn[(sizeof(toUpper) / sizeof(*toUpper)) + 1];
Another change that you should do, which was suggested in the comment is, sizeof() won't work here, as an array decays into a pointer when passed onto a function. sizeof(toUpper) would return the size of a pointer. Read this to understand the problem.
Use strlen() here, if the string pointed by toUpper is NUL terminated.
If not then send the length separately to the function as another parameter.
Lots of problems, something like this should work better:
void upperAndZeros(char* toUpper) {
char toReturn[strlen(toUpper) + 1];
int i;
for (i = 0; toUpper[i] != '\0'; i++) {
if (islower(toUpper[i])) {
toReturn[i] = (char) toupper(toUpper[i]);
} else {
toReturn[i] = '0'; // beware not 0 but char '0'
}
}
toReturn[i] = '\0';
printf("The modified string is '%s'", toReturn);
}

How To Replace A Certain Character in C

I am writing a program that replaces characters in the user's input in C but I don't know how to replace the certain characters. Is there a certain method for C that replaces characters in a string? If you know python, then I want something a bit like this in python:
string.replace('certain_character','replacement_character')
Something like that, except for C, and not python.
This is my code that I have written so far:
#include <stdio.h>
int main(){
char str[BUFSIZ];
printf("Welcome To My Secret Language encoder!Enter some text: \n");
scanf("%s",str);
/*
Where I want to replace certain characters
*/
printf("Here is your text in secret language mode: %s \n",str);
}
I'm writing this code to learn C more, and that's why i'm not doing it in a higher level language like python.So, how do you replace certain characters in a string?
Nothing like that in C. You'll have to scan the string yourself:
#include <string.h>
char str[] = "I love cats";
int i;
for(i = 0; i < strlen(str); i++)
{
if(str[i] == 'c')
str[i] = 'b';
}
Now, if you're looking for a substring, you'll need something like strstr.
strchr finds the given character in a string, or returns NULL.
int main() {
int c;
while ( ( c = getchar() ) != EOF ) {
char const * found, * source = "abc", * dest = "xyz";
if ( ( found = strchr( "abc", c ) ) != NULL ) {
putchar( dest[ found - source ] );
} else {
putchar( c );
}
}
return 0;
}
If you have a lot of characters that you want to replace with other characters (like a Caesar cypher) you can build a lookup for yourself as follows:
#include <string.h>
char plain[] = "Hello there good people";
char encoder[26] = "ghijklmnopqrstuvwxyzabcdef";
char secret[100]; // long enough
int n = strlen(plain);
for(ii = 0; ii < n; ++ii) {
secret[ii] = encoder[(tolower(plain[ii]) - 'a')%26];
}
secret[n] = '\0';
This uses a couple of tricks:
cast all characters to lower case
subtract 'a' from the lowercase number - since a char is really just a number, we now have a == 0
Perform a modulo operation on the result so things that fall outside of the range of good characters don't cause a memory access error.
Add a '\0' at the end to make sure the string is properly terminated.
Copying things into a new string; obviously you could do an in-place replacement.
As written this will turn numbers (digits) and punctuation / symbols / spaces into characters. You could decide that anything that is not a letter is maintained - and maybe that only lower case letters are converted. In that case
#include <string.h>
char plain[] = "Hello there good people";
char encoder[26] = "ghijklmnopqrstuvwxyzabcdef";
char secret[100]; // long enough
int n = strlen(plain);
for(ii = 0; ii < n; ++ii) {
if(plain[ii] >= 'a' && plain[ii] <= 'z') {
secret[ii] = encoder[plain[ii] - 'a'];
}
else {
secret[ii] = plain[ii];
}
}
secret[n] = '\0';
there is no such function, you have to write one using strstr.
if you can use std::string, you can use string.replace()
Say you want to replace: A with z and b with X
char *replace(char *src, int replaceme, int newchar)
{
int len=strlen(src);
char *p;
for(p=src; *p ; p++)
{
if(*p==replaceme)
*p=newchar;
}
return src;
}
usage:
replace(string, 'A', 'z');
replace(string, 'b', 'X');
This is just the logic to do it, you need more statements in your code.

Resources