I don't understand atoi function in K&R C book? - c

#include <stdio.h>
#include <string.h>
int main(void)
{
char s[]= "9";
printf("atoi = %d",atoi(s));
system("pause");
return 0;
}
int atoi(char s[])
{
int i=0,n=0;
for(i;s[i]>='0' && s[i]<='9';i++)
n=10*n + (s[i]-'0');
return n;
}
In above program it gave me result 9 as per program it should print ascii value for 9
and I don't understand what this for loop does.
for(i;s[i]>='0' && s[i]<='9';i++)
n = 10*n + (s[i]-'0');

Lets break this down:
for (i;
This creates a for loop, with the loop variable i. This is not necessary, but more of a coding style.
s[i] >= '0' && s[i] <= '9'
This checks to make sure that the character at that index is inside the range for a decimal character (0 - 9), and if it is not, it exits the loop, then returns the number.
i++
After the loop runs, this increases the index you are checking in the string by one.
n = 10 * n
This adds an extra digit to 'n' by multiplying by 10, because you know that if you have one more character in your number, it must be multiplied by ten (say I start parsing 100, I read the first two strings, and have 10, there is one more character, so I multiply by ten to get 100.
+ (s[i]-'0');
This adds the next digit to 'n', the result, which is determined by subtracting the character at the current index by '0', which, when in the range of 0 - 9, returns the integer for that number (if this confuses you, take a look at an ASCII Chart.
Hopefully this helped you understand.

this converts string representation to number like "329" to 329
It takes 3 first then 3*10+2=32
then 32*10 + 9 =329

for(i;s[i]>='0' && s[i]<='9';i++) /* loop over just the digits, in L->R order */
n = 10*n + (s[i]-'0'); /* Take value so far, "shift" a 10's place left,
and add in value of latest digit
(diff between ASCII of digit & ASCII of zero) */

Related

How to store 100 digit number in C using strings

My problem is that i dont know what this functions do, thats program
from my teacher(not whole program just functions). Just wanna ask you what this functions do, mainly why
i store my number from right to left at string? thanks
#include<stdio.h>
#include<string.h>
#define MAX 1000
void str_to_num(char *str, char *number, int *dlzka)
{
int i;
for(i=0; i < MAX; i++)
number[i] = 0;
*dlzka = strlen(str);
for(i = 0; i < *dlzka; i++)
cis[(*dlzka) - 1 - i] = str[i] - '0';
}
void plus(char *cislo, int *d1, char *cis2, int d2)
{
int i; prenos = 0;
if(*d1 < d2)
*d1 = d2;
for(i = 0; i < *d1; i++)
{
pom = number[i] + number[i];
pom += prenos;
number[i] = pom % 10;
prenos = pom / 10;
}
}
Here is the lesson your teacher should be teaching:
There is a difference between the numerical value of 1, and the computer code (ASCII for example) that is used to represent character 1 displayed on the screen or typed on the keyboard.
Every time you see 1 on the screen, your computer sees 49 in memory.
0 is 48, 2 is 50 and so on.
Conveniently, all digit characters are arranged in a sequence from 0 to 9, so to convert their character codes to their numeric values all you have to do is subtract the character code of zero to get the digit position in the sequence.
For example: 49 - 48 = 1 --> '1' - '0' = 1
And this is how the first function, str_to_num works.
C language does not provide a variable large enough to work with 100 digit numbers, so you need to sum them up one digit at a time.
The second function has completely wrong variable names, but it is still pretty obvious what it is trying to do:
It sums up two single digit numbers, then stores the ones part of the result in an array and the tenth (if sum is > 9) in a helper variable.
As already suggested in the comments, this is how you sum up numbers manually on a page one digit at a time.
I don't know what prenos means in your language, but in English this variable should be called carry and it keeps the overflowing tens digit for the next round.
There is however something missing from the sum function: if the sum of the last (leftmost) two digits is more than 9, the extra 1 will be lost, and the result will be wrong.
Check the original code your teacher gave you - either you copied it wrong, or he is giving a bad example.

K&R Code for getting an int

I'm having trouble understanding the code for getting an int in K&R.
Specifically the last line of this function:
void getint( int *pn )
{
int c;
while (isspace(c = getch()))
;
for (*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + (c - '0') ;
}
Here is what's going on here:
Since pn is a pointer to the result passed by pointer, assigning or reading *pn means accessing the result that we have so far. Any change that you make inside this function will be accessible in the context of the caller, who passed you a pointer to int.
Since codes of decimal digits are next to each other, c-'0' means a numeric value of the character code representing a digit. For example, if c is '5' (in single quotes), then c-'0' is equal to 5 (no quotes).
Now the rest of the algorithm becomes clear: attaching a digit to the right of a number means taking the prior value of the number, multiplying it by ten, and adding the value of the digit to the result.
For example, if you are reading "12345" and you have read "123", then *pn is 123, and the next digit is 4. You multiply 123 by 10 to get 1230, and add 4 to it. Now you have 1234, and the next digit is 5. You multiply by ten again to get 12340, and add 5 to get your final result of 12345.
I am pretty sure this is code for inputting an integer faster by reading digits char by char.So this would be something like
void input_int(int *pn)
{
for ( *pn = 0; isdigit(c); c =getch())
*pn = 10 * *pn + ( c - '0') ;
}
and used as
int a;
input_int(&a);
What is happening is that we read the digits char by char and simultaneously create an integer.

Manipulating array of chars

I'm writing a code in C programming language that receives a string (of chars) as input and each letter advances 3 in the alphabet. E.g. If user types "abc", the program should return "def". The problem is that if the user types 'z' (e.g.), the program returns some char, instead of my goal (which would be this case the letter 'c'). My current algorithm includes this if statement:
if ((text[i]>='a' && text[i]<='w')||(text[i]>='A' && text[i]<='W'))
text[i] = (text[i]) + 3;
But this forces me to write all this lines:
else if (text[i]=='x') text[i]='a';
else if (text[i]=='X') text[i]='A';
else if (text[i]=='y') text[i]='b';
else if (text[i]=='Y') text[i]='B';
else if (text[i]=='z') text[i]='c';
else if (text[i]=='Z') text[i]='C';
How can I optimize my code?
Your problem can be addressed with simple arithmetic logic. The range of char ranges from 0 - 255. Each value corresponds to a separate character. The letters 'A-Z' and 'a-z' range from 65 - 90 and 97 - 122 respectively. So for your problem there are two ranges. You can check with the standard library function that your character falls in upper case or lower case range. then you can set the base for your range. Next you will find the offset of your character from base, add 3 in it. the new value can be made circular using % operator. each range has maximum of 26 characters so you can make your range circular by taking a mod from 26. Now add the resulting value (offset) to the base to get the desired character.
#include <ctype.h>
...
...
...
char c = text[i];
char base = isupper(c)? 'A' : 'a';
text[i] = base + (((c - base) + 3) % 26); // New Desired Character

What is the output of the following code and how?

I can't understand the logic of the for loop in the function fun:
long fun(char* s)
{
long r=0;
for(;*s; r=(r<<1)|(*s++ - '0'));//explain this
return r;
}
int main()
{
printf("%d ",fun("000001010"));
}
for(;*s; r=(r<<1)|(*s++ - '0'));//explain this
is:
int r=0;
while(*s){
int m=*s-'0';
r=r*2 + m;
++s;
}
As commented above It will parse(convert) your binary string to number
It is more or less equivalent to this:
long r = 0;
for(size_t i=0; i<strlen(s); i++) // Traverse the string
{
r = r<<1; // Shift the long representation
if( s[i] != '0' ) // Is current char 0 or 1
{
r = r | 1; // It is 1: append it to long representation
}
}
The structure of a for loop is the following:
Before the first semi-colon you define and/or initialize any values related to the loop
between the two semi-colons lies the logic that is checked at the start of each loop, if it is true the loop goes on
The code after the second semi-colon executes after the loop body is finished
So in your for loop there is nothing before the first semi-colon, nothing needs to be initialized, that's normal.
The *s will be true (different than 0) for as long as the ASCII value stored there is different than '0', that it the string termination character. So it's the same as saying strlen(s)!=0
r=(r<<1) performs a bitwise operation on r.
*s++ - '0' subtracts the character '0' from the character pointed to by s and then increments the pointer to point to the next character
This for loop will run number of times, the characters inputed in fun() function parameters, e.g. here 9.
The value of r will be decided by the bitwise operation (r<<1), subtraction (*s++ - '0') and the orring operation | of these two previous operations.
for first five iterations, value of the r will be 0, as leftshift operation on 0 will yeild 0 and ASCII value subtraction of the characters will also come as 0.
for 6th iteration, subtraction will bear value 1, and subsequently r will have 1.
for 7th iteration, leftshift operation (multiplication by 2) will have output 2, so r=2.
for 8th, leftshift operation will have output 4 and subtraction 1, so orring of (1 | 4) will have 5.
and for last iteration, leftshift operation will yeild o/p 10.
So finally You should get 10 as o/p.

I don't understand itoa() in K&R book

I am reading K&R; so far I'm doing well with it, but there is something in function itoa() which I don't understand. Here in itoa() they say they reverse the numbers themselves. For example 10 is 01 (they reverse the string):
void itoa(int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
return;
}
I don't understand how it reversed the number. Even though we are just doing n % 10 + '0' then its the following digit which 10 then 1 gets deleted then it goes to 0 right ? Or I don't get its logic ?
In the do-while loop, it is pulling the numbers off from behind (the least significant digit first). So, if you had the number -123456789, it processes the 9, then the 8, then the 7, etc.
So, when it hits the null-terminator (3rd to last line), you would have "987654321-", which is then reversed.
n % 10 gives 0 for n = 10, so after the loop, the string s contains 01.
The call to reverse() fixes this.
The algorithm determines the digits from least to most significant order. Because the total number of digits that will be generated is not known in advance, the correct position cannot be determined as they are generated - the least significant digit will be at the end, but the 'end' is not known. So they are buffered in the order they are calculated (reverse) and then the whole string is reversed to correct the ordering.
One way of avoiding this is to determine the length in advance:
decimal_digits = (int)log10( n ) + 1 ;
but on devices without an FPU (and some with very simple FPUs) that is likely to be a heavier task than string reversal.

Resources