Second FOR loop is being skipped - c++

I am not getting any compile-time errors, but whenever i run the program the second FOR loop gets skipped and the program stops. i put a cout after it and that executed, but the second for loop was still skipped.
#include <iostream>
using std::cout;
int main()
{
int numbers[5];
for(int i; i < 5; i++)
{
std::cin >> numbers[i];
}
for(int i; i < 5; i++)
{
cout << numbers[i] << "\t";
}
}

When you write
int i;
That declares an int named i without initializing it. Its value is said to be indeterminate. There is not much you can do with an indeterminate value, for example
int x = i;
invokes undefined behavior. When your code has ub then almost anything can happen. You could get no output at all, or some gibberish, or Hamlet printed on the screen (though this happens rarely).
You are not initializing the counter in both loops. That the first one appears to work is purely a matter of luck. Or rather bad luck, because appearing to work is the worst incarnation of wrong code.
Many guidelines suggest to initialize variables as soon as you declare them. Often this is put another way: Only declare a variable when you can initialize it. In any case, seeing int i; should make you shiver in fear ;).
Your loops should look like this:
for(int i=0; i < 5; i++)
{
std::cin >> numbers[i];
}
for(int i=0; i < 5; i++)
{
std::cout << numbers[i] << "\t";
}
On the other hand, if you want to iterate the whole container you can use a range based for loop which eliminates the chance for such mistake completely:
for(auto& n : numbers)
{
std::cin >> n;
}
for(const auto& n : numbers)
{
std::cout << n << "\t";
}
Note that use of initialized variables can be diagnosed by most compilers. With -Wall -Werror clang refuses to compile your code. Unfortunatly gcc fails to diagnose the issue in your code (while it quite reliably can diagnose cases such as int i; int x = i;). Hence, you should pay attention to warnings, and to make sure you cannot miss them you can treat them as errors.

In both of the for loops, try replacing int i; with int i = 0;.

From wikipedia: Unintialized variable in C
A common assumption made by novice programmers is that all variables are set to a known value, such as zero, when they are declared. While this is true for many languages, it is not true for all of them, and so the potential for error is there
In C++/C when you don't initialize a variable, it gets the current value from memory or variable stack, you can't expect a especific value.
It's considered a good practice to always initialize variables in C/C++. So just change your code to:
for(int i = 0; i < 5; i++) for both loops and it will works.
Extra
Your IDE should warn you about unitialized variables, check plugins like cppcheck or any kind of linter for c/c++

Related

Naive reverse string iteration infinite loop and/or assertion failure C++ / Visual Studio 2022

I am trying to reverse iterate through a string, but am getting assertion failure for the [] operator in the latest VS.
int foo() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
std::cout << s[i] << std::endl;
}
return 0;
}
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop:
int foo2() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
//std::cout << s[i] << std::endl;
}
return 0;
}
Iterating forwards works just fine with or without anything in the for loop:
int bar() {
std::string s = "s";
for (int i = 0; i < s.size(); i++) {
std::cout << s[i] << std::endl;
}
return 0;
}
I am using the C++14 standard and the same code used to work on other compilers/older versions of VS. The same problem exists for any string size (although that should be irrelevant). I understand I could modify the code to use and dereference pointer instead of using int, but want to understand why this doesn't work anymore, why is it unsafe or incorrect, or what else am I missing. Thanks!
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop
s.size() is an unsigned long so it can never be less than 0. The behavior of narrowing conversion due to assignment of unsigned long to int is implementation defined behavior though it should not be a problem when assigning unsigned long value 0 to int, at least I wouldn't think so, but who knows, MSVC does have its quirks.
It appears the compiler is smart enough to predict that there cannot be an infinite loop when this particular body of the for loop is present, which leads me to believe that an exception may be thrown when accessing the array, perhaps out of bounds access.
Using the debugger to track the value of i is your best bet to understand what is going on.
The issue was in fact originally caused by "auto" i rather than "int" i, but not properly refreshed. Auto gave i an unsigned int type, which overflowed the [] operator, or caused infinite loop turning over from zero to 18446744073709551615 once the i = 0 cycle completes and i-- is executed.
Thank you everyone for the helpful replies!
Could it be that your int defaults to being unsigned and therefore decrementing when i=0 resuts in a high value ?
As #PeteBecker mentioned, int should be signed and should not overflow. However my guess is that your actual code does not use int.

why is the sort() changing my input array?

i am stuck on a problem where, after taking input of an array and sorting it and not doing any operation on it at all, the output shows a different array?
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long int c[n],h[n],a[n];
for(int i=0;i<n;i++){
cin>>c[i];
}
for(int i=0;i<n;i++){
cin>>h[i];
}
sort(h,h+n);
for(int i=0;i<n;i++){
a[i]=0;
}
int i=0;
int begin=(i+1)-c[i];
int end = (i+1)+c[i];
int j=begin;
while(i<n){
a[j-1]++;
j++;
if(j>end){
i++;
begin=(i+1)-c[i];
end= (i+1)+c[i];
j=begin;
}
}
sort(a,a+n);
for(int i=0;i<n;i++){
cout<<h[i]<<" ";
}
}
return 0;
}
input for h[]={8,8,8,8,8}..n=5
output h[]={10,10,9,9,8}
Here is a version of your code written in reasonably decent C++. I didn't touch the loop in the middle because I have no clue what it's doing. You're using obscure variable names and no comments and doing all kinds of bizarre things with indexes and mixing them up with user input.
Now, reading indexes from user input and using them isn't bad, though in a real program you'd want to be doing lots of bounds checking on that input to make sure people weren't feeding you bad data. But doing all that stuff with such poorly named variables with no explanation is going to leave anybody looking at it scratching their head. Don't do that.
Also, avoid the use of begin and end as variable names, especially if they hold indexes. In most cases it will confuse things terribly as begin and end are important identifiers in the standard library and always refer to iterators, which are sort of like indexes, but most definitely not indexes, adding greatly to the confusion. beginidx and endidx could be acceptable substitutes in this case.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using ::std::vector;
using ::std::sort;
using ::std::copy_n;
using ::std::copy;
using ::std::fill;
using ::std::istream_iterator;
using ::std::ostream_iterator;
using ::std::cin;
using ::std::cout;
int main() {
// your code goes here
using vec_el_t = long long int;
int t;
cin >> t;
while (t--) {
int const n = []() { int n; cin >> n; return n; }();
vector<vec_el_t> c{n}, h{n}, a{n};
copy_n(istream_iterator<vec_el_t>{cin}, n, c.begin());
copy_n(istream_iterator<vec_el_t>{cin}, n, h.begin());
// Suggested debugging code:
// cout << "h before sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
sort(h.begin(), h.end());
// Suggested debugging code:
// cout << "h after sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
fill(a.begin(), a.end(), 0);
// Weird, unexplained algorithm begins here
int i = 0;
int begin = (i + 1) - c[i];
int end = (i + 1) + c[i];
int j = begin;
while (i < n) {
a[j - 1]++;
j++;
if (j > end){
i++;
begin = (i + 1) - c[i];
end = (i + 1) + c[i];
j = begin;
}
}
// Weird unexplained algorithm ends here
sort(a.begin(), a.end());
copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
}
return 0;
}
Changes made... Use vector not a variable length array, which isn't valid C++ anyway and will only work in g++ and clang. Don't use explicit loops if there is an algorithm that will do the job. Try to make as many things const as you can so you can make sure that the compiler catches it if you try to change things you didn't mean to change. Avoid using std; and if you want to import names from ::std import exactly the ones you need. Don't use compiler or library implementation specific header files and use the ones from the standard instead (i.e. no bits/stdc++.h).
As for your problem, I have no idea. I suspect that the index manipulation combined with looping isn't doing what you expect. If you print out the arrays before and after sorting, you will discover that sort only alters order, and not content.
As a general rule, always suspect your own code first and make absolutely sure it's correct. And if you really think it's the library code, prove it beyond a shadow of a doubt before coming here to ask why the library isn't doing what it says it does.
The complicated code I didn't touch looks rife with opportunities for out-of-bounds access, and that results in undefined behavior, which means your program might do absolutely anything in that case. You might change uses of operator [] with calls to the at function (one of the many perks of using vector) instead. That way, attempts at out-of-bounds access will throw an exception.
Within these lines you are accessing a outside its limits:
int i=0;
int begin=(i+1)-c[i]; // begin = 1 - c[0]; <<-- this could be arbitrarily small!
int end = (i+1)+c[i]; // unrelated
int j=begin; // also equal to 1-c[0]
while(i<n){
a[j-1]++; // increment a[-c[0]] which is UB unless c[0]==0
This means undefined behavior (UB), i.e., it could do nothing, it could segfault, or (what apparently happened in your case) access elements of an adjacent data structure.

Uninitialized local variable 'lc' used but I initialized it

I wanted to check whether what I wrote on the programming exam was working at least. And it turned out that it was not. And I do not understand why EXACTLY it does not work.
The task was to write a program with boolean function which should return true state if 2d matrix has only one row which consist entirely of negative element.
Here is the code:
#include "stdafx.h"
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
bool cns();
const int n=5;
int a[n][n];
bool cns() {
int ts;
//!!!!
int lc; //!! I have initiated lc variable but still it does not work !!
//!!!
//standard 2d static quad matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << "a[" << i << "][" << j << "]=" << endl;
cin >> a[i][j];
}
}
//check whether the sum of elements of the row is negative or not
for (int i = 0; i < n; i++) {
ts = 0; //temp sum
for (int j = 0; j < n; j++) {
ts += a[i][j]; //I thought what if sum of elements is negative then the whole row is negative too
if (ts < 0) { //I have just realized that is wrong
lc++; //counter of negative lines, which consist entirely of negative elements
}
}
}
//only one row should be whole negative
if (lc == 1) {
return true;
}
else {
return false;
}
}
int main()
{
int lc;
cout << cns << endl;
return 0;
}
So could you tell me please where I did mistake with variable 'lc' and why compiler tells me "uninitialized local variable 'lc' used"?
You haven't initialized lc, but declared it.
To initialize a variable means giving it an initial value (which you should always do):
int lc = 0;
Initialising a variable is, essentially, giving it an initial value.
Your definition of lc
int lc;
does not initialise it. Since it is a variable of automatic storage duration (i.e. it is local to a block), it is not initialised.
Accessing its value therefore gives undefined behaviour.
The first thing that the code does with lc (within the first set of loops in your code) is
lc++;
Incrementing a variable of type int requires accessing its value, before producing an effect (doing the act of incrementing). Hence undefined behaviour.
The compiler warning is being issued because of that. To eliminate the warning, either initialise it where it is defined. For example;
int lc = 42;
or ensure the first operation is to set it to a valid value
int lc;
// later on the first thing ever done to lc is ...
lc = 47;
People often assume that all variables (of basic types, like int) which are defined without being explicitly initialised will have an initial value of 0 (zero). That is true in some other languages, but not in C++ - at least not in this context (an int of static storage duration IS zero-initialised).
Initialization is not what you have done here. As stated by amc176 you have only declared it.
When you declare variable lc, memory is reserved on the stack. The amount of memory reserved depends on the data type (a char will take up more memory than an int).
However, if you do not provide an initial value for that variable (i.e. initialize it) the initial value of the data type will be exactly what was present in that specific piece of memory. That is why your compiler is complaining.

creating mxn 2D array in c++ without using any external library

I am a beginner to C++ syntax. Now, I need to create an mxn 2D array in C++ to use it in another project. I have looked at other answers which involve using tools like vector, etc. Many tools are not working on my Visual Studio 15 i.e. for vector I can not define with std::vector without a message like vector is not in std. So, I have wrote the following code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int i; int j; int row[5][10] = {};
for (int j = 0; j < 10;)
for (int i = 0; i < 5;)
{
row[i][j] = 500;
int printf(row[i][j]);
i++;
j++;
cout << "Array:" << row[i][j] << endl;
}
return 0;
}
Surely, this is not the correct syntax. So the output is beyond my expectation. I want to create an m*n array with all the elements being the same integer; 500 in this case. That is, if m=3, n=2, I should get
500 500 500
500 500 500
There's a couple things wrong with your current code.
The first for loop is missing curly brackets
You're redefining int i and int j in your for loop. Not a complilation issue but still an issue.
You're using printf incorrectly. printf is used to output strings to the console. The correct line would be printf("%d", row[i][j]);
If you want to use a vector, you have to include it using #include <vector>. You can use a vector very similar to an array, but you don't have to worry about size.
You seem to be learning. So, I did minimal correctios to make it work. I suggest you to make modifications as per your needs.
#include <iostream>
using namespace std;
int main()
{
int row[5][10] = {};
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 5; i++) {
row[i][j] = 500;
cout << row[i][j] << " ";
}
cout << endl;
}
return 0;
}
Care and feeding of std::vector using OP's program as an example.
#include <iostream>
#include <vector> // needed to get the code that makes the vector work
int main()
{
int m, n; // declare m and n to hold the dimensions of the vector
if (std::cin >> m >> n) // get m and n from user
{ // m and n are good we can continue. Well sort of good. The user could
// type insane numbers that will explode the vector, but at least they
// are numbers.
// Always test ALL user input before you use it. Users are malicious
// and incompetent <expletive delteted>s, so never trust them.
// That said, input validation is a long topic and out of scope for this
// answer, so I'm going to let trapping bad numbers pass in the interests
// of keeping it simple
// declare row as a vector of vectors
std::vector<std::vector<int>> row(m, std::vector<int> (n, 500));
// breaking this down:
// std::vector<std::vector<int>> row
// row is a vector of vectors of ints
// row(m, std::vector<int> (n, 500));
// row's outer vector is m std::vector<int>s constructed with
// n ints all set to 500
for (int j = 0; j < n; j++) // note: j++ has been moved here. This is
// exactly what the third part of a for
// statement is for. Less surprises for
// everyone this way
// note to purists. I'm ignoring the possible advantages of ++j because
// explaining them would muddy the answer.
// Another note: This will output the transverse of row because of the
// ordering of i and j;
{
for (int i = 0; i < m; i++) // ditto I++ here
{
// there is no need to assign anything here. The vector did
// it for us
std::cout << " " << row[i][j]; // moved the line ending so that
// the line isn't ended with
// every column
}
std::cout << '\n'; // end the line on the end of a row
// Note: I also changed the type of line ending. endl ends the line
// AND writes the contents of the output stream to whatever media
// the stream represents (in this case the console) rather than
// buffering the stream and writing at a more opportune time. Too
// much endl can be a performance killer, so use it sparingly and
// almost certainly not in a loop
}
std::cout << std::endl; // ending the line again to demonstrate a better
// placement of endl. The stream is only forced
// to flush once, right at the end of the
// program
// even this may be redundant as the stream will
// flush when the program exits, assuming the
// program does not crash on exit.
}
else
{ // let the use know the input was not accepted. Prompt feedback is good
// otherwise the user may assume everything worked, or in the case of a
// long program, assume that it crashed or is misbehaving and terminate
// the program.
std::cout << "Bad input. Program exiting" << std::endl;
}
return 0;
}
One performance note a vector of vectors does not provide one long block of memory. It provides M+1 blocks of memory that may be anywhere in storage. Normally when a modern CPU reads a value from memory, it also reads values around it off the assumption that if you want the item at location X, you'll probably want the value at location X+1 shortly after. This allows the CPU to load up, "cache", many values at once. This doesn't work if you have to jump around through memory. This means the CPU may find itself spending more time retrieving parts of a vector of vectors than it does processing a vector of vectors. The typical solution is to fake a 2D data structure with a 1D structure and perform the 2D to 1D mapping yourself.
So:
std::vector<int> row(m*n, 500);
Much nicer looking, yes? Access looks a bit uglier, though
std::cout << " " << row[i * n + j];
Fun thing is, the work done behind the scenes converting row[j][i] to a memory address is almost identical to row[j*n+i] so even though you show more work, it doesn't take any longer. Add to this the benefits you get from the CPU successfully predicting and reading ahead and your program is often vastly faster.

segmentation fault when calling a function

Segmentation fault when calling the Update_Multiplier and gdb debugger shows these:
Program received signal SIGSEGV, Segmentation fault.
0x080b74e8 in Update_Multiplier() ()
double upperbound = 116325;
double objective = 1.1707e+07;
int main()
{
Update_Multiplier();
}
void Update_Multiplier()
{
cout << "function 0" << endl;
// Determine subgradient vectors
double gra[1000][1000];
double grb[1000][1000];
double dumX = 0;
double stepsize[1000][1000];
double tuning=2;
double LRADum[1000][1000];
double LRBDum[1000][1000];
cout << "function 1" << endl;
// update subgradient vectors
for (int i=1; i<=noOfNodes; i++)
{
for (int j=1; j<=noOfNodes; j++)
{
if (C[i][j] != 0)
{
dumX=0;
for (int p=1; p<=noOfCommodity; p++)
{
dumX += X[i][j][p];
}
gra[i][j]=dumX-U[i][j]*Y[i][j]-Q[i][j];
grb[i][j]=Q[i][j]-B[i][j]*Y[i][j];
}
}
}
// update stepsize
cout << "function 2" << endl;
for (int i=1; i<=noOfNodes; i++)
{
for (int j=1; j<=noOfNodes; j++)
{
if (C[i][j] != 0)
{
stepsize[i][j]=(tuning*(UpperBound-Objective))/sqrt((gra[i][j]*gra[i][j])*(grb[i][j]*grb[i][j]));
LRADum[i][j]=LRA[i][j]+stepsize[i][j]*gra[i][j];
LRA[i][j]=LRADum[i][j];
LRBDum[i][j]=LRB[i][j]+stepsize[i][j]*grb[i][j];
LRB[i][j]=LRBDum[i][j];
}
}
}
}
I see two suspicious things in your code.
First, you are taking too much stack space (about ~40 MB).
Second, you are starting the index of the array at 1, where it should be 0:
for (int i=1; i<=noOfNodes; i++)
Change it to:
for (int i=0; i<noOfNodes; i++)
At a guess, you have a stack overflow! You cannot reliably create gigantic arrays on the stack. You need to create them dynamically or statically.
Where did you define noOfNodes? What is the initial value of this? Or, do you read this in from the console? If this is uninitialized, it probably has junk data -- which may or may not explain the crash.
You need a stack of at least 40 megabytes to run this function because you're allocating five arrays of one million eight-byte doubles each.
Change the function to allocate the double arrays from the heap using new.
You should really give us the whole code, e.g. noOfNodes is not defined anywhere.
Just a stab in the dark: are you possibly overflowing C since your indices (i and j) go from 1 to noOfNodes?
First, what Neil said is true.
Second, C and C++ arrays start from index zero. If you declare
int a[100]; // 100 elements, from zeroth to ninety-ninth.
Then its elements are a[0], a[1] ... a[99].
I can not see anything wrong with this code as given, BUT: You might have an off-by-one error if noOfNodes is 1000.
Remember that Arrays are 0-indexed so you have to access indexes 0 - 999 instead of 1 - 1000 as you are doing
me too i have this problem and my function returned std::string now i just do reference an dreturn type void like that:
void readOnDicoFile(std::ifstream file/*If you have "using namespace std;" instruction, put ifstream, not std::ifstream (you can put both)*/)
and before:
std::string readOnDicoFile(std::string fileName/*If you have "using namespace std;" instruction, put ifstream, not std::ifstream (you can put both)*/)