What is the output of the following code and how? - c

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.

Related

++i and i++ in while loop in C

I am using a program to detect the boundary of each data type, which is like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
/*first while loop using a++ dosesn't give us a right answer*/
int a = 0;
while (a++ > 0);
printf("int max first = %d\n", a-1);
/*second while loop using ++a performs well*/
int b = 0;
while (++b > 0);
printf("int max second = %d\n", b-1);
system("pause");
return 0;
}
After I compile this propram and excute it, it returns:
int max first = 0
int max second = 2147483647
So I try to debug it, and I find out that in the first part, after a++ becomes 1, then it just stop autoincrement and jump the while loop,while in second part it runs well, why is this happening?
The pre-increment operator (e.g. ++b) is done first, and the value of the expression is the incremented value.
That is
int b = 0;
while (++b > 0) ...
will increment b first and then check its value using the larger-than comparison. Since in the very first iteration ++b will make b equal to 1 the condition will be 1 > 0 which is true.
Now the post-increment operator does the increment after the old value is used.
So for example a++ will return the old value of a and then do the increment.
So with
int a = 0;
while (a++ > 0) ...
the very first iteration a++ will return 0 which means you have the condition 0 > 0 which is false and the loop will never even iterate once. But the value of a will still be incremented, so afterwards it will be equal to 1 (when the loop have already ended).
This behavior of the pre- and post-operators should be part of any decent book, tutorial or class.
after a++ becomes 1, then it just stop autoincrement and jump the
while loop
This happens because of the post and pre increment operators and the ; in while loop working together.
a will be incremented by 1 after the condition a++ > 0 is evaluated. Thus, the condition fails. The ; at the end of the while statement results in an empty loop and the next print statement will be executed even if the condition on which the while loop is based returns true.
This is exactly what happens in the second while loop - the pre increment operator will increment b before the condition is checked inside while (++b > 0);. The empty while loop keeps on adding one to the value of b until there is an overflow.
At this point, strictly speaking, you have invoked undefined behaviour because the operation has resulted in overflowing a signed integer.
Let me rewrite the main function you wrote - so that it becomes easier to understand.
int main()
{
/*first while loop*/
int a = 0;
while (a > 0){ a = a + 1; }
printf("int max first = %d\n", a-1);
/*second while loop*/
int b = 0;
b = b + 1;
while (b > 0){ b = b + 1; }
printf("int max second = %d\n", b-1);
system("pause");
return 0;
}
Some observations regarding what happened here:
Because at the beginning of the first while loop - the value of a is 0 - which is not greater than 0; the loop gets skipped at the beginning. As a result, the first printf outputs 0.
At the beginning of the second while loop, before evaluating the loop control condition; the loop control variable b gets incremented by 1, resulting the value of b becoming 1; which is greater than 0. For this reason, the second loop is executed.
While executing the second loop, the value of b keeps incrementing by 1 until the value of b overflows. At this point, the program encounters undefined behaviour - and exits the while loop if the program doesn't crash or keeps executing the loop indefinitely (in which case, at some stage the OS will terminate the program; or ask the user to terminate it - as the program will become non-responsive).
You mentioned that you wanted to measure the limit of int values; I hope this reference and this reference will help you in some way.

what is this "continue" does exactly?

I have this part of the code, I don't understand. I know "continue" in if, skips that statement. But why? It supposed to print out an array like " 073.45 * C". The i=2 is for the numbers, right? what does Temp_s[5-i}=result%10+0x30 do? Can someone explain this code please.
void Convert_data_to_temp(unsigned long data)
{
unsigned long result;
unsigned char i=0;
result=((33*1000*data)/4096)%100000;//rounding off to maximum 5 digits
Temp_s[0]=0x30;
Temp_s[3]='.';
for(i=0;i<6;i++)
{
if(i==2){continue;}
Temp_s[5-i]=(result%10)+0x30;
result=result/10;
}
Temp_s[i]=32;
Temp_s[i+1]=32;
Temp_s[i+2]='*';
Temp_s[i+3]=32;
Temp_s[i+4]='C';
Temp_s[i+5]=13;
Temp_s[i+6]=10;
}
Thanks
Well that's a nice mess for sure. Here's what this code does (assuming there's a Temp_s char array in scope that has at least 13 elements).
void Convert_data_to_temp(unsigned long data)
{
unsigned long result;
unsigned char i=0;
// Calculate... something.
// Apparently the calculation is done in fixed-point decimal,
// with 3 decimal places (hence `*1000`).
// Also, the comment is wrong: that's not rounding off, the result will wrap.
// In any case, we can be sure that 0 <= result < 100000.
result=((33*1000*data)/4096)%100000;//rounding off to maximum 5 digits
Temp_s[0]=0x30; // ASCII for '0'
Temp_s[3]='.';
// Now Temp_s looks like this (? represents an indeterminate value:
//
// 0 ? ? . ? ? ? ? ? ? ? ? ?
// Now we're filling Temp_s backwards from the 5th index,
// with the respective digits of `result`. The `continue` skips over
// index 3 so we don't overwrite the '.' we just put there.
for(i=0;i<6;i++)
{
if(i==2){continue;}
Temp_s[5-i]=(result%10)+0x30; // Again, 0x30 is just ASCII '0'.
result=result/10;
}
// Let's say that result was 12345. Now Temp_s looks like this:
//
// 1 2 3 . 4 5 ? ? ? ? ? ? ?
// And now we fill the rest of Temp_s with these hard-coded values.
// Note that we retrieve i at the value it was left by the for, i.e. 6.
Temp_s[i]=32; // 32 is an ASCII space
Temp_s[i+1]=32;
Temp_s[i+2]='*';
Temp_s[i+3]=32;
Temp_s[i+4]='C';
Temp_s[i+5]=13; // ASCII Carriage return
Temp_s[i+6]=10; // ASCII Line feed
// In the end, Temp_s looks like this:
//
// 1 2 3 . 4 5 [space] [space] * [space] C \r \n
}
Apparently the code is broken, too: the computation of result hints at 3-decimals fixed-point, but the representation ends up with only two decimals, and overwrites the '0' that was assigned at the very beginning.
I suggest you just throw that crazy code away and use the tried-and-true standard library:
snprintf(
Temp_s, sizeof Temp_s,
"%.3lu.%.2lu * C\r\n",
result / 100, result % 100
);
The code as a whole converts a 5-digit decimal number such as 54321 into "543.21 * C\r\n" — except that it doesn't ensure that the string is null terminated. However, if the target array Temp_s is a global variable and is big enough and is only written to by this function, then probably there is a null at the end already, but it is simpler and safer to make sure.
The assignment Temp_s[0]=0x30; could be dropped, and the loop could be written more clearly as:
for (i = 0; i < 6; i++)
{
if (i == 2)
Temp_s[5-i] = '.';
else
{
Temp_s[5-i] = (result % 10) + '0';
result /= 10;
}
}
strcpy(&Temp_s[6], " * C\r\n"); // Adds null termination
Frankly, though, it could (and maybe should) be written as a call to sprintf() (which also ensures that the string is null terminated):
int dp = result % 100;
int un = result / 100;
sprintf(Temp_s, "%.3d.%.2d * C\r\n", un, dp);
You could write instead (noting that result is an unsigned long, hence the change of format conversion specifier):
sprintf(Temp_s, "%.3lu.%.2lu * C\r\n", result / 100, result % 100);
It would be preferable to be able to use snprintf(), but it isn't clear how this global variable is declared, and using sizeof(Temp_s) might not be correct:
snprintf(Temp_s, sizeof(Temp_s), "%.3lu.%.2lu * C\r\n", result / 100, result % 100);
That's weird. Looks like you're iterating over that for loop, but you're not executing the code for i == 2. The continue statement sends you to the next iteration of the for loop before you do anything.
That'd the kind of code that'd really benefit from a well-placed comment..
Temp_s[5-i]=(result%10)+0x30;
Writes at index 5-i of the array Temp_s
The result modulo 10 + 48.
The continue skips the statements in the loop and goes back to the i++ statement and after that to the predicate of the loop. But only if i is equal to two.
All in all this should give you the result calculated before as a string representation.
The if i==2 preserves that you do not overwrite the '.'.

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.

atmost K mismatch substrings?

I'm tryring to solve this problem though using brute force I was able to solve it, but
the following optimised algo is giving me incorrect results for some of the testcases .I tried but couldn;t find the problem with the code can any body help me.
Problem :
Given a string S and and integer K, find the integer C which equals the number of pairs of substrings(S1,S2) such that S1 and S2 have equal length and Mismatch(S1, S2) <= K where the mismatch function is defined below.
The Mismatch Function
Mismatch(s1,s2) is the number of positions at which the characters in S1 and S2 differ. For example mismatch(bag,boy) = 2 (there is a mismatch in the second and third position), mismatch(cat,cow) = 2 (again, there is a mismatch in the second and third position), Mismatch(London,Mumbai) = 6 (since the character at every position is different in the two strings). The first character in London is ‘L’ whereas it is ‘M’ in Mumbai, the second character in London is ‘o’ whereas it is ‘u’ in Mumbai - and so on.
int main() {
int k;
char str[6000];
cin>>k;
cin>>str;
int len=strlen(str);
int i,j,x,l,m,mismatch,count,r;
count=0;
for(i=0;i<len-1;i++)
for(j=i+1;j<len;j++)
{ mismatch=0;
for(r=0;r<len-j+i;r++)
{
if(str[i+r]!=str[j+r])
{ ++mismatch;
if(mismatch>=k)break;
}
if(mismatch<=k)++count;
}
}
cout<<count;
return 0;
}
Sample test cases
Test case (passing for above code)
**input**
0
abab
**output**
3
Test case (failing for above code)
**input**
3
hjdiaceidjafcchdhjacdjjhadjigfhgchadjjjbhcdgffibeh
**expected output**
4034
**my output**
4335
You have two errors. First,
for(r=1;r<len;r++)
should be
for(r=1;r<=len-j;r++)
since otherwise,
str[j+r]
would at some point begin comparing characters past the null-terminator (i.e. beyond the end of the string). The greatest r can be is the remaining number of characters from the jth index to the last character.
Second, writing
str[i+r]
and
str[j+r]
skips the comparison of the ith and jth characters since r is always at least 1. You should write
for(r=0;r<len-j;r++)
You have two basic errors. You are quitting when mismatches>=k instead of mismatches>k (mismatches==k is an acceptable number) and you are letting r get too large. These skew the final count in opposite directions but, as you see, the second error "wins".
The real inner loop should be:
for (r=0; r<len-j; ++r)
{
if (str[i+r] != str[j+r])
{
++mismatch;
if (mismatch > k)
break;
}
++count;
}
r is an index into the substring, and j+r MUST be less than len to be valid for the right substring. Since i<j, if str[j+r] is valid, then so it str[i+r], so there's no need to have i involved in the upper limit calculation.
Also, you want to break on mismatch>k, not on >=k, since k mismatches are allowed.
Next, if you test for too many mismatches after incrementing mismatch, you don't have to test it again before counting.
Finally, the upper limit of r<len-j (instead of <=) means that the trailing '\0' character won't be compared as part of the str[j+r] substring. You were comparing that and more when j+r >= len, but mismatches was less than k when that first happened.
Note: You asked about a faster method. There is one, but the coding is more involved. Make the outer loop on the difference delta between starting index values. (0<delta<len) Then, count all acceptable matches with something like:
count = 0;
for delta = 1 to len-1
set i=0; j=delta; mismatches=0; r=0;
while j < len
.. find k'th mismatch, or end of str:
while mismatches < k and j+r&ltlen
if str[i+r] != str[j+r] then mismatches=mismatches+1
r = r+1
end while
.. extend r to cover any trailing matches:
while j+r<len and str[i+r]==str[j+r]
r + r+1
end while
.. arrive here with r being the longest string pair starting at str[i]
.. and str[j] with no more than k mismatches. This loop will add (r)
.. to the count and advance i,j one space to the right without recounting
.. the character mismatches inside. Rather, if a mismatch is dropped off
.. the front, then mismatches is decremented by 1.
repeat
count = count + r
if str[i] != str[j] then mismatches=mismatches-1
i = i+1, j = j+1, r = r-1
until mismatches < k
end if
end while
That's pseudocode, and also pseudocorrect. The general idea is to compare all substrings with starting indices differing by (delta) in one pass, starting and the left, and increasing the substring length r until the end of the source string is reached or k+1 mismatches have been seen. That is, str[j+r] is either the end of the string, or the camel's-back-breaking mismatch position in the right substring. That makes r substrings that had k or fewer mismatches starting at str[i] and str[j].
So count those r substrings and move to the next positions i=i+1,j=j+1 and new length r=r-1, reducing the mismatch count if unequal characters were dropped off the left side.
It should be pretty easy to see that on each loop either r increases by 1 or j increases by 1 and (j+r) stays the same. Both will j and (j+r) will reach len in O(n) time, so the whole thing is O(n^2).
Edit: I fixed the handing of r, so the above should be even more pseudocorrect. The improvement to O(n^2) runtime might help.
Re-edit: Fixed comment bugs.
Re-re-edit: More typos in algorithm, mostly mismatches misspelled and incremented by 2 instead of 1.
#Mike I have some modifications in your logic and here is the correct code for it...
#include<iostream>
#include<string>
using namespace std;
int main()
{
long long int k,c=0;
string s;
cin>>k>>s;
int len = s.length();
for(int gap = 1 ; gap < len; gap ++)
{
int i=0,j=gap,mm=0,tmp_len=0;
while (mm <=k && (j+tmp_len)<len)
{
if (s[i+tmp_len] != s[j+tmp_len])
mm++;
tmp_len++;
}
// while (((j+tmp_len)<len) && (s[i+tmp_len]==s[j+tmp_len]))
// tmp_len++;
if(mm>k){tmp_len--;mm--;}
do{
c = c + tmp_len ;
if (s[i] != s[j]) mm--;
i++;
j++;
tmp_len--;
while (mm <=k && (j+tmp_len)<len)
{
if (s[i+tmp_len] != s[j+tmp_len])
mm++;
tmp_len++;
}
if(mm>k){tmp_len--;mm--;}
}while(tmp_len>0);
}
cout<<c<<endl;
return 0;
}

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

#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) */

Resources