How does C++ while code including two integers operate step by step? - c++

I am quite new to C++ programming, I have reviewed while loops in python before however the two integers confuse me here. I would be very happy if you can explain to me how this while loop operates step by step.
#include<iostream>
using namespace std;
int main() {
int i;
int j;
while(i<10 || j < 5) { // i kucuk ondan kucuk oldu surece {} icerisindeki islemler surekli olarak while() loopu ile tekrarlancak
cout<<"i: "<<i<<" "<<"j: "<<j<<endl;
i = i + 1; // eger bu kod olmaz ise, sonsuza dek i degerine basacak
j = j + 1;
}
return 0;
}

#include<iostream>
using namespace std;
int main() {
/* You should first give a starting value
to the I and j, otherwise they
will get a random number and your while won't work*/
int i=0;
int j=0;
/* so as the word says "while" - while (something here is true)do the
following code between the starting
brackets and the finishing brackets. When it's not True skip the loop and go to the next line, in this example we will go to return 0 */
/*The value of i is 0 and the value of j is 0, and we first check if 0(i)<10 that's true next we check the other one
if 0(j) < 5 yes do the following block*/
/* the || mean "or' if either one of them
is true do the following block of code between the brackets*/
while(i<10 || j < 5) {
//we print
cout<<"i: "<<i<<" "<<"j: "<<j<<endl;
//we are incrementing the values of i and j for 1;
i = i + 1;
j = j + 1;
/*so what happens now it jumps again to the while
and checks if the statement is true, now i = 1 and j = 1;
and this runs until i is 10 because only then the i won't be lesser then
10 and j won't be lesser then 5 it will be false*/
*/
}
//close the program
return 0;
}
Hope I was clear!

You don't declare variables in Python. A "variable" is created when you first assign a value to a name. So you can't have uninitialized variables in Python.
That is not the case in C and C++. This code is declaring the i and j variables, but not assigning any values to them before trying to use them in the while loop. So your code has undefined behavior, as the variables contain whatever random values happened to already be present in memory where they get allocated.
You need to initialize the variables before your loop tries to evaluate them:
int i = 0;
int j = 0;

Related

Make floor pattern

How do i make this?
image of my homework
note: Batasan means limitaion and Contoh means example
So, my professor wants me to do make output the same size horizontal and vertically in pattern shown in the image
I dont know what to do, but the best i can make is this:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
const char * array1[4];
const char * array2[4];
array1[0] = "O", array1[1] = ">", array1[2] = "X", array1[3] = "<";
array2[0] = "v", array2[1] = "/", array2[2] = "^", array2[3] = "\\";
cin>>n;
for(int i = 1; i <= n; i++){
if (i%2 != 0){
for(int j = 0; j <=n; j++){
cout << array1[j];
}
cout<<"\n";
} else if (i%2 != 0) {
for(int j = 0; j <=n; j++){
cout << array2[j];
}
cout<<"\n";
}
return 0;
}
}
I dont know if array is necessary or not.
If you guys have any suggestion about my program feel free to give me some.
This is my first time asking in this web and im sorry if my post and english are terrible
Thanks in advance:)
We are here to help.
I will first show you the problems in your code and then make a proposal on how to make it better.
So, let us first check your code:
#include<bits/stdc++.h> is a non C++ compliant compiler extension. It should never be used. On my machine, it does not compile.
using namespace std; should not be used. It is better to always use full qualified names. This will avoid name clashes from different scopes or namespaces
Variables should have meaningful names. One character variables are in most cases not that good
All variables should be initialized during definition
C-Style arrays should not be used in C++. Always use a specialized STL container like std::vector or std::array
In C++ we use std::string for strings and not char[] or char *
Array indices in C/C++ start with 0. If you use <= in the end condition of a for loop, you will access an element one past the end. This is a severe out of bound error. You do that in you for loop with the 'j'
There is anyway a severe out of bound bug here. You access array[j] and j might be 4 or bigger. That is a bug and must be corrected. You can simply do a modulo devision % by 4. Then you do never exceed the 4. it will then always be 0,1,2,3,0,1,2,3,0,1,2,3 . . .
You should write as much as possible comments
If we correct all this findings, then we could come up with:
#include <array>
#include <iostream>
constexpr size_t NumberOfLinePatterns = 2;
constexpr size_t NumberOfElementsPerLinePattern = 4;
using Pattern = std::array<std::array<char, NumberOfElementsPerLinePattern>, NumberOfLinePatterns>;
// If you do not yet know the std::array. Then uncomment the following and
// remove on opening and closing curly brace in the initialization below
// using Pattern = char[NumberOfLinePatterns][NumberOfElementsPerLinePattern];
Pattern pattern{{
{'O','>','X','<'},
{'v','/','^','\\'}
}};
int main() {
// Get number of rows and columns to print
unsigned int numberOfElements{}; std::cin >> numberOfElements;
// Now, for all rows and columns
for (unsigned int row{}; row < numberOfElements; ++row) {
for (unsigned int column{}; column < numberOfElements; ++column) {
// Print the selected character
std::cout << pattern[row % NumberOfLinePatterns][column % NumberOfElementsPerLinePattern];
}
std::cout << '\n';
}
return 0;
}

My array is gettting an error because it's being defined as a singular integer

The point of this program is to output whether a series of digits (the number of digits undefined) is sorted or not (largest to smallest or smallest to largest).
I have defined my array in my function parameter, and I am trying to use a for loop to store the user's input, as long as it is above 0, in said array.
However, I am getting the error argument of type int is incompatible with parameter of type int*.
The exact error is the argument of type int is incompatible with parameter of type int*.
It is referring to line 22 and 23, these two;
isSorted(list[2000]); and
bool is = isSorted(list[2000]);.
I know this means my for loop is assigning a single value to my variable repeatedly from reading similar questions however I can not figure out how to fix this.
#include <iostream>
using namespace std;
bool isSorted(int list[]);
int main()
{
int i;
int list[2000];
int k = 0;
for (i = 0; i < 2000; i++)
{
int j;
while (j > 0)
{
cin >> j;
list[i] = j;
}
}
isSorted(list[2000]);
bool is = isSorted(list[2000]);
if (is == true)
cout << "sorted";
else
cout << "unsorted";
return 0;
}
bool isSorted(int list[])
{
int i = 0;
for (i = 0; i < 2000; i++)
{
if (list[i] > list[i + 1] || list[i] < list[i - 1])
{
return false;
}
else
return true;
}
}
I removed unused variable k.
Made 2000 parameterized (and set to 5 for testing).
In isSorted you are not allowed to return
true in the else as if your first element test would end in else you would return true immediately not testing other elements. But those later elements can be unsorted as well.
In isSorted you are not allowed to run the loop as for(i = 0; i < 2000; i++), because you add inside the for loop 1 to i and end up querying for i == 1999 list[2000], which is element number 2001 and not inside your array. This is correct instead: for (i = 0; i < 1999; i++). You also do not need to check into both directions.
You cannot call isSorted(list[2000]) as this would call is sorted with an int and not an int array as parameter.
You write int j without initializing it and then query while j > 0 before you cin << j. This is undefined behaviour, while most likely j will be zero, there is no guarantee. But most likely you never enter the while loop and never do cin
I renamed the isSorted as you just check in your example for ascending order. If you want to check for descending order you are welcome to train your programming skills and implementing this yourself.
Here is the code with the fixes:
#include <iostream>
using namespace std;
bool isSortedInAscendingOrder(int list[]);
const int size = 5; // Set this to 2000 again if you want
int main()
{
int i;
int list[size];
for (i = 0; i < size; i++)
{
int j = 0;
while(j <= 0)
{
cin >> j;
if(j <= 0)
cout << "rejected as equal or smaller zero" << endl;
}
list[i] = j;
}
if (isSortedInAscendingOrder(list))
cout << "sorted" << endl;
else
cout << "unsorted" << endl;
return 0;
}
bool isSortedInAscendingOrder(int list[])
{
for (int i = 0; i < size -1; i++)
{
if (list[i] > list[i + 1])
{
return false;
}
}
return true;
}
This is a definition of an array of 2000 integers.
int list[2000];
This is reading the 2000th entry in that array and undefined, because the highest legal index to access is 1999. Remember that the first legal index is 0.
list[2000]
So yes, from point of view of the compiler, the following only gives a single integer on top of being undefined behaviour (i.e. "evil").
isSorted(list[2000]);
You probably should change to this, in order to fix the immediate problem - and get quite close to what you probably want. It names the whole array as parameter. It will decay to a pointer to int (among other things loosing the information of size, but you hardcoded that inside the function; better change that by the way).
isSorted(list);
Delete the ignored first occurence (the one alone on a line), keep the second (the one assigning to a bool variable).
On the other hand, the logic of a your sorting check is flawed, it will often access outside the array, for indexes 0 and 1999. I.e. at the start and end of your loop. You need to loop over slightly less than the whole array and only use one of the two conditions.
I.e. do
for (i = 1; i < 2000; i++)
{
if (list[i] < list[i - 1])
/* ... */
The logic for checking ascending or descending sorting would have to be more complex. The question is not asking to fix that logic, so I stick with fixing the issues according to the original version (which did not mention two-way-sorting).
You actually did not ask about fixing the logic for that. But here is a hint:
Either use two loops, which you can break from as soon as you find a conflict, but do not return from the fuction immediatly.
Or use one loop and keep a flag of whether ascending or descending order has been broken. Then return true if either flag is still clear (or both, in case of all identical values) or return false if both are set.

What can I use to stop a loop instead of 'return 0'?

so I made a simple loop that finds out if an array has the elements with the values of 0 and 1.
if the loop indeed finds 0 or 1 inside of the array, it will say "YES", otherwise "NO".
yes, the program works just fine, but at the end of the program it prints out "YES" or "NO" as many times as i put cin>>dim to.
for example if dim which means (dimension[of the array]) is 5 it's going to print either "YESYESYESYESYES" or "NONONONONO"
I have to use return 0 in order to make it print it out like once, but I feel like this is not the right way to do it. Please help me with this. thanks!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, dim, v[100];
cin>>dim;
for(i=0;i<dim;i++)
cin>>v[i];
for(i=0;i<dim;i++)
if(v[i]==0 || v[i]==1){
cout<<"YES"; return 0;}
else{
cout<<"NO"; return 0;}
return 0;
}
The break statement can be used to break out of loops. The example from cppreference:
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 5; k++) { //only this loop is affected by break
if (k == 2) break;
std::cout << j << k << " ";
}
}
As the comment suggests, break only breaks the innermost loop.
In your code you always exit from the loop on the very first iteration, hence you do not need the loop in the first place. This will have the same output as your code:
int main() {
int i, dim, v[100];
cin >> dim;
for(i=0; i < dim; i++)
cin >> v[i];
if(v[0] == 0 || v[0] == 1) {
cout << "YES";
} else {
cout << "NO";
}
}
After reading the question again...
I made a simple loop that finds out if an array has the elements with the values of 0 and 1
If you exit the loop after checking the first element then you only check the first element. If you want to see if an array contains only 1 or 0 or it contains at least one element which is 0 or 1 (not 100% clear which one you want), then you rather need this:
bool only_zero_or_one = true;
bool one_zero_or_one = false;
for (int i = 0; i < dim; ++i) {
zero_or_one = ( v[i] == 0 | v[i] == 1);
only_zero_or_one = zero_or_one && only_zero_or_one;
one_zero_or_one = zero_or_one || one_zero_or_one;
}
Only for one_zero_or_one you can break the loop once zero_or_one == true.
Moreover, you should rather use a std::vector. In your code, if the user enters a dim which is greater than 100 you write beyond the bounds of v. This can be avoided easily:
size_t dim;
std::cin >> dim;
// construct vector with dim elements
std::vector v(dim);
// read elements
for (size_t i=0; i < v.size(); ++i) std::cin >> v[i];
// .. or use range based for loop
for (auto& e : v) std::cin >> e;
but I feel like this is not the right way to do it
Returning is an entirely right way to break out from a loop.
Another right way is the break statement, which jumps to after the loop.
Even better, you can actually check if v[i]==0 or 1 inside the input for loop immediately after taking input and set a flag to true. Depending on requirement, you can either break or wait until the entire input is read and then come out and check for flag==true and then print "YES" and print "NO" if flag==false.
This will save you running the loop again to check for 0 or 1.

C++ Printing Odd numbers instead of Prime Numbers

I have been working on an assignment question for days and cannot seem to get the correct output (I've tried so many things!) The question is:
Write a program that uses two nested for loops and the modulus operator (%) to detect and print the prime numbers from 1 to 10,000.
I have been doing from 1 to 10 as a small test to ensure its working. I am getting 2,3,5,7,9 as my output, so I know something is wrong. When I increase the number from 10 to 20 it is printing 2 plus all odd numbers. I am including my code below. Thanks!!
int main() {
for (int i=2; i <=10; i++){
for (int j=2; j<=i; j++){
if (i%j==0 && j!=i) {
break;
}
else {
cout<< i <<endl;
break;
}
}
}
}
In addition to Sumit Jindal's answer inner for loop can be done by this way as well:
for(int j=2; j*j<=i ; j++)
If we think about every (x,y) ordered pair that satisfies x*y = i, maximum value of x can be square root of i.
The problem lies in the if-else branch. Your inner loop will be run exactly once because it will break out of the inner loop as a result of your if else branch.
When you first enter the inner loop the value of j is 2. Your condition will test if variable i is divisible by 2. If it is it breaks. Other wise (your else branch) will print the value of i and breaks out.
Hence printing odd numbers.
Break out of the inner loop and check whether j equals i in outer loop. You have to make j available for outer loop.
Your print statement is within the inner loop, and it should not be - it's only a prime if you run all the way through the inner loop without finding a divisor.
As a second point, you only need to check for divisors up to the square root of i, not all the way up to i.
You are breaking the inner loop after the first iteration itself, which is checking if the number(ie i) is different from j and is divisible by 2 or not (since j=2 for the first iteration)
I am getting 2,3,5,7,9 as my output
This is because every odd number fails the if and is printed in else condition
A minor correction in your code, adding a flag. Also you don't need to run the inner loop i times, infact only i/2 times is sufficient. This is simple mathematics, but will save significant number of CPU cycles (~5000 iterations lesser in your case)
#include <iostream>
int main()
{
int n = 10;
for(int i=2; i<=n; i++){
bool isPrime = true;
for(int j=2; j<=i/2; j++){
if(i!=j && i%j==0){
isPrime = false;
break;
}
}
if(isPrime)
std::cout << i << " ";
}
return 0;
}
Another version, if you don't mind output in reverse order.
int n = 10;
for (int i = n; i > 1; --i)
{
int factorCount = 0;
for (int j = 2; j <= n; ++j)
{
if (i % j == 0)
factorCount++;
if (factorCount > 1)
break;
}
if (factorCount == 1)
cout << i << endl;
}
int main() {
for (int i = 2; i <= 100; i++) {
for (int j = 2; j < i; j++) {
if (i%j == 0)
break;
if (j==i-1) // means has never run previous if blog
cout << i << endl;
}
}
return 0;
}

Sieve of Eratosthenes C++ code

I'm fairly new to programming, and I just started C++
I found this problem, which involved generation all prime numbers upto "n". This is my code, where I've assumed "n" to be 10. I've tried my best. I'd really appreciate it if you guys could tell me what's wrong.
The for loop that's in a separate blockquote is repeating indefinitely, that means the value of i isn't being updated. I used a cout statement to print the value, it's either 0 or 1. Why is this happening? Is there a fault in the logic?
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int NumList[10], flag[10];
int i,j;
for(i = 0; i<10; i++) //Generate a list of numbers from 1 to 10
NumList[i] = i+1;
for(i = 0; i<10; i++) // Create a flag array, initialized to 1
flag[i] = 1;
for(i=1; i<10; i++)
{
if(NumList[i]%2==0) // Mark all even numbers in the list
flag[i] = 0; // since they're not prime
}
for(i = 2; i<10; i++) //Start from 3
{
if(flag[i]==1) // Check which numbers are left over
{
for(j = NumList[i]-1;j<10; ) //Since index = value-1 in this case
{
j+= NumList[i]; //Keep incrementing by value and marking in flag[]
flag[j] = 0;
}
}
}
}
The code is looping infinitely because you have accessed out of bounds in the following loop
for(j = NumList[i] - 1; j<10; )
{
j += NumList[i];
flag[j] = 0;
}
given that Numlist[i] is 3 when i = 2 in your outer loop, and j starts of as 2 in your inner loop, the following happens:
j takes value 2+3, flag[5] is assigned the value 0, current loop ends check 5 < 10
j takes value 5+3, flag[8] is assigned the value 0, current loop ends check 8 < 10
j takes value 8+3, flag[11] is assigned the value 0, current loop ends check 11 < 10
Once the third loop has finished (having modified flag[11]) all bets are off with respect to what will happen next. Indeed it is plausible that you are clobbering some other variable you have defined which is living at the address referenced by flag[11].
As for making this problem going away, with least disturbance to your current logic (whatever it is - it doesn't look correct) you can just increase the size of the flags array.