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.
Related
I've got an assignment where I have to sum whole numbers up to 100 digits.
They gave me this struct to represent big numbers (I think there are better ways to represent this, but I'm not allowed to modify it):
typedef struct {
char* string;
int lengthError;
} BigNumber;
Where string is the number itself and lengthError is the length of the number or an error that is a previously defined enum.
I've also have the implementation of the sum function
BigNumber *sum(BigNumber* num1, BigNumber* num2) {
BigNumber* result = malloc(sizeof(BigNumber));
int limit = getLength(num1->lengthError, num2->lengthError);
result->string = malloc(limit);
int digitResult;
int index = limit -1;
int carry = 0;
while(index != -1) {
int d1 = ((int)num1->string[index]) - ((int)'0');
int d2 = ((int)num2->string[index]) - ((int)'0');
digitResult = d1 + d2 + carry;
if (digitResult > 9) {
digitResult = digitResult - 10;
carry = 1;
} else {
carry = 0;
}
itoa(digitResult, &result->string[index], 10); //I think this is the problem
index--;
}
result->string[limit] = '\0';
printf("result: %s\n", result->string);
return result;
}
I haven't finished writing that function, I know there are a lot of flaws in it, but the problem is that I can't get to sum 12 + 12. The result I get is 2.
I thought approaching this problem by picking the lasts character of both numbers, transform them into an int and sum them having in mind the carry digit. After I got the result in digitResult I try to convert it to a char and store it in the corresponding position of the result->string pointer
Once it has finished the operation, I add an \0 at the last position of the result->string.
So the question is, how do I make this operation to work as desired? Debugging the code, I noticed that the first time it stores the first result in result->string, following the example above this would be a number 4, it stores trash in that position instead. In the second addition, I store a number 2 correctly and that's the final result I get in when I print the result.
Your use of the itoa function is a problem (though, as you have also suggested, maybe not the only one).
The itoa function converts its first argument into a null-terminated string - so, as well as writing the character representation of digitResult at the indicated place in the string, it also adds a '\0' character after it. Thus, your string will always be terminated immediately after the last digit you write, and 12 + 12, giving 24 will appear to be just the first character: 2.
What you can do instead is to convert the digit yourself (reversing the operation you used to get the d1 and d2 values), then just directly set the string element to the converted digit.
So, instead of:
itoa(digitResult, &result->string[index], 10);
use:
result->string[index] = (char)(digitResult + '0');
This question already has answers here:
What does void* mean and how to use it?
(10 answers)
Closed 5 years ago.
I'm trying to make a calculator that takes a void pointer called yourVal, look at the first byte and decide if it's a '*' or '/'. Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23). I'm a novice with pointers in C, and I really have no idea how to even set a value to a void pointer. When I do the following in main
void *yourVal;
*yourVal = "*1234567";
printf("%s\n", yourVal);
I'm not able to dereference a void pointer. But I tried with a char pointer, and I have the same issue.
This is my code for the calculator function. Based on whether I use printf or not, I get different results.
int calculator(void *yourVal){
char *byteOne;
short int *byteThree, *byteFive, *byteSeven;
int value;
byteOne = (char *)yourVal;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
if(*byteOne == '*') {
value = *byteThree * *byteFive * *byteSeven;
printf("You multiplied\n");
}
else if(*byteOne == '/') {
if (*byteThree == 0) {
value = 0xBAD;
printf("Your input is invalid\n");
}
else {
value = *byteFive / *byteThree;
printf("You divided\n");
}
}
else {
value = 0xBAD;
printf("Your input is invalid\n");
}
}
The division isn't working at all, and the multiplication only grabs one digit. Any tips would be appreciated. I looked at various sources but I'm not seeing how to work with void pointers efficiently. Also, I can't use any library functions other than printf, and this is a school assignment, so try not to give too many spoilers or do it for me. We were given one hint, which is to cast yourVal to a structure. But I'm lost on that. Thanks
byteOne = (char *)payload;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
This doesn't do what you think it does. If you want to read the numbers at these positions, you need to do something like.
char* Value = yourValue;
unsigned byteOne, byteThree, byteFive, byteSeven;
byteOne = Value[0] - '0';
byteThree = Value[2] - '0';
byteFive = Value[4] - '0';
byteSeven = Value[6] - '0';
What I have done here is read the byte at that position and subtract the ASCII value of '0' to get the numerical value of that character. But again this will work only for a single character.
If you need to read more characters you will have to use library functions like sscanf or atoi.
The void pointer adds no functionality you need to solve this problem, it just complicates things. Use a char pointer instead.
"*1234567" is a string, not an array of integers. You cannot treat it as an array of integers. Each character would have to be converted to an integer before you do arithmetic. The easiest way to do that is to subtract by the ASCII character '0'.
"...i multiply bytes 3+4..." When counting bytes, you always start at 0. In the string "*1234567", the 2 is the byte with index 2 not 3.
"Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23)"
I fail to see how this algorithm makes any sense. What is the 1 there for? Why aren't you using some conventional formatting such as prefix, postfix or just plainly typed-out equations?
Example:
int calculator (const char* yourVal)
...
int byte2 = yourVal[2] - '0';
Can any one explain what does the following code do? As per my knowledge this program converts the number to the given base but I can't understand how it is done?
#include<stdio.h>
char *fun(unsigned int num, int base);
int main()
{
char *s;
s=fun(128, 2);
s=fun(128, 16);
printf("%s\n",s);
return 0;
}
char *fun(unsigned int num, int base)
{
static char buff[33];
char *ptr = &buff[sizeof(buff)-1];
*ptr = '\0';
do
{
*--ptr = "0123456789abcdef"[num %base];
num /=base;
}while(num!=0);
return ptr;
}
What does this line *--ptr = "0123456789abcdef"[num %base]; in the above code means?
You can split *--ptr = "0123456789abcdef"[num %base]; into several separate statements so it becomes more clear:
*ptr= is the same as ptr[0]=, i.e. it stores some value at location 0 of the memory where ptr is poiinting to. (End of the buff during the first loop iteration)
--ptr decreases the value of ptr by 1 (after it is used). So it points to to the previous (second last) location of buff.
Combined, *--ptr = first sets the value of ptr[0] and then decreases the pointer.
Next, "0123456789abcdef" char(acter) array, so "0123456789abcdef"[...] gets a value from the array of chars at the specified index.
The used index num % base' calculates the remainder after dividingnumbybase`
So combined the complete line grabs a value from the char array (at index num % base), stores it at the location where ptr it pointing to and decreases ptr (i.e. the points the the previous memory location)
About the actual working of the application: What this is doing is checking the remainder of num (for the given base) and grabs the correct (char)-value from the string (i.e. gets the representing number). Next, it divides the number by its base, in order to be able to determine the next remainder, and so on.
This would result in the representation being reversed (reading to right to left), so the buffer is written from the back to the start (hence the --ptr part, instead of ++ptr).
I think your main confusion lies in the statement
"0123456789abcdef"[num %base];
Well, this can be rewritten as a combination of
char arr[] = "0123456789abcdef";
and
arr[num %base];
Other than that, *--ptr = can be broken down to
--ptr;
*ptr = <some value>;
As far as the program logic in considered, you're quite right and the digit is chosen by using the [num %base] position from the array holding the digits.
ptr is a pointer that holds memory address of a char variable.
--ptr simply decrements the pointer (now it'll point to the previous object of the same type). * is simply accessing the value.
"0123456789abcdef"[num %base]
will return the char at the position num % base.
Here *--ptr is decrement the one position in a array and pointing to one place.
So when you are using that "0123456789abcdef"[num %base]. answer of num % base is giving
one output. Take that is two. So it will return the character that is placed on the second place.
So based on the answer of num % base is storing the value in the given string.
My analysis is as follows after googling in net.
Firstly, "0123456789abcdef" is used to pick values if it is decimal values are picked from 0-9, if it is octal values are picked from 0 to 7, if it is hexa decimal values are picked from 0-f, if it is binary only between 0 and 1.
Simple "0123456789abcdef" can be treated as character array i.e. char a[] = "0123456789abcdef";
and "0123456789abcdef"[num % base] means a[num % base]. Each time the the number given is divided with base the character is picked up from the string.
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.
#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) */