Strange result of displaying array using increment/decrement operator in C++ - c++

#include <iostream>
using namespace std;
int main()
{
double donation[10];
int index = 0;
cout.setf(ios::fixed);
cout << "Enter sum of money for donating: ";
while (index < 10 && cin >> donation[index])
{
cout << "donation #" << 1 + index++ << ": " << donation[index] << endl;
}
return 0;
}
Result
That code couldn't display right value of donation...
I could check the mistake is '1 + index++', but I don't know why did.
Why my code using '1 + index++' has a difference with code when I use 'index++' in the next line.

Keep to the idiomatic way instead of trying to understand stranger constructions and also mixing increments with function/operator parameters should be avoided (see sequence points):
for (int index = 0; index < 10; ++index)
{
if (! std::cin >> donation[index])
break;
std::cout << "donation #" << (1 + index) << ": " << donation[index] << std::endl;
}
This should do what is expected and should be understood with some knowledge of C++. It runs at most 10 times, tries to fill input to the array and displays when the input works or stops when the input fails. The only issue would be better validation of the user input.

Related

#include <cmath> stopped working in C++20?

Summarize the problem:
My goal is to generate odd numbers up to a limit, store them in a vector then output the square of them.
Describe what you've tried:
So far, I used the #include < cmath > at the start before int main(), then I used a couple of if statements to check whether the limit is zero, if so I output an error message. If the limit is >0 then I squared the odd numbers using pow(num,2) however, this does not work and gives wrong answer. For example, it gives the square of 13 as 600ish, that is obviously wrong. Please give advice. My full code is here, it is very simple so I did not put much comments in there:
#include<iostream>
#include<format>
#include<cmath>
#include<vector>
using namespace std;
int main()
{
int limit{};
cout << "Enter a limit of odd integers: \n";
cin >> limit;
vector<int>oddnumb(limit);
if (limit == 0)
{
cout << "You MUST enter a number>0, then restart the program. \n";
return 0;
}
if (limit > 0)
{
cout << "Odd numbers are as follows: \n";
for (size_t i{}; i < limit-1; ++i)
{
oddnumb[i] += ++i;
cout << oddnumb[i] << endl;
}
cout << "Squared odd numbers follow: \n";
for (size_t i{}; i < limit - 1; ++i)
{
oddnumb[i] += ++i;
cout << pow(oddnumb[i],2) << endl;
}
}
I've written up a working version of what you want to do. I urge you to figure it out yourself first, that's the best way to learn, and then check your version against what I've got here. Note that this is certainly not the best way to do it. But I wrote it in a way that should be easy to understand. In programming there are lots of ways to tackle any problem, the best way is arguably... the way that works! Good luck in your journey with C++!
#include <cmath>
#include <iostream>
#include <vector>
int main()
{
double input{};
while (input < 1)//validate that input is greater than 0 here by looping if it isn't
{
std::cout << "Enter a limit of odd integers: ";
std::cin >> input;
if (input < 1)//if a valid range is entered this is never shown
{
std::cout << "Enter a valid range. Greater than 0. \n\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
std::vector<double> oddNumbers{};
std::cout << "Odd numbers:\n";
//notice we're starting this loop at 1, since 0 is even we just avoid it
for (double i = 1.0; i <= input; i += 2.0) //you can add more than just 1 to i
{
oddNumbers.push_back(i);// here we're putting the value of i at the back of the vector
std::cout << i << " squared is " << pow(i, 2.0) << '\n';
//we could avoid using a vector by printing the squared value of i within this loop
}
std::cout << "Squared Odd Numbers:\n";
//we do need to start this loop at 0 to access the first element of the vector
for (unsigned int i = 0; i < oddNumbers.size(); i++)
//we also increase i by just one each time to access each element we stored
{
std::cout << pow(oddNumbers[i], 2.0) << '\n';
}
return 0;
}

c++ Question with displaying text between two array variables

I always seem to have this problem when I want to display two variables of an array in one iteration of a loop, I'm wondering if there is a nicer way of displaying the array.
The code works if I change ++i to i+1 but I'm wondering why that happens, and I'm wondering if there's a smarter way to do what I want. The error says unsequenced modification and access to 'i' [-Wunsequenced]
#include <iostream>
#include <memory>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int players = 0,rounds=0;
bool winnerFound=false;
cout << "Welcome to my tournament match maker\n";
cout << "Enter the number of participants in the tournament: ";
cin >> players;
rounds=players/2;
string *pNames = new string[players]; //dynamically allocate
for (int i = 0;i < players;i++)
{
cout << "Enter the name of player " << i + 1<<":";
cin >> pNames[i];
}
random_shuffle(&pNames[0],&pNames[players]);
for(int i=0;i<rounds;i++)
{
cout<<pNames[i]<<" vs "<<pNames[++i]; //
}
return 0;
}
I'm not sure if that's the best way to do it, any tips would be appreciated.
For the tips, I think it is better to use a STL container instead of a raw array. std::array or std::vector for example. You can change the declaration of pNames as follows:
std::vector <std::string> pNames(players);
Your problem is that you iterate only until rounds. You don't want that, you want to loop over all players, not only half of them.
To make your code work, you need to write:
for(size_t i = 0; !pNames.empty() && i < pNames.size()-1; ++i)
{
std::cout << pNames[i] << " vs " << pNames[++i] << std::endl;
}
But I think it is a bad way to modify i from inside the loop, you better have to directly increment i by two in the loop statement. This will give:
for(size_t i = 0; !pNames.empty() && i < pNames.size()-1; i+=2)
{
std::cout << pNames[i] << " vs " << pNames[i+1] << std::endl;
}
Of course, if you have only one player or any odd number of players, you will miss the last one (because you need two opponents to make a vs).
I hope it can help.
#include <iostream>
#include <memory>
#include <string>
#include <algorithm>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
int players = 0,count=0;
cout << "Welcome to my tournament match maker\n";
cout << "Enter the number of participants in the tournament: ";
cin >> players;
string *pArray = new string[players]; //dynamically allocate
cin.ignore();
for (int i = 0;i < players;i++)
{
cout << "Enter the name of player " << i + 1<<":";
getline(cin, pArray[i]);
}
random_shuffle(&pArray[0], &pArray[players]);
for (int i = 0;i < players;i++)
{
cout << ++count << ": " << pArray[i] << " vs " << pArray[i + 1] << endl;
i++;
}
return 0;
}
Any critiques?
Firstly i++ and ++i are different.
i++ increments after returning the value and
++i increments before returning the value of the result.
It would be more readable if you incremented your i in the for loop by two and then not have a side effect when asking for the array value. And of course you need to check if i is valid at this point
for(int i=0; i < players-1; i += 2)
{
// check if valid.
// with odd numbers of players, the last remaining player will be dropped.
cout << pNames[i]<<" vs " << pNames[i+1]; // no side effect.
// In a for loop
// all increments should happen in
// the loop header.
}

Nested loops C++

So I am making a program that will create a square based on the users desired size. My code so far reads the value, prints out the top of the square but i'm getting caught up on how to set up the sides because of a nested loop I've created. The issue here is that I need for the loop to reset it's values every time it exists.
Here's my code so far:
#include <iostream>
using namespace std;
int main(int,char**) {
int x;
int z=1;
int l=0;
int n=0;
int q=1;
int m=0;
int o=0;
do{
cout << "Enter length between 0 and 64 (-1 to exit): ";
cin >> x;
if (x>-1&&x<64){
cout << "+";
for (;x-2!=n;++n){
cout << "-";
}
cout << "+" << endl;
}
else{
cout << "Length must be between 0 and 64 inclusive, or enter -1 to exit.";
}
do {
cout << "|";
do {
//cout << " ";
//++m;
//}while (x-2!=m);
cout << "|" << endl;
++o;
}
while (x-2!=o);
++z;
}
while (z!=5);
}
The commented out portion is where the program is getting caught up at, it seems that when I increment m until it exits the do while loop, it holds onto the value that it was incremented to. I know that a continue statement breaks from the loop and begins a new iteration of the loop but it doesn't seem to want to fit inside the do-while loop even if i create an if statement such as
if (x-2==m){
continue;
}
Any help would be appreciated
Just put m = 0; before the loop.
m = 0;
do {
cout << ' ';
++m;
} while (x-2 != m);
Or use a for loop instead;
for (int m = 0; m != x-2; m++) {
cout << ' ';
}
This is the more common idiom for repeating something a certain number of times, since you can see all the conditions related to the loop in a single place.

Why arrays do not print whole table?

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int d,m;
int districts=3;
int months = 12;
double sales[districts][months];
for (d=0 ; d < districts; d++)
{
for(m=0; m< months; m++)
{
cout << "Enter sales for District " << d+1 << ":" << " and Month " << m+1 << ": ";
cin >> sales[districts][months];
}
}
cout << "\n\n\n";
cout << setw(40) << "Months\n";
cout << setw(26) << "1 2 3 4 5 6 7 8 9 10 11 12\n";
for (d=0; d < districts ; d++)
{
cout << "District " << d+1;
for(m=0; m< months; m++)
{
cout << ": " << sales[districts][months];
}
}
return 0;
}
This code after running takes only two input values from user and after that a window appear displaying message a problem caused the program to stop working correctly.
There are no compilation errors and I am unable to find the problem. Is there anyone who can help?
You use variables d and m as counter-variables for your loops, but inside the loops you use the maximum value for both of them (districts and months) instead of d and m.
Change this: cin >> sales[districts][months]; to this: cin >> sales[d][m];
Also, this: cout << ": " << sales[districts][months]; to this: cout << ": " << sales[d][m];.
The term sales[districts][months] refers to a particular element sales[3][12], which also happens to be out of bounds for the 2-d array.
The reading loop is repeatedly reading a value to sales[districts][months], i.e. to sales[3][12], which - since array indexing starts at zero in all dimensions, doesn't exist. That gives undefined behaviour.
The output loops are repeatedly outputting the same value, which also gives undefined behaviour.
A common symptom (but not the only possible one) of undefined behaviour is abnormal program termination - and you are seeing an example of that.
There is also the wrinkle that
int districts=3;
int months = 12;
double sales[districts][months];
involves a variable length array (VLA) which is a feature of C (from the 1999 C standard or later) but is not valid C++. If that construct works for you, your compiler supports a non-standard extension.

Sudoku input program skipping a prompt

I wrote a program for my computer science class that validates and solves sudoku puzzles from .txt files, but I wanted to take it one step further and write a program that made it easy to input and sudoku game. I'm sure you can figure out the format of the files based on this code. My only problem is that the last cin gets skipped, and that option is important to me. Any insight will be appreciated!!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct s {
s();
~s() {/*zzzz*/}
void show_grid();
void set (int &r, int &c, int &v) {g[r][c] = v;}
private:
int g[9][9];
};
//************************************************************************
void s::show_grid() {
//print game out to check it
cout << " | ------------------------------- |" << endl;
for (int k=0; k<81; k++) {
if (k%3 == 0)
cout << " |";
cout << " " << g[k/9][k%9];
if (k%9 == 8) {
cout << " |" << endl;
if ((k/9)%3 == 2)
cout << " | ------------------------------- |" << endl;
}
}
cout << endl;
}
//************************************************************************
s::s() {
//initialize all elements to zero
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
g[i][j] = 0;
}
}
}
//************************************************************************
void create_name (string &name) {
//append .txt extension LIKE IT OR NOT
string ext = name;
ext.erase(ext.begin(), ext.end() - 4);
if (ext.compare(".txt")!=0)
name.append(".txt");
}
//************************************************************************
int main () {
s g;
string name;
string yon("");
int count = 0;
int row, col, val, rcv;
ofstream os;
cout << "Enter game file name: ";
cin >> name;
create_name(name);
//open and do typical checks
os.open(name.c_str());
if (os.fail()) {
cerr << "Could not create " << name << ". Waaaah waaaaaaaaaah...\n\n";
return 0;
}
//useful output (hopefully)
cout << "Enter grid coordinates and value as a 3-digit number,\n"
<< "from left to right, row by row.\n"
<< "(e.g. 2 in first box would be 112)\n";
//take input as one int, to be user friendly
while (cin >> rcv && count < 81) {
row = (rcv / 100) - 1;
col = ((rcv / 10) % 10) - 1;
val = rcv % 10;
os << row << " " << col << " " << val << endl;
g.set (row, col, val);
count++;
}
os.close();
//From here down is broken, but it still compiles, runs, and works
cout << "Show grid input(y/n)?\n";
cin >> yon;
if (yon.compare("y")==0)
g.show_grid();
else if (yon.compare("n")==0)
cout << "Peace!\n";
return 0;
}
The problem is here:
while (cin >> rcv && count < 81)
Consider what happens when count==81: First, rcv will be input from cin, and only then the condition count < 81 will be evaluated to false. The loop will stop, and the value of rcv will be ignored. So effectively you read one input too many.
You should change the order of evaluation, so that count is checked first:
while (count < 81 && cin >> rcv)
Edit:
According to your comment above you are actually expecting to read less than 81 values. In that case, I recommend having the user input a special value (for example, 0) to terminate the loop. You'd just need to add if (rcv==0) break;. If you just input an invalid value as you are apparently doing, the cin stream will be put in a failed state and further input will not succeed.
Try something like:
//useful output (hopefully)
cout << "Enter grid coordinates and value as a 3-digit number,\n"
<< "from left to right, row by row.\n"
<< "(e.g. 2 in first box would be 112)\n"
<< "or Z to end the loop\n"; // 1
//take input as one int, to be user friendly
while (count < 81 && cin >> rcv ) { // 2
row = (rcv / 100) - 1;
col = ((rcv / 10) % 10) - 1;
val = rcv % 10;
os << row << " " << col << " " << val << endl;
g.set (row, col, val);
count++;
}
if(!std::cin) { // 3
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
1) Let the user know that he can enter in invalid char. It doesn't have to be Z, actually any non-numeric char will work.
2) Fix off-by-one error in the order of the &&.
3) If std::cin is in error state, clear the error and ignore the Z.
cin >> yon
still actually reads in a variable, it just reads in the variable that the while loop found to be false. When the while loop condition returns false rcv is ignored, so the number remains in the input stream waiting for the next cin statement. When yon is called that number meant for rcv is read into yon, giving you some strange errors.
it would be better to use interjay's method:
while (count < 81 && cin >> rcv)