Is redefinition of a variable valid inside loops? - c++

I have encountered the following binarySearch program
int binarySearch(int a[],int b, int c)
{
int start=0,end=b-1;
while(start<=end)
{
int mid=start+(end-start)/2;
if(a[mid]==c)
return mid;
else if(a[mid]>c)
end=mid-1;
else
start=mid+1;
}
if(start>end)
return -1;
}
in which mid variable is initialized in the loop which will be executed if the condition start<=end becomes true.
I am new to programming and i have learnt that redefinition of variable is not valid in C. But i have encountered binarySearch program in which loop will be executed when start<=end will be true and will be initializing an int variable named mid again and again till the condition will be true and thus redefinition will take place. I want to know "are redefinition valid inside loops?" or something else i am missing.

A variable itself is a compile-time concept, it's a label in the source code, a name which refers to an actual object that will exist at runtime.
Since int mid is only spelled once in your code, there's no redefinition. Even if it was spelled multiple times, if the variables are in different places, it can be legal (the variables will shadow one another):
int a = 1;
int main()
{
std::cout << a << '\n'; // 1
int a = 2;
if (true)
{
int a = 3;
std::cout << a << '\n'; // 3
}
std::cout << a << '\n'; // 2
}

Related

Strange C++ output with boolean pointer

I have the following code:
#include <iostream>
using namespace std;
int main() {
int n = 2;
string s = "AB";
bool* xd = nullptr;
for (int i = 0; i < n; i += 100) {
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
cout << "wtf: " << " " << (*xd) << " " << endl;
}
}
When I run this on my own mac with g++ -std=c++17, I get a random integer every time (which is odd since *xd should be a bool). Weirdly enough, this doesn't happen on online IDEs like csacademy and onlinegdb.
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
tmp is an automatic variable. It is destroyed automatically at the end of the scope where the variable is declared. In this case, the lifetime of the object ends when the if-statement ends. At that point, the pointer xd which pointed to the variable becomes invalid.
(*xd)
Here, you indirect through an invalid pointer. That's something that a program must never do. The behaviour of the program is undefined. The program is broken. Don't do this.

Recursion in the main function

I tried recursion in the main function, but why 'i' variable is not getting updated, it only gets updated till i=1 and then remains constant.
Below is the code:-
int main(int i = 0)
{
std::cout << "i value" << i << std::endl;
if (i == 3)
return 0;
std::cout << "hello" << std::endl;
main(i++);
}
See for example cppreference/main_function:
The main function has several special properties:
It cannot be used anywhere in the program
a) in particular, it cannot be called recursively
b) its address cannot be taken
[...]
You cannot call main recursively. Also your signature is not correct. Correct signatures are:
int main () { body } (1)
int main (int argc, char *argv[]) { body } (2)
/* another implementation-defined form, with int as return type */ (3)
For (3) you need to check your implementation, I am not aware of one that allows int main(int) (though I didn't bother to check).
Last but not least, foo(i++); will increment i and then call foo with the original value of i. You probably want foo(++i); or rather foo(i + 1);.
TL;DR
int my_main(int i=0) {
// put code here
my_main(i + 1);
}
int main() {
my_main();
}

Get index of element in a struct c++

I want to get the index of an element in a struct.Below is the code. However it is only returning 0 as the output. Assuming I have added data to the struct below, the function find_index does not return the index of the element.It only returns 0;
struct Person{
string name;
int age;
float spread_prob;
float disease_prob;
float recover_prob;
status disease_status;
int sick_day;
};
Person person[9];
int find_index(string m){
for(i=0;i<9;i++){
if(m==person[i].name){
return i;
}
}
return 0;
}
The return 0 is inside your for-loop. So when the first iteration match, return i is return 0 and if this is not the case return 0 is called. Move the return 0 out of your loop, so the loop will not break after one iteration.
Firstly, your code has syntactical errors such as the loop variable i being not defined and logical errors such as returning 0 inside the for-loop, (which means that irrespective of any index match, your function will only return 0) and returning 0 itself is an error since that implies your string or name is found at the first index. If your not following array indices, consider adding a +1 to the return statement. Otherwise, use something else, such as a -1 or any negative number to indicate that the string is not found/matched in any index.
Next, your code is not defined under proper scope for a minimal reproducible example (one which can be directly copy-pasted and tested on our compilers).
Considering the Person objects are in main(), I have created a lambda / temporary-function inside the main scope which should help you solve your problem: (considering struct's name member and an array of 3 Person objects for demonstration)
#include <iostream>
struct Person
{
std::string name;
};
int main()
{
Person person[3];
person[0].name = "Karl";
person[1].name = "John";
person[2].name = "Felix";
auto findIndex = [=](std::string m)
{ for(int i = 0; i < 3; i++)
{ if(m == person[i].name)
return i;
}
return -1;
};
std::cout << findIndex("Felix");
std::cout << "\n";
std::cout << findIndex("Blaze");
}
Output :
2
-1
int find_index(string m){
int ret = -1; // -1 denotes not available
for(i=0;i<9;i++){
if(m==person[i].name){
ret = i;
break;
}
}
return ret ; //If it matches it will return the index on which it breaks.
}
You can use a return variable.

mergesort not working in c++

Is there anything wrong with the usage of the "return" values of the three fuction? The values printed out are garbage values with seemingly random numbers as outputs.I would also like to add that i havent made it recursive because i wanted to check whether this would work or not.
Most all of the mergesort implementation I've seen hardly contain any return values, is that something im doing wrong. If you were to go about a similar type of implementation, how would you do it?
#include <iostream>
using namespace std;
int* goleft(int array[], int size)
{
int halved=size/2;
int left[halved];
for(int i=0;i<halved;i++)
{
left[i]=array[i];
}
return left;
}
int* goright(int array[],int size)
{
int halved=size/2;
int right[size-halved];
for(int i=halved,j=0;i<size;i++,j++)
{
right[j]=array[i];
}
return right;
}
int* mergesort(int array[],int size)
{
int *l,*r;
l=goleft(array,size);
r=goright(array,size);
int merger[size];
int halved = size/2;
int i;
for(i=0;i<halved;i++)
cout<<l[i]<<endl;
for(i=0;i<halved;i++)
cout<<r[i]<<endl;
int x=0,y=0,k=0;
while(x+y!=size)
{
if(l[x]<r[y])
{
merger[k]=l[x];
x++;k++;
}
else if(l[x]>=r[y])
{
merger[k]=r[y];
y++;k++;
}
}
return merger;
}
int main()
{
int size;
cin>>size;
int array[size];
for(int i=0;i<size;i++)
cin>>array[i];
int *merged=mergesort(array,size);
cout<<"sorted array"<<endl;
for(int i=0;i<size;i++)
cout<<merged[i]<<endl;
return 0;
}
And when we create variables of same name during loops and recursions, are new variable created for every loop iteration or recursion? or do they overwrite the value for the previous variable. for e.g when we write
while(true)
{
int i=0;
}
would a new variable be made at every iteration
and
genericFunction()
{
int i = SomeRandomValue
genericFunction();
}
similarly would a new variable be made at each recursion?
As you thought, the error is in "scopes". To answer to your questions :
while(true)
{
int i=0;
}
The process is :
//iteration N start
create scope
allocate memory for an int variable named 'i' in the current scope
//statements done
delete current scope //deallocate the variables in the current scope
//iteration N end
//iteration N+1 start
/*...*/
So in each iteration it is a different variable. You can test it with this code :
while (true) {
int i;
std::cout << &i << std::endl; //displays the memory location of i
system("PAUSE"); //waiting user input between each iteration
}
In the example with genericfunction, the process is :
//N call to genericFunction
create scope //scope N
//N+1 call to generic Function
create scope //scope N+1
/* statements */
delete current scope //scope N+1
// exit of call N+1
delete current scope //scope N
//exit of call N
You can test it with this complete code :
#include <iostream>
void genericFunction(int a)
{
int i = 0;
std::cout << "scope " << a << " : " << &i << std::endl;
if (a < 9) { //to prevent infinite call
genericFunction(a + 1);
}
std::cout << "scope " << a << " : " << &i << std::endl;
}
int main() {
genericFunction(0);
system("PAUSE");
return 0;
}
A generic rule is : when you have {, you create a new scope and select it as current scope, when you have }, you delete the current scope and select the previous scope. Some scopes permits access to previous scopes (for example a WHILE LOOP : in the code int a; while(true) {a++;}, it modifies the value of a in the previous scope), but when a function scope is created you have no access to previous scopes.
Now for your specific issue with mergedsort, it is the declaration of your variable merger inside the function mergesort. To see the process :
/* ... */
int *merged=mergesort(array,size);
//Call to mergesort
//Creation of scope A
/* ... */
int merger[size]; //Allocation of memory for 'merger' in scope A
/* ... */
return merger; //Affect the location of 'merger' to location pointed by 'merged' in previous scope
//Deletion of scope A (including deallocation of 'merger')
// Now 'merged' points to location of 'merger' which is a deallocated variable :
//no guarantees of the data stored at this location
So it is why there is a problem in your code. One way to correct it is by allocate manually some space for your variable : variables allocated manually have to be deallocated manually, so they will not be deallocated when destroying a scope. Actually the implementation inside the function is using the c++ keyword new : int *merger = new int[size];.
By replacing this declaration your code will be running : but be careful : here's an other rule, if you're using somewhere the keyword new you have to use delete somewhere else : manual allocation have to be followed by manual deallocation. So at the end of your main function, you have to add delete[] merged;. In this way there's no trouble ;) .

How do I return value to main function without directly calling the function

I have multiple functions in my program. Each function has some conditions. If conditions are met, then it passes on the value to another function which again checks the value with some conditions, modifies it.
The first function [named 'squarefree()'] is called from main [obviously] and it further goes on to call another function which in course calls another function untill the process stops at last function named 'end()'. Like this:
#include <iostream>
using namespace std;
int squarefree(int n);
int goodnumber(int sf);
int end(int gn);
int main() {
// your code goes here
int l,r;
cin>>l;
cin>>r;
for(int p=l;p<=r;p++)
{squarefree(p);}
/*int ret=end(int gn); PROBLEM LIES HERE
cout<<ret; */
return 0;
}
int squarefree(int n){
int i;
for(int i=2;i<n;i++)
{
if((n%(i*i))==0)
{
cout<<"number not square free"<<endl;
break;
}
else{
cout<<"number square free"<<endl;
goodnumber(n);
break;
}
}
return 0;
}
int goodnumber(int sf){
cout<<"Sf is:"<<sf<<endl;
int s=0,c=0,flag=0;
for(int j=1;j<=sf;j++)
{
if(sf%j==0)
{
s+=j;
for(int k=2;k<=j/2;++k)
{
if(j%k==0)
{
c++;
}
}
}
}
cout<<"s is:"<<s<<endl;
cout<<"no.of prime numbers dividin s are:"<<c<<endl;
for(int l=2;l<=c/2;++l)
{
if(c%l==0)
{
flag=1;
break;
}
}
if (flag==0)
{cout << "C is a prime number, so this is good number and needs to be passed to next function"<<endl;
end(s);
}
else
{cout << "C is not a prime number"<<endl;
}
return 0;
}
int end(int gn)
{
int sum=0;
sum+=gn;
cout<<"SUm of factors of the good number is:"<<sum<<endl;
return sum;
}
The 'end()' function returns a value sum. Now I want this value sum to be updated everytime the for loop in main() function runs. For example: Sum in first iterations is 5, sum is 2nd iteration is 10, so total sum gets 15 and so on.
If somehow, the value returned by end function can be fetched into main function, that would be great.
Look at all those int-returning functions that are always returning 0. You might be able to take advantage of that.
A trivial example:
#include <iostream>
int step3(int val)
{
return val * val;
}
int step2(int val)
{
return step3(val + 1);
}
int step1(int val)
{
return step2(val * 2);
}
int main()
{
std::cout << step1(1);
}
But take care. You might find a case where you don't get any valid results and need to inform the caller that no result was found.
In addition to the idea of having the functions return the result of the next stage in the pipeline, which is an excellent idea, you can pass the address of the variable in which to store the result (allowing you to return more than one result, or an error code), or store the result of each stage in a temporary variable and return that (allowing you to use a result in more than one computation). I would advise against using a global variable to bypass the stack; it’s considered poor practice.
Some Examples:
// Returning the result of the next stage in the pipeline:
int g(int);
int f(int x)
{
return g(x);
}
// Passing a variable by reference:
enum errcode { success, failure };
errcode sqr( int input, int& output )
{
output = input * input; // This modifies the second variable the caller gave.
return success;
}
// Storing in a temporary variable:
int stage2(int);
int stage1(int x)
{
const int y = stage2(x); // Store the result in a temporary.
const int z = sqr(y);
return z;
}
// Passing results through a global variable is a bad idea:
int necessary_evil = 0; // Declared in global scope; should at least be
// declared static if possible to make it visible only in this source file.
// Namespaces are a fancier way to do something similar.
void kludge(int x)
{
necessary_evil = x * x; // The caller will check the global.
return;
}
There are examples of all of these in the standard library: printf() is essentially a wrapper for vfprintf(), strtol() takes a parameter by reference that the function sets to a pointer to the remainder of the string, and errno is a global variable.