Convert String to Integer without library function in C [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have to write a program that converts an user input (which is a string) to an Integer. In the same time it should check, if the user input really is a number.
And also everything in one method.
and NO LIBRARY FUNCTIONS allowed.
I can't figure any idea how to do it. All I got for the beginning is just this pathetic structure
#include <stdio.h>
void main()
{
char input[100];
int i;
int sum = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%c, &input");
for (i = 0; i < 100; i++)
{
}
}
I appreciate any help, thanks

The conversion is the easy part...
But if you must not use library functions,
there is only one way to take a string, and that is argv;
there is only one way to give an integer, and that is the exit code of the program.
So, without much ado:
int main( int argc, char * argv[] )
{
int rc = 0;
if ( argc == 2 ) // one, and only one parameter given
{
unsigned i = 0;
// C guarantees that '0'-'9' have consecutive values
while ( argv[1][i] >= '0' && argv[1][i] <= '9' )
{
rc *= 10;
rc += argv[1][i] - '0';
++i;
}
}
return rc;
}
I did not implement checking for '+' or '-', and did not come up with a way to signal "input is not a number". I also just stop parsing at the first non-digit. All this could probably be improved upon, but this should give you an idea of how to work around the "no library functions" restriction.
(Since this sounds like a homework, you should have to write some code of your own. I already gave you three big spoons of helping regarding argv, the '0'-'9', and the conversion itself.)
Call as:
<program name> <value>
(E.g. ./myprogram 28)
Check return code with (for Linux shell):
echo $?
On Windows it's something about echo %ERRORLEVEL% or somesuch... perhaps a helpful Windows user will drop a comment about this.
Source for the "'0'-'9' consecutive" claim: ISO/IEC 9899:1999 5.2.1 Character sets, paragraph 3:
In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.
I'm sure this is preserved in C11, but I only have the older C99 paper available.

Take hightes digit and add it to number, multiply the number by 10 and add the next digit. And so on:
#include <stdio.h> // scanf, printf
void main()
{
char input[100];
printf("Type a String which will be converted to an Integer: ");
scanf("%s", input);
int number = 0;
int neg = input[0] == '-';
int i = neg ? 1 : 0;
while ( input[i] >= '0' && input[i] <= '9' )
{
number *= 10; // multiply number by 10
number += input[i] - '0'; // convet ASCII '0'..'9' to digit 0..9 and add it to number
i ++; // step one digit forward
}
if ( neg )
number *= -1;
printf( "string %s -> number %d", input, number );
}
input[i] - '0' works, because ASCII characters '0'..'9' have ascending ASCII codes from 48 to 57.

So basically you want to know how something like the standard library atoi works. In order to do this, you need to consider how strings represent numbers.
Basically, a string (that represents a number) is a list o digits from 0 to 9. The string abcd (where a, b, c, d are placeholders for any digit) represents the number a*10 ^ 3 + b*10^2 + c * 10 + d (considering base 10 here, similar for other bases). So basically you need to decompose the string as shown above and perform the required arhitmetic operations:
// s - the string to convert
int result = 0;
for (int index = 0; index < strlen(s); index++) {
result = result * 10 + s[index] - '0';
}
The operation s[index] - '0' converts the character that represent a digit to its value.

// the function returns true for success , and false for failure
// the result is stored in result parameter
// nb: overflow not handled
int charToInt(char *buff,int *result){
*result=0;
char c;
while(c=*buff++){
if((c < '0') || (c >'9')) // accept only digits;
return 0;
*result *= 10;
*result += c-'0';
}
return 1;
}

Lot of things which are missed. Firstly taking a string in is done by scanf("%s",input); By the way in which you are receiving it, it only stores a character, secondly run the loop till the length of the string recieved. Check the below code.
#include <stdio.h>
#include<string.h>
void main()
{
char input[100];
int i;
int sum = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%s", input);
for (i = 0; i < strlen(input); i++)
{
if(input[i]>=48 && input[i]<=57)
{
//do something, it is a digit
printf("%d",input[i]-48);
//48 is ascii value of 0
}
}

Try it:
#include <stdio.h>
void main()
{
char input[100];
int i,j;
int val = 0;
printf("Type a String which will be converted to an Integer: ");
scanf("%s",input);
for(j=0; input[j] != '\0'; j++); // find string size
for (i = 0; i < j; i++)
{
val = val * 10 + input[i] - 48;
}
}

If you want your code to be portable to systems that don't use ASCII, you'll have to loop over your char array and compare each individual character in the source against each possible number character, like so:
int digit;
switch(arr[i]) {
case '0':
digit=0; break;
case '1':
digit=1; break;
// etc
default:
// error handling
}
Then, add the digit to your result variable (after multiplying it by 10).
If you can assume ASCII, you can replace the whole switch statement by this:
if(isdigit(arr[i])) {
digit=arr[i] - '0';
} else {
// error handling
}
This works because in the ASCII table, all digits are found in a single range, in ascending order. By subtracting the ordinal value of the zero character, you get the value of that digit. By adding the isdigit() macro, you additionally ensure that only digit characters are converted in this manner.

Related

Repetition code in C isn't working for large numbers

I'm writing a code in C to find the digits that repeat in a given number, and the one that I wrote works fine for small numbers, but the output gets messed up if I input a large value, N < 1000.
Here is my code; please help me out!
For the input:
1839138012980192380192381090981839
I get this output:
0 2 3 5 7 8
#include <stdio.h>
int main()
{
int digit, digits[10], flag = 0, i;
long long num;
scanf("%lld", &num);
while (num)
{
digit = num % 10;
if (digits[digit])
flag = 1;
digits[digit]++;
num /= 10;
}
if (flag)
{
for (i = 0; i < 10; i++)
{
if (digits[i] > 1)
printf("%d ", i);
}
printf("\n");
}
else
printf("The are no repeated digits.\n");
return 0;
}
The long long type can only represent a limited range of numbers. In your C implementation, 1839138012980192380192381090981839 is too big for long long, and scanf("%lld", &num) does not work.
Instead, read each character of input using c = getchar();, where c is declared as an int. If, after getchar, c is EOF, stop looping and print the results. If c is not EOF, then check whether it is a digit using if (isdigit((unsigned char) c)). The isdigit function is defined in <ctype.h>, so include that header.
If the character is a digit, then convert it from a character to the number it represents using c - '0'. You can use int d = c - '0'; to store the number in d. Then increment the count for the digit d.
If the character is not a digit, you can decide what to do:
There will likely be a new-line character, '\n', at the end of the line the user entered. You may want to ignore it. When you see the new-line, you could end the loop and print the results, you could continue reading to see if there are any other digits or characters before EOF is seen and report a problem to the user if there are, or you could ignore it and continue looping.
There could be spaces in the input. You might want to ignore them, or you might want to report a problem to the user.
If there are other characters, you might want to report a problem to the user.
Here's another approach, which you could use with a string of some maximum length (defined by the constant MAX_LEN).
A string made up of a bunch of char will use one byte per character, so you can define MAX_LEN up to how many bytes you have in system memory, generally, although in practice you probably would use a much smaller and more reasonable number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 12345
int main()
{
int digit, digits_checker[10] = {0}, flag = 0, i;
char* num;
/* set aside space for the string and its terminator */
num = malloc(MAX_LEN + 1);
/* read num from input */
scanf("%s", num);
/* get the string length */
size_t num_length = strlen(num);
/* walk over every character in num */
for (size_t position = 0; position < num_length; position++)
{
/*
We assume that the value of num[position] is an
ASCII character, from '0' to '9'. (If you can't make
that assumption, check the input and quit with an
error, if a non-digit character is found.)
If the input is valid, the digits 0-9 in the ASCII
table start at 48 ('0') and end at 57 ('9'). Subtracting
48, therefore, gives you the integer value at each digit
in num.
*/
digit = num[position] - 48;
/*
Increment a counter for each digit
*/
digits_checker[digit]++;
}
/* num is no longer needed, so we free its memory */
free(num);
/* check each digit */
for (i = 0; i < 10; i++)
{
if (digits_checker[i] > 1) {
printf("%d ", i);
flag = 1;
}
}
if (!flag) {
printf("The are no repeated digits.\n");
}
else {
printf("\n");
}
return 0;
}
The suggestion to check input is a good one. You can't necessarily assume that what someone enters will be entirely made up of digit characters.
But hopefully this demonstrates how to set aside space for a string, and how to read through it, one character at a time.

how to fix this code so that it can test the integers present next to the character?

Given a string containing alphanumeric characters, calculate the sum of all numbers present in the string.
The problem with my code is that it displays the integers present before the characters, but it is not summing up the integers after the characters.
The execution is easy in python and C++ but I cant get it done using C! Can anyone please verify where I have done wrong? << thank you !
enter code here
#include<stdio.h>
#include<string.h>
int convert(char[]);
int main()
{
char ch[100],temp[100]={0};
int i=0,s=0,j=0,n;
scanf("%s",ch);
for(i=0;i<strlen(ch);i++)
{
if((ch[i]>='0') && (ch[i]<='9'))
{
temp[j]=ch[i];
j++;
}
else
{
if(temp[0]== '\0')
{
continue;
}
else
{
n=convert(temp);
s+=n;
temp[0]= '\0';
j=0;
}
}
}
printf("%d",s);
return 0;
}
int convert(char s[]) //converting string to integer
{
int n=0;
for(int i=0;i<strlen(s);i++)
{
n= n * 10 + s[i] - '0';
}
return n;
}
Input : 12abcd4
Expected output : 16
But the output is 12 for my code.
There are two problems in your code. The first was mentioned in the comments : if the last character is a digit, the last "number section" will not be taken into account. But I don't think that the solution given in the comments is good because if the last character is not a digit, you will have a wrong value. To correct this, I added an if statement that check if the last character is a digit, if so call convert().
The second problem is that strlen return the number of characters in you string from the beginning until it finds an '\0'. The way you used your string lead to the follow problem :
ch = "12abcd4".
At first you have temp = '1' + '2' + '\0'...
After calling convert() you set temp[0] to '\0', thus temp = '\0' + '2' + '\0'... .
And when you start reading digit again, you set '4' in temp[0]. Your string is now : '4' + '2' + '\0'... .
The n returned will be 42 and your result 54 (12+42). There are several solution to have the expected behavior, I chose to use your variable j to indicate how many characters should be read instead of using strlen() :
#include<stdio.h>
#include<string.h>
int convert(char[], int size);
int main() {
char ch[100],temp[100]={0};
int i=0,s=0,j=0,n;
scanf("%s",ch);
for(i=0;i<strlen(ch);i++) {
if((ch[i]>='0') && (ch[i]<='9')) {
temp[j]=ch[i];
j++;
// change here
if(i == strlen(ch) - 1) {
n=convert(temp, j);
s+=n;
}
}
else {
// change here
n=convert(temp, j);
s+=n;
if(temp[0]== '\0') {
continue;
}
temp[0]= '\0';
j=0;
}
}
printf("%d\n",s);
return 0;
}
//change here
int convert(char s[], int size) {
int n=0;
for(int i=0;i<size;i++) {
n= n * 10 + s[i] - '0';
}
return n;
}
You could use a combination of strtoul() and strpbrk() to do this.
Declare two character pointers start_ptr and end_ptr and make start_ptr point to the beginning of the string under consideration.
char *start_ptr=s, *end_ptr;
where s is the character array of size 100 holding the string.
Since your string has only alphanumeric characters, there is no - sign and hence there are no negative numbers. So we can get away with using unsigned integers.
We are using strtoul() from stdlib.h to perform the string to integer conversion. So let's declare two variables: rv for holding the value returned by strtoul() and sum to hold the sum of numbers.
unsigned long rv, sum_val=0;
Now use a loop:
for(; start_ptr!=NULL; )
{
rv = strtoul(start_ptr, &end_ptr, 10);
if(rv==ULONG_MAX && errno==ERANGE)
{
//out of range!
printf("\nOut of range.");
break;
}
else
{
printf("\n%lu", rv);
sum_val += rv;
start_ptr=strpbrk(end_ptr, "0123456789");
}
}
strtoul() will convert as much part of the string as possible and then make end_ptr point to the first character of the part of the string that could not be converted.
It will return ULONG_MAX if the number is too big and errno would be set to ERANGE.
Otherwise the converted number is returned.
strpbrk() would search for a set of characters (in this case the characters 0-9) and return a pointer to the first match. Otherwise NULL is returned.
Don't forget to include the following header files:
stdlib.h ---> strtoul
string.h ---> strpbrk
limits.h ---> ULONG_MAX
errno.h ---> errno
In short, we could make the program to something like
for(; start_ptr!=NULL; sum_val += rv, start_ptr=strpbrk(end_ptr, "0123456789"))
{
rv = strtoul(start_ptr, &end_ptr, 10);
if(rv==ULONG_MAX && errno==ERANGE)
{
//out of range!
break;
}
}
printf("\n\n%lu", sum_val);
So the value of sum_val for the string "12abcd4" would be 16.
scanf() is usually not the best way to accept input that is not well-formatted. Maybe you can use fgets()-sscanf() combo instead.
If you must use scanf(), make sure that you check the value returned by it, which in your case must be 1 (the number of successful assignments that scanf() made).
And to prevent overflow, use a width specifier as in
scanf("%99s",ch);
instead of
scanf("%s",ch);
as 100 is the size of the ch character array and we need one extra byte to store the string delimiter (the \0 character).

Confusing Character String Interaction

I'm currently doing the CS50 course, and I'm stuck on the credit problem. The idea is to make a program to verify cards due to their inbuilt checksum. The first step is to take every second digit and multiply it by 2, then add all the digits of the products together.
My code isn't finished, but I've set it up to print some intermediary steps just so I can see what's going on.
#include <stdio.h>
#include <string.h>
void checksum (char number[20]);
int main (void){
char *card;
printf("Please enter a card number:");
scanf("%s", card);
if (strlen(card) == 13 || strlen(card) == 16 || strlen(card) == 15) {
checksum(card);
}
else{
printf("Not a number. Please try again.\n");
main();
}
}
void checksum (char *number) {
int check = 0;
int digits = 0;
for(int i = 1; i < 17; i += 2){
printf("No%c\n", number[i]);
digits = (number[i] * 2);
printf("D%i\n", digits);
while (digits > 0) {
check += digits % 10;
printf("C%i\n", check);
digits = digits / 10;
}
}
}
I know the first part is far from perfect but it's the checksum function I'm concerned with at the moment. When it takes the second digit(5) everything is fine. But then when it's multiplied by 2 according to the next line, somehow the result is 106(?)
Can someone explain what's going on here?
terminal output
You read in a string, i.e. a sequence of characters, probably in ASCII format. So your input "1500150015001500" is actually a sequence of characters terminated by string terminating character 0x0, e.g. like { '1', '5', '0', .... '\0' }. A single character value like '1', when interpreted as an integral value, is represented by its ASCII code, which is 48 for '0', 49 for '1', ... , and 53 for '5'. Hence, an expression like char c = '5'; int digit = c*2 actually yields 106 for digit. To take character '5' as integral value 5, you could write int digit = (c - '0'), which is the same as if you wrote (53 - 48).
Without modifying your code to much, test what happens:
#include <stdio.h>
#include <string.h>
void checksum (char *number);
int main (void){
char card[30];
printf("Please enter a card number:");
scanf("%s", card);
if (strlen(card) == 13 || strlen(card) == 16 || strlen(card) == 15) {
checksum(card);
}
else{
printf("Not a number. Please try again.\n");
main();
}
}
void checksum (char *number) {
int check = 0;
int digits = 0;
for(int i = 1; i < strlen(number); i += 2){
printf("No%c\n", number[i]);
digits = ((number[i]-'0') * 2);
printf("D%i\n", digits);
while (digits > 0) {
check += digits % 10;
printf("C%i\n", check);
digits = digits / 10;
}
}
}
A couple of things:
char *card; scanf("%s", card); is not going to work. You need to either declare card as an array of fixed size (i.e. char card[20]), or use malloc to allocate memory for the pointer char *card;. If you choose the latter option you also need to use free on the memory when you're done with it.
In your function checksum, you need to convert the characters you read in the string card into numbers. If the character set on your system is ASCII, you can achieve this by subtracting the value 0x30 (i.e. the numeric value of the character '0') from each character in the string before performing arithmetic on it.
char number[20] in a function signature is pointless; see this question for more information. Since the array decays to a pointer to its first element when passed as a function argument, you may as well have char *number in the function signature.

Print every number with 0 in their digits (Only natural) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
The program requires a user to insert a number. Let's say we put 149. Now the program prints every number that has 0 digits in them till the number 149 (Including the number). So it's going to be 10,20,30,40,50,60,70,80,90,100,101...110..140 [Let's say the limit would be till 10000]
I have been trying to do this, but i only added +10 to every one, but that cannot be done >100 where it is 101,102..
Use the function sprintf to convert an integer to a string and then search for the character '0' in the string. If found, then print the number. Here's a simple working program implementing this idea.
#include <stdio.h>
#include <string.h>
#define MAXLEN 50 // max number of digits in the input number
int main(void) {
char buf[MAXLEN + 1]; // +1 for the null byte appended by sprintf
char ch = '0'; // char to be searched for in buf
int i, x;
if(scanf("%d", &x) != 1) {
printf("Error in reading input.\n");
return -1;
}
for(i = 1; i <= x; i++) {
sprintf(buf, "%d", i); // write i to the string buffer and append '\0'
if(strchr(buf, ch)) // strchr returns a pointer to ch if found else NULL
printf("%d\n", i);
}
return 0;
}
You can also extract each digit of an integer in the given range and check it for zero. Here's a naive implementation.
#include <stdio.h>
int main(void) {
int i, x;
int r;
if(scanf("%d", &x) != 1) {
printf("Error in reading input.\n");
return -1;
}
for(i = 1; i <= x; i++) {
for(r = i; r > 0; r /= 10) {
if(r%10 == 0) {
printf("%d\n", i);
break;
}
}
}
return 0;
}
The simple approach would be to iterate through all natural numbers up to the target number and testing each of them to see if they have any zero digits. Note that the last digit of a non-negative integer i can be obtained as the remainder from division by the base (i % 10 here). Also remember that integer division in C truncates decimals, e.g., (12 / 10) == 1
As a start, consider to convert each number to char [] and then check whether it contains a '0' or not.
To read on:
How to check if a int var contains a specific number
Count the number of Ks between 0 and N
I think this would be the answer.
int j;
for(int i=1;i<150;i++){
j=i;
while(j>0)
{
if(j%10==0)
{
printf("%d\n",i);
break;
}
else
j=j/10;
}
}

Get char at a defined location in a string in C

I'm looking to read in a number from the keyboard and then I have to manipulate each digit individually (it's an Octal to Decimal converter).
Is there something similar to the charAt() method from Java that can be used to work with s particular digit?
I currently have the below code (incomplete) but when compiling, it returns "error: subscripted value is neither array nor pointer"
#include <stdio.h>
#include <math.h>
#include <string.h>
int main()
{
printf("Please enter an octal number ending with #");
char nextNum = getchar();
char number;
int counterUp = 0; //Records how many digits are entered
int counterDown = 1; //Records progress during conversion
int decimalNumber = 0;
while(nextNum != '#') //reads in the whole number, putting the characters together to form one Octal number.
{
number = (number + nextNum);
counterUp++;
nextNum = getchar();
}
//Begin converson from Octal to Decimal
while(counterUp >= 0)
{
int added = (number[counterUp] * (pow(8, counterDown)));
decimalNumber = (decimalNumber + added);
counterDown++;
}
}
I'm not looking to be told how to go from octal to decimal, just how to work with one digit at a time.
Use fgets() instead of a single char:
char number[25]; // max of 25 characters in string
fgets(number, 24, stdin); // read a line from 'stdin', with a max of 24 characters
number[24] = '\0'; // append the NUL character, so that we don't run into problems if we decide to print the string
Now you can subscript number at will, e.g. number[10] = 'A'.
I think you're used to Java way where you can write something like:
String number = "";
number += "3";
number += "4";
Strings in C do not work like that. This code doesn't do what you think it does:
char number = 0; // 'number' is just a one-byte number
number += '3'; // number now equals 51 (ASCII 3)
number += '4'; // number now equals 103 (meaningless)
Maybe something like this will work for you:
char number[20];
int i = 0;
number[i++] = '3';
number[i++] = '4';
Or, you could simply use scanf to read a number in from the keyboard.
I recommend that you find a good book about C and read about strings first, then scanf second.
I think you need to step back and look at your algorithm more closely.
What does char number store? What do you expect this loop to do:
while(nextNum != '#') //reads in the whole number, putting the characters together to form one Octal number.
{
number = (number + nextNum);
counterUp++;
nextNum = getchar();
}
In particular, what does number = (number + nextNum); mean?
You need to define number as an array of chars.
e.g.
char number[16];
Then change your reading loop to append to the array.
while(nextNum != '#')
{
number[counterUp] = nextNum;
counterUp++;
nextNum = getchar();
}

Resources