the declare scope of loop - c++

Can anyone explain to me, why the below codes have different output?
void GenerateMatrix(int mat[][MaxSize],int ran[],const int rows,const int cols)
{
int i,k=0;
while (i<rows)
{
int j=0;
while (j<cols)
{
mat[i][j]=ran[k];
j,k++;
}
i++;
}
}
and the correct one
void GenerateMatrix(int mat[][MaxSize],int ran[],const int rows,const int cols)
{
int k=0;
for (int i=0; i<rows;i++)
{
for (int j=0; j<cols;j++)
{
mat[i][j]=ran[k];
k++;
}
}
}
the ran[] is an array declared in main()
int main()
{
srand(time(NULL));
int a[10];
for (int i=0;i<10;i++)
{
a[i]={(rand() % 20-0+1)+1};
cout<<a[i]<<endl;
}
.
.
.
}
the first one always output strange random numbers, not in the range of random numbers I set for a[] in main().
The second one is correct.
I have change the scope of declaration of k in the first one function, still the same. I'm just wondering witch part result in this?

You seem to be following a "spoken English" approach to using the ,, like "do something to this list of variables". In this reading, the initialisation failure (where it does create a list other than you mean; spotted by CherryDT) and the incrementation failure (caused by misuse as comma operator; spotted by two commenters, including me) can be "read".
I propose to change that by reading up on the "comma operator" and reviewing some tutorials on other uses of ",".
Consider reducing/avoiding the use altogether, it is too dangerous for your coding habits.

In the first function you have two errors:
The statement
int i,k=0;
is equivalent to
int i;
int k=0;
This means that i is uninitialized and will have an indeterminate value.
You need to explicitly initialize it as well:
int i = 0, k = 0;
The second error is the statement:
j,k++;
This is equivalent to
j;
k++;
That is, it evaluates the left-hand side of the comma operator (i.e. j) and then throws away the result. Then it evaluates and returns the result of the right-hand side (i.e. k++).
You need to increment both variables:
j++;
k++;
Or you can use the for loops which are more compact, still as readable, and harder to make such mistakes as in the first function.

Related

Find ways an Integer can be expressed as sum of n-th power of unique natural numbers.code giving wrong output

I have t test cases.
Given two numbers x and n, find number of ways x can be expressed as sum of n-th power of unique natural numbers.
The approach is to either select a number or move to the next one.The ans returned is stored in an array since I am using the dp approach.
This is my code
#include<bits/stdc++.h>
using namespace std;
int arr[101];
int func(int x,int n,int ind)
{
if(arr[x]!=-1)
{
return arr[x];
}
if(x==0)
{
return 1;
}
if(ind>=(sqrt(x)+1))
{
return 0;
}
if(x<0)
{
return 0;
}
//you can either take ind or just move to the next one
arr[x]=func(x-pow(ind,n),n,ind+1)+func(x,n,ind+1);
return arr[x];
}
int main()
{
int t;
cin>>t;
while(t)
{
int ans=0;
memset(arr,-1,sizeof(arr));
int x,n;
cin>>x>>n;
int ind=1;
ans=func(x,n,ind);
cout<<"printing the ans\n"<<ans;
t--;
}
return 0;
}
for input
1
10 2
I am getting
printing the ans
-297160607
though the ans is 1
I inserted a simple debug output in func. For the given input "1 10 2" x sometimes gets negative. This causes UB when accessing the array, but does not necessarily crash.
You already check if x is less than 0, but after using x. Move the if(x < 0) up and you are done.
In general to avoid such mistakes you should use stl containers like std::array or std::vector. Though it is not garantued by the c++ standard, many implementations will performe bounds checking on operator[] when compiled in debug mode. Or you can use at() where the standard garantuess bounds checking.

C++ Passing arrays by reference to a function but contents remain unchanged

I'm working on a program to solve an Economics model. First, I declare a namespace as follows:
namespace myNameSpace
{
const int d1{10};
const int d2{5};
const int d3{7};
double array[d1][d2][d3]={};
}
Then, I have a function that modifies array:
void doSomething(double (&array)[myNameSpace::d1][myNameSpace::d2][myNameSpace::d3])
{
int i,j,k;
for (i=0, j=0, k=0; i<myNameSpace::d1,j<myNameSpace::d2,k<myNameSpace::d3; i++,j++,k++)
array[i][j][k]=i+j+k+1.0;
}
In the main function I call doSomething as:
int main()
{
doSomething(myNameSpace::array);
for (int i=0;j<myNameSpace::d1;j++)
std::cout << myNameSpace::array[i][1][1] << std::endl;
}
The output I get in the console is:
0
0
0
Can you provide any guidance on this? I've tried passing array without the address-of operator &, but then inside doSomething, array losses the first dimension. Any help will be highly appreciated!!
First of all, your for loop
for (i=0, j=0, k=0; i<myNameSpace::d1,j<myNameSpace::d2,k<myNameSpace::d3; i++,j++,k++)
doesn't do what you think it does, and you would've (hopefully) noticed that if you compiled with warnings (warning: relational comparison result unused).
It has 2, related, major problems:
Since i<myNameSpace::d1,j<myNameSpace::d2,k<myNameSpace::d3 only returns the value of the last comparison, due to the comma operator being used. So, you are effectively iterating until k<myNameSpace::d3.
The for loop you wrote - is just a single loop. It doesn't iterate through all possible combinations of values of i, j, and k, as you might have wanted.
It initializes i, j, k to 0; checks comparison expression (which, as explained by (1) only checks the value of k); and after the code in the loop was run - increments all of i, j, k by 1. Hence - you are setting only the 0/0/0, 1/1/1, 2/2/2, ..., up until k/k/k indices of your array. And, because your middle array has a bound, which is smaller than k - you invoke undefined behavior by stepping out of bounds.
And, lastly, you are printing only the i/1/1 index of your array, and since the only one value in the index range 0/1/1-d1/1/1 that's set is 1/1/1 - it is, exactly what's printed with a non-zero value.
To iterate over the whole array, as, might have been your intention - you should use nested loops, so they would allow all of the loop variables to change independently of one another:
for (i=0; i<myNameSpace::d1; i++)
{
for (j=0; j<myNameSpace::d2; j++)
{
for (k=0; k<myNameSpace::d3; k++)
{
array[i][j][k]=i+j+k+1.0;
}
}
}
for start you have a problem with your for loop
initialize i and running over j. once I changed it, I received some values.
If your array declared with those sizes it's way shorter (and readable)to write:
void doSomething( declspec(myNameSpace::array) &array )
or much better to declare type alias to use it everywhere:
using myArrayType = double[myNameSpace::d1][myNameSpace::d2][myNameSpace::d3];
not to mention that d1,d2 and d3 should be const. Toset ALL elements of array your loops should look like this:
void doSomething( myArrayType &array )
{
int i,j,k;
for ( i = 0; i < myNameSpace::d1; i++)
for ( j = 0; j < myNameSpace::d2; j++)
for (k = 0; k < myNameSpace::d3; k++)
array[i][j][k]=i+j+k+1.0;
}
Everything written in single for divided by comma is happening in single iteration. There are perverted ways to write it in single for() but I don't recommend that code.
for() loop is very flexible. pretty much it looks like
for(expressionFirst; expressionCheck; expressionEach )
statement to execute
expressionFirst can be ANY statement OR a single declaration, it executes only once, before loop starts. expressionCheck executed at beginning of each iteration, it must be any expression that is contextually convertible to bool (i.e. if even explicit T::operator bool() const; is applicable in this case), if it returns false, the loop stops. expressionEach is any expression that evaluates at end of each iteration.
Equivalent of for()
{
expressionFirst
while ( expressionCheck )
{
statement to execute
expressionEach;
}
}
All expressions are optional, so you can use for(;;) - a "forever" loop.
Comma operator you use allows to sequence several expressions, only last one is returned as result. Thus it is called sequence operator. And that's why your loop is wrong.
And you have a typo in main function, which led you to print only the first element of array, no increment of i.
I tried to compile your code, and I got an error in this line:
for (int i=0;j<myNameSpace::d1;j++)
The variable j is undeclared. As you can note, you declared the variable i inside the for loop, but not j. Do you want to loop using i or j? ...Maybe it's i because inside the body of the loop you used it as first-dimension index?
So, maybe you meant this code?
for (int i = 0; i < myNameSpace::d1; i++)
std::cout << myNameSpace::array[i][1][1] << std::endl;
In addition, are you sure the loop inside doSomething does what you mean?
Or maybe you want to loop using three nested loops for each array dimension?
E.g.:
void doSomething(double (&array)[myNameSpace::d1][myNameSpace::d2][myNameSpace::d3])
{
for (int i = 0; i < myNameSpace::d1; i++) {
for (int j = 0; j < myNameSpace::d2; j++) {
for (int k = 0; k < myNameSpace::d3; k++) {
array[i][j][k] = i + j + k + 1.0;
}
}
}
}
Note that in C++ raw arrays are passed by reference, so the &array syntax is unnecessary. Moreover, the compiler also ignores the raw array dimensions (myNameSpace::d1, etc.) for array parameters. Those may be good for documentation purposes though.

Error in program for modified bubble sort

Codeforces problem 339A-http://codeforces.com/problemset/problem/339/A
I have tried to sort the values stored at even places of the array(starting from 0).I get an error while running the program or program returns a junk value.What is wrong with my solution?
My solution:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[101],temp;
int i,j;
cin>>s;
for(i=0;i<strlen(s);i+=2) //Bubble sorting values at even values of i.'+' is stored at odd values of i.
{
for(j=0;j<(strlen(s)-i-2);j+=2)
{
if(s[j]>s[j+2])
{
temp=s[j];
s[j]=s[j+2];
s[j+2]=temp;
}
}
}
cout<<s;
}
Your compiler should have warned you about the problem (you did switch on all warnings, yes? always do that!): Once i==strlen(s)-1, the loop for j is essentially unbounded, by the magic of arithmetic rules for signed/unsigned values.
for(unsigned j=0; j+2+i < strlen(s); j+=2)
does not have this problem. (i should be unsigned as well.)
Or stop the loop for i earlier. The problem in your code is still there then, but you won’t run into it. But I believe that is the worse route to take – fix the bug, and then optimize by observing i doesn’t need to go as far up, because the last character already forms a sorted sequence.
For odd lengths len of s, the outer loop runs until i==len-1. The inner loop then terminates at len - len - 1 - 2. Since strlen returns an unsigned type, this evaluates to a very large unsigned number, causing the inner loop to read way beyond the end of s. Eventually you'll reach memory you don't have access to read or write, causing the crash.
You can fix this by ending the outer loop sooner
int len = strlen(s);
for(i=0;i<len-2;i+=2) {
for(j=0;j<(len-i-2);j+=2)
Change this:
for(i=0;i<strlen(s);i+=2)
Into this:
for(i=0;i<strlen(s) - 2;i+=2)
Otherwise the s value be handled beyond its end-point
here is my code
void bubble(int a[], int n){
for(int i=0; i<n; i++){
int swaps=0;
for(int j=0; j<n-i-1; j++){
if(a[j]>a[j+1]){
int t=a[j];
a[j]=a[j+1];
a[j+1]=t;
swaps++;
}
}
if(swaps==0)
break;
}
}

Wrong number of iterations in for loop.Also getting unexpected output

Codeforces problem 160A-http://codeforces.com/problemset/problem/160/A
I am getting either 1 or 2 as the output for all test cases.I think this is because the for loop at the end of the solution is only running either once or twice only.I am not able to identify why is the loop ending after atmost 2 iterations.What is wrong with my solution.
My solution:
#include<iostream>
using namespace std;
int total(int x,int y,int array[100]) //Function to calculate sum of xth to yth term of array.
{
int z=0;
for(int a=x;a<=y;a++)
{
z+=array[a];
}
return z;
}
int main()
{
int n,coin[],sum1,sum2,i,j,a,temp,noofcoins;
cin>>n;
for(i=0;i<n;i++)
cin>>coin[i];
for(i=0;i<n;i++) //Bubble sorting array in descending order.
{
for(j=0;j<n-i-1;j++)
{
if(coin[j]<coin[j+1])
{
temp=coin[j];
coin[j]=coin[j+1];
coin[j+1]=temp;
}
}
}
noofcoins=0;
sum1=0;
sum2=0;
for(i=0;((i<n)&&(sum1<=sum2));i++)
{
sum1+=coin[i];
sum2=total(i+1,n,coin);
++noofcoins;
}
cout<<noofcoins;
}
First, avoid using global variables. This declaration belongs to the main body
int n,coin[100],sum1,sum2,i,j,temp,noofcoins;
Once you correct it you'll notice the variable i used in the function totalis the same as the one used in main. Just initialize it in the for.
for(int i=x;i<y;i++)
Then, the condition in the final for is wrong. It should be:
for(i=0;((i<n)&&(sum1<=sum2));i++)
You have defined i as a global variable.
You use i both in the function total as in main where you use i for the loop where you call total. So after you called total, i has become a different value, and the loop in main will end.
U have declared i as a global variable and then u are using it at two places and then that's certainly causing the problems
1-there's no reason to declare your variables globally, it's better to declare them in your main() function.
2-Your way of bubble sorting seems to be wrong. The correct way is to sort the bubble until there's no swapping required.
bool flag=flase;
while (!flag){
flag=true;
for(i=0;i<n-1;i++){ //Bubble sorting array in descending order.
if (coin[i]<coin[i+1]){
temp=coin[i];
coin[i]=coin[i+1];
coin[i+1]=temp;
flag=false;
}
}
}
3-your way of passing an array to a function is incorrect. Read the part "Arrays as parameters" on this page for the right way.
4-Finally, you might want to use "new" function to create your array. This way it will not be limited to your maximum array size of 100, and also won't waste memory when your array is smaller than 100.
Read here for learning to use "new" function.
following may help:
int twin(std::vector<int> coins)
{
std::sort(coins.begin(), coins.end());
const int total = std::accumulate(coins.begin(), coins.end(), 0);
int left = total;
int right = 0;
for (size_t i = 0; i != coins.size(); ++i)
{
const int value = coins[coins.size() - 1 - i];
left -= value;
right += value;
if (right > left) {
return 1 + i;
}
}
return 0;
}

Basic obfuscation program

#include<iostream>
#include<conio.h>
#include<math.h>
#include<vector>
#include<iterator>
#include<string>
using namespace std;
int main() {
int k=0;
string s;
cout<<"string ";
getline(cin,s); //taking in a string from the user
float n=s.size(); //storing size of string
int f=floor((sqrt(n))); //floor of square root of input string
int c=ceil((sqrt(n))); //ceiling
int m=f*c; //storing product of f and c
vector< vector<string> > vec(n<=m?f:++f, vector<string>(c)); //makes a 2d vector
//depending on user's
//string length
for(int i=0;n<=m?i<f:i<++f;i++) //looping acc to user's input and assigning
{
for(int j=0;j<c;j++) //string to a matrix
{
if(k<s.size())
{
vec[i][j]=s[k];
k++;
}
}
}
for(int j=0;j<c;j++) //printing the vector
{
{
for(int i=0;n<=m?i<f:i<++f;i++)
cout<<vec[i][j];
}cout<<" ";
}
getch();
}
It's not working for n>m as for a string of length 8 characters it makes a vector of 2*3 thus failing to enclose the whole string in the matrix and which is why I am using ternary so as to make a vector of bigger size when it encounters cases like these.
.So what am I doing wrong?
I'll just write the whole question.
One classic method for composing secret messages is called a square code. The spaces are removed from the english text and the characters are written into a square (or rectangle). The width and height of the rectangle have the constraint,
floor(sqrt(word)) <= width, height <= ceil(sqrt(word))
The coded message is obtained by reading down the columns going left to right. For example, the message above is coded as:
imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau
Sample Input:
chillout
Sample Output:
clu hlt io
This won't fix your entire problem, but I still feel it is important. You seem to misunderstand how the ternary works. Let's observe one of its uses here:
for (int i = 0; n <= m ? i < f : i < ++f; i++) {}
// ^^^^^^^^^^^^^^^^^^^^^^^^ <--- not the intended outcome
This will not work because the returned side of the ternary does not "stick" itself in-place. In other words, neither i < f nor i < ++f will be put directly into the for-loop. Instead, it'll give you a value.
To see what it's really doing, you'll first need to understand that the ternary is just another way to do an if-else. The ternary above, put into if-else form, looks like this:
if (n <= m)
i < f; // left side of the ":"
else
i < ++f; // right side of the ":"
Let's break it down further:
i < f
This is doing a less-than comparison of i and f. So, depending on the individual values, you'll receive either a 0 (false) or a 1 (true).
So, in your for-loop, this will occur:
for (int i = 0; 1; i++) {}
// ^ <--- if comparison returns true
for (int i = 0; 0; i++) {}
// ^ <--- if comparison returns false
So, for your example, you'll need to find the value of f before the loop. You can use a ternary for that part, but only if you understand it. Otherwise, use another method to find f (the intended numerical value). Once you find it, then you can put i < f into the for-loop.