Lecture four - Simple instructions and tricks
There are three types of loops in C: for, while and do while.
for ( init-statement(optional) ; condition(optional) ; iteration_expression(optional) )
Any "while" loop can be trivially re-written as a "for"
while (number <= 126)
is the same as
for ( ; number <= 126 ; )
What happens here?
for(;; i++)
{
printf("%d ", i);
}
While loop:
while(condition) {
statement(s);
}
do.. while loop:
do {
statement(s);
}
while( condition );
Break statement
Terminates the loop or switch statement and transfers execution to the statement immediately following the loop or switch.
do {
printf("%d ", a);
a = a + 1;
if( a > 15) {
// terminate the loop
break;
}
} while( a < 20 );
Continue statement
Causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating.
do {
if( a == 15) {
// skip the iteration.
a = a + 1;
continue;
}
printf("value of a: %d ", a);
a = a + 1;
}
while( a < 20 );
Output:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19
The "if ... else ..." branching mechanism is a familiar construct in many procedural programming languages. In C++, it is simply called an if statement, and the general syntax is
if (condition) {
Statement1;
...
...
StatementN;
} else {
StatementN+1;
...
...
StatementN+M;
}
In computer programming, ?: is a ternary operator that is part of the syntax for basic conditional expressions.
(condition) ? (if_true) : (if_false)
Example
largest = ((a > b) ? a : b);
The main fundamental difference is that the ternary operator is an expression whereas the if structure is a statement. A ternary operator expression's result can be assigned to a variable -- the results of an if statement cannot.
Ternary operator does not support block of code as the block of code does not return a value (is not an expression).
What will happen?
int x,y;
scanf("%d %d",&x,&y);
((x<y)?x:y) = -((x>y)?x:y);
For choosing out of more than two options we can use switch
switch (selector)
{
case label1: <statements 1>
break;
...
...
...
case labelN: <statements N>
break;
default: <statements>
}
The statements which are executed are exactly those between the first label which matches the value of selector and the first "break" after this matching label.
When a "break" is encountered within a case's statement, control is transferred immediately to the first program statement following the entire "switch" statement. Otherwise, execution continues.
Without breaks all code under given case will be executed.
Regular switch statements, by default, have a unique scope for the whole switch (as shown by the {}).
However this given an error:
switch( x ) {
case 0:
int y = 0;
printf("int: %d\n",y);
case 1:
char y = 'A'; // Error: y is already an int
printf("char: %c\n",y);
case 2:
float y = 1.66;
printf("float: %f\n",y);
default:
// do nothing
break;
}
Solution:
switch(x) {
case 0: {
int y = 0;
printf("int: %d\n",y);
}
case 1: {
char y = 'A'; // now it is ok
printf("char: %c\n",y);
}
case 2: {
float y = 1.66;
printf("float: %f\n",y);
}
default: {
// do nothing
break;
}
}
#include<stdio.h>
int main()
{
switch(3/3)
{
case 1:
printf("case 1 executed ");
case 2:
printf("case 2 executed ");
break;
default:
printf("Default block executed");
}
return 0;
}
Output:
case 1 executed case 2 executed
The pair container is a simple container consisting of two data elements or objects.
The first element is referenced as ‘first’ and the second element as ‘second’ and the order is fixed (first, second).
Pair is used to combine together two values which may be different in type.
To access the elements, we use variable name followed by dot operator followed by the keyword first or second.
#include <iostream>
#include <utility>
using namespace std;
int main()
{
pair <int, char> PAIR1 ;
pair <string, double> PAIR2 ("GeeksForGeeks", 1.23) ;
pair <string, double> PAIR3 ;
PAIR1.first = 100;
PAIR1.second = 'G' ;
PAIR3 = make_pair ("GeeksForGeeks is Best",4.56);
cout << PAIR1.first << " " ;
cout << PAIR1.second << endl ;
cout << PAIR2.first << " " ;
cout << PAIR2.second << endl ;
cout << PAIR3.first << " " ;
cout << PAIR3.second << endl ;
return 0;
}
std::tuple is a fixed-size collection of different values.
// Declaring tuple
tuple <char, int, float> geek;
// Assigning values to tuple using make_tuple()
geek = make_tuple('a', 10, 15.5);
// Printing initial tuple values using get()
cout << "The initial values of tuple are : ";
cout << get<0>(geek) << " " << get<1>(geek);
cout << " " << get<2>(geek) << endl;
// Use of get() to change values of tuple
get<0>(geek) = 'b';
get<2>(geek) = 20.5;
An operator, in computer programing, is a symbol that usually represents an action or process. These symbols were adapted from mathematics and logic. An operator is capable of manipulating a certain value or operand.
assignment | inc / decrement | arithmetic | logical | comparison | member access | other |
a = b a += b a -= b a *= b a /= b a %= b a &= b a |= b a ^= b a <<= b a >>= b |
++a --a a++ a-- |
+a -a a + b a - b a * b a / b a % b ~a a & b a | b a ^ b a << b a >> b |
!a a && b a || b |
a == b a != b a < b a > b a <= b a >= b |
a[b] *a &a a->b a.b a->*b a.*b |
a(...) a, b ? : |
Precedence | Operator | Description | Associativity |
1 | : | Scope resolution | Left-to-right |
2 | a++ a-- | Suffix/postfix increment and decrement | |
type() type{} | Functional cast | ||
a() | Function call | ||
a[] | Subscript. | ||
-> | Member access | ||
3 | ++a --a | Prefix increment and decrement | Right-to-left |
+a -a | Unary plus and minus | ||
! ~ | Logical NOT and bitwise NOT | ||
(type) | C-style cast | ||
*a | Indirection (dereference) | ||
&a | Address-of | ||
sizeof | Size-of | ||
new | Dynamic memory allocation | ||
delete | Dynamic memory deallocation | ||
4 | .* ->* | Pointer-to-member | Left-to-right |
5 | a*b a/b | a%b Multiplication, division, and remainder | |
6 | a+b a-b | Addition and subtraction | |
7 | << >> | Bitwise left shift and right shift | |
8 | < <= | For relational operators < and ≤ respectively | |
> >= | For relational operators > and ≥ respectively | ||
9 | == != | For relational operators = and ≠ respectively | |
10 | a&b | Bitwise AND | |
11 | ^ | Bitwise XOR (exclusive or) | |
12 | Bitwise OR (inclusive or) | ||
13 | && | Logical AND | |
14 | || | Logical OR | |
15 | a?b:c | Ternary conditional | Right-to-left |
throw | throw operator | ||
= | Direct assignment | ||
+= -= | Compound assignment by sum and difference | ||
*= /= %= | Compound assignment | ||
<<= >>= | Compound assignment by bitwise shift | ||
&= ^= |= | Compound assignment by AND, XOR, and OR | ||
16 | , | Comma | Left-to-right |
Example:
x = -a * b;
Precedence levels = has level 15, * has level 5 and - has level 3.
Thus it is equivalent to:
x = ((-a) * b);
Operators that have the same precedence are bound to their arguments in the direction of their associativity. For example, the expression a = b = c is parsed as a = (b = c), and not as (a = b) = c because of right-to-left associativity of assignment, but a + b - c is parsed (a + b) - c and not a + (b - c) because of left-to-right associativity of addition and subtraction.
The Operators which operate on Single Operand known as Unary Operators, some of the unary operators are:
++ Increment Operator
-- Decrement Operator
& Address Of Operator
* Dereference operator
- Unary Minus Operators
~ (One’s Compliment) Negation Operator
! Logical NOT
The program fragment
x = 4;
y = x++;
results in "x" having the value 5 and "y" having the value 4, whereas
x = 4;
y = ++x;
results in both variables having value 5.
Why is it so?
i++ makes a copy, increases i, and returns the copy (old value).++i increases i, and returns i.
// ++i
function pre_increment(i) {
i += 1;
return i;
}
// i++
function post_increment(i) {
copy = i;
i += 1;
return copy;
}
++i will be the faster than i++ since it doesn't make a copy.
In general, assignment statements have a value equal to the value of the left hand side after the assignment. Hence the following is a legal expression which can be included in a program and which might be either evaluated as true or as false:
(y = ++x) == 5
That is why this does not create compilation error
if (a = b)
cout << "a is equal to b.";
What will be the value of b?
int a = 5;
int b = a++ + ++a;
(At least according to the things that we have just mentioned)
Output:
b = 12
a = 7
Undefined behaviour may also be expected when Language Standard omits the description of any explicit definition of behavior.
int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.
i = i++ * ++i; // Undefined Behaviour
i = ++i + i++; // Undefined Behaviour
i = ++i + ++i; // Undefined Behaviour
i = v[i++]; // Undefined Behaviour
i = v[++i]: // Well-defined Behavior
i = i++ + 1; // Undefined Behaviour
i = ++i + 1; // Well-defined Behaviour
++++i; // Well-defined Behaviour
Comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).
Example:
/**
* Assigns value of b into i.
* Results: a=1, b=2, c=3, i=2
*/
int a=1, b=2, c=3;
int i = (a, b);
And another one:
/**
* Increases value of a by 2, then assigns value of resulting operation a+b into i .
* Results: a=3, b=2, c=3, i=5
*/
int a=1, b=2, c=3;
int i = (a += 2, a + b);
Last example:
int x=0;
if(cin>>x,x*=2,x<8) { /*do stuff*/}
What will be printed on the screen?
int main()
{
int x = 10, y;
y = (x++, printf("x = %d\n", x), ++x, printf("x = %d\n", x), x++);
printf("y = %d\n", y);
printf("x = %d\n", x);
return 0;
}
Output:
x = 11
x = 12
y = 12
x = 13
std::cout << (-7 % 3) << std::endl;
std::cout << (7 % -3) << std::endl;)
Gives -1 and 1. In general if a % b = x then
(a/b)*b + x = a
thus
(-7/3) => -2
-2 * 3 => -6
so a%b => -1
(7/-3) => -2
-2 * -3 => 6
so a%b => 1
A | B | !A | A && B | A || B | A ^ B |
0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 0 | 1 | 1 | 0 |
Logical operators "&&" ("and"), "||" ("or") and "!" ("not"),
The operator "&&" has a higher precedence than the operator "||".
NOT ( ~ ): Bitwise NOT is an unary operator that flips the bits of the number i.e., if the ith bit is 0, it will change it to 1 and vice versa.
N = 5 = (101)
~N = ~5 = ~(101) = (010) = 2
AND ( & ): Bitwise AND is a binary operator that operates on two equal-length bit patterns. If both bits in the compared position of the bit patterns are 1, the bit in the resulting bit pattern is 1, otherwise 0.
OR ( | ): Bitwise OR is also a binary operator that operates on two equal-length bit patterns, similar to bitwise AND. If both bits in the compared position of the bit patterns are 0, the bit in the resulting bit pattern is 0, otherwise 1.
There are two shift operators a << b and a >> b.
The former shifts all the bits in a to the left by b positions; the latter does the same but shifts right.
You can think of left-shifting by b as multiplication by 2^b and right-shifting as integer division by 2^b.
The most common use for shifting is to access a particular bit, for example, 1 << x is a binary number with bit x set and the others clear
1 << 1 = 2
1 << 2 = 4
1 << 4 = 16
1 << n = 2^n
4 >> 1 = 2
6 >> 1 = 3
5 >> 1 = 2
16 >> 4 = 1
Power set is a set of all subsets of a given set.
void printPowerSet(char *set, int set_size)
{
/*set_size of power set of a set with set_size n is (2**n -1)*/
unsigned int pow_set_size = pow(2, set_size);
int counter, j;
/*Run from counter 000..0 to 111..1*/
for(counter = 0; counter < pow_set_size; counter++)
{
for(j = 0; j < set_size; j++)
{
/* Check if jth bit in the counter is set If set then print jth element from set */
if(counter & (1<<j)) printf("%c", set[j]);
}
printf("\n");
}
}
Count bits which are one in a given number.
int count_ones(int num)
{
int count = 0;
int mask = 0x1;
while (num) {
if (num & mask)
count++;
num >>= 1;
}
return count;
}
The & and | operators have lower precedence than comparison operators. That means that x & 3 == 1 is interpreted as x & (3 == 1), which is probably not what you want.
If you need to change a value really quick to test something:
int x =
//Actual_value
Testing_value
;
Two string literals, placed "next to" each other, will be treated as one:
printf("abc" "def"); // same as printf("abcdef")
This is useful for long strings that you can extend onto more than one line
if (num & 1)
cout << "ODD";
else
cout << "EVEN";
Since last bit denotes the parity of the number.
// Using shift operator
// t is non zero (2^(i)) to be exact if ith bit is set else 0
int t= num & (1<<i);
// Setting ith bit
num|=(1<<i);
// flipping ith bit
num ^ = (1<<i); // ^ is the xor operator
// clearing the ith bit
num=num & ~(1<<i);
n = n << 1; // Multiply n with 2
n = n >> 1; // Divide n by 2
More efficient than
n = n * 2; // Multiply n with 2
n = n / 2; // Divide n by 2
Notice that
101 >> 1 == 10
So
5 / 2 == 2
There is special function in C++ which allows us to swap values of two variables
int c=3;
int d=4;
swap(c,d); // Now c=4 and d=3
a XOR b is equal 1 iff a and b has different bit value.
a | b | a XOR b |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
// A quick way to swap a and b
a ^= b;
b ^= a;
a ^= b;
This method is fast and doesn’t require the use of 3rd variable.
// Use of strlen() can be avoided by:
for (i=0; s[i]; i++)
{
...
}
// loop breaks when the character array ends.
Because the last symbol in string is a zero in the array of chars.
We must be knowing that the maximum size of array declared inside the main function is of the order of 10^6 but if you declare array globally then you can declare its size up to 10^7.
/* Function to check if x is power of 2*/
bool isPowerOfTwo (int x)
{
/* First x in the below expression is
for the case when x is 0 */
return x && (!(x&(x-1)));
}
Function return zero for power of 2 and non-zero value otherwise (remind that every non-zero value means true).
This function is used to assign continuous values to array. This function accepts 3 arguments, the array name, size, and the starting number.
// C++ code to demonstrate working of iota()
#include<iostream>
#include<numeric> // for iota()
using namespace std;
int main()
{
// Initializing array with 0 values
int ar[6] = {0};
// Using iota() to assign values
iota(ar, ar+6, 20);
// Displaying the new array
cout << "The new array after assigning values is : ";
for (int i=0; i<6 ; i++)
cout << ar[i] << " ";
return 0;
}
Output:
The new array after assigning values is : 20 21 22 23 24 25
What does it count?
int x;
int y;
int p1,p2; // the result goes here
p1 = y ^ ((x ^ y) & -(x < y));
p2 = x ^ ((x ^ y) & -(x < y));
The rand() function in <stdlib.h> returns a pseudo-random integer between 0 and RAND_MAX.
Pseudorandom number generator, is a function that produces numbers according to some deterministic formula that appear to be random but actually are not. The value of a sequence is determined by so called seed.
Pseudorandom number is a number that isn't truly random, but is "random enough" for most purposes.
Pseudorandom numbers are not safe in cryptographic settings!
Instead of using so many includes , we can simply include bits/stdc++.h in the code and it takes care of all.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <numeric>
#include <bitset>
#include <fstream>
#include <iomanip>
// Instead of all of that we can just use
#include <bits/stdc++.h>
http://www.geeksforgeeks.org/c-tricks-competitive-programming-c-11/
http://en.cppreference.com/w/cpp/language/operator_precedence
https://www.topcoder.com/community/data-science/data-science-tutorials/a-bit-of-fun-fun-with-bits/
https://www.doc.ic.ac.uk/~wjk/c++Intro/
https://pl.wikipedia.org/wiki/Alternatywa_roz%C5%82%C4%85czna
https://stackoverflow.com/questions/31300738/why-ternary-operator-does-not-support-blocks
https://medium.com/@nilotpalmrinal9797/useful-c-tricks-8f251276a53d
http://msoucy.me/seminars/evilC/
http://opensourceforu.com/2012/06/power-programming-bitwise-tips-tricks/
https://www.hackerearth.com/practice/notes/bit-manipulation/
https://www.tutorialspoint.com/cplusplus/cpp_continue_statement.htm