This question already has answers here:
cout << order of call to functions it prints?
(3 answers)
Closed 2 years ago.
#include <iostream>
using namespace std;
int output_1(string s, char c);
int output_2(string s, char c);
int main() {
string str;
char c;
cout << "Enter a string: ";
getline(cin, str);
cout << "Enter a character: ";
cin >> c;
cout << "[1] the number of times the character appears: " << output_1(str, c) << endl;
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
return 0;
}
int output_1(string s, char c) {
int count = 0;
for (int x = 0; x < s.length(); x++)
if (s[x] == c)
count++;
return count;
}
int output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
Why is the second output not in order and have an extra 0 at the end?
Enter a string: test
Enter a character: t
[1] the number of times the character appears: 2
0 3 [2] That character is found at Index/Indices: 0
The problem is this line:
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
The first thing to note is that << is just syntactic sugar for a function call. So we can re-write it to look like this:
cout.op<<("[2] That character is found at Index/Indices: ")
.op<<(output_2(str, c))
.op<<(endl);
Because they are chained statements you can think of this as:
std::ostream& t1 = cout.op<<("[2] That character is found at Index/Indices: ");
std::ostream& t2 = t1.op<<(output_2(str, c));
std::ostream& t3 = t2.op<<(endl);
So what we have are three method calls to op<<() each passing one parameter. Before calling these methods that the compiler must get the operands to the calls. The first one is easy as it is a literal string, the second one requires a function call. So the compiler must call the function output_2() before it can call op<<() and the third one is an function (easy to pass the address).
But the compiler can sequence that call to output_2() at any point (as long as it happens before the call to op<<(). So it looks the compiler is doing this:
<Seq Start>
void& x = output_2(str, c); // yes I know thats not legal C++ just for explaining.
std::ostream& t1 = cout.op<<("[2] That character is found at Index/Indices: ");
std::ostream& t2 = t1.op<<(x);
std::ostream& t3 = t2.op<<(endl);
<Seq End>
Note: The compiler could place the call anywhere between <Seq Start> and <Seq End> (before it is needed) it's just an implementation detail. Now the call to output_2() also actually outputs to the std::cout followed by a int (which is not returned (undefined behavior by itself)).
Instead of printing value in main, Try this :
//call this from main
output_1(str, c);
output_2(str, c);
Then:
void output_1(string s, char c) {
int count = 0;
for (int x = 0; x < s.length(); x++)
if (s[x] == c)
count++;
cout<< count<<endl;
}
void output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
This is UB. output_2 should return an int, but doesn't return anything. Now you get a 0, but it could be anything.
As you're building op an ostream in output_2, you could use a stringstream internally and convert that to a string for the output.
#include<string>
#include<iostream>
#include<algorithm>
#include<sstream>
int output_1(std::string const& s, char c) {
return std::count(cbegin(s), cend(s), c);
}
std::string output_2(std::string const& s, char c) {
std::stringstream os;
for (int x = 0; x < s.length(); ++x) {
if (c == s[x]){
os << x << " ";
}
}
return os.str();
}
int main() {
std::string str = "test";
char c = 't';
std::cout << "[1] the number of times the character appears: " << output_1(str, c) << '\n';
std::cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << '\n';
}
You issue is that output_2 lies. The return type of int says the function returns a value. There is no return statement, so there is undefined behavior.
My suggested solution:
void output_2(string s, char c)
{
for (int x = 0; x < s.length(); x++)
{
if (c == s[x])
{
cout << x << " ";
}
}
}
int main()
{
//...
cout << "[1] the number of times the character appears: " << output_1(str, c) << endl;
cout << "[2] That character is found at Index/Indices: ";
output_2(str, c);
cout << endl;
return 0;
}
In the above code fragments, the return type of output_2 is set to void since it doesn't return a value.
In the main function, the output_2() is removed from the cout statement (since output_2() doesn't return a value), and set as a separate function call.
Running through output_2():
int output_2(string s, char c) {
for (int x = 0; x < s.length(); x++) {
if (c == s[x]){
cout << x << " ";
}
}
}
First pass (t) prints 0.
Second pass (e) prints nothing.
Third pass (s) prints nothing
Fourth pass (t) prints 3
You wrote output_2() as returning int, but actually you should be returning an array of integers and printing those (or something similar). The return value of a function that is supposed to return an int but has no return line is undefined. The behaviour of the whole program is also undefined because of this missing return statement. Anyway, in your specific case, it looks like output_2() returned 0 and so finally after control was returned to main it printed
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
where output_2(str, c) prints a zero (in an undefined manner). I think one thing that you were missing (with respect to order) is that the line
cout << "[2] That character is found at Index/Indices: " << output_2(str, c) << endl;
first allows output_2() to print 0 and 3 and then starts to print this line.
Related
I'm a beginner to learning C++. Just today I tried to learn the boolean operator and if-else statement.
This is the code:
int main(){
//if-else statement
int a, b;
bool result = (a < b);
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result <<std::endl;
if(result == true){
std::cout << a << " is less than " << b << std::endl;
}
if(!(result == true)){
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}
These are the results after a few executions:
Initially the results were fine, but then after a couple times it went wrong.
Does anybody know what the cause of this is?
Your mistake is that you compare the two variables and save the result before you assign any proper values to these variables. In other words, you compare uninitialized variables a and b which have undefined values.
First, you do:
bool result = (a < b);
And then after you get the values:
std::cin >> a;
std::cin >> b;
You should do the following instead:
// ...
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = a < b; // <-- move this down here!
// ...
You expect result to be evaluate a == b when you use it later. Instead bool result = (a < b); initializes result with (a < b) once and its value does not change afterwards. As neither a nor b are initialized when you declare result your code has undefined behavior.
You can make result a function object to make it work as you expected by using a lambda expression. However, to call it you'll have to add ():
int main(){
//if-else statement
int a = 0;
int b = 0;
auto result = [&](){ return a < b; };
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result() <<std::endl;
if(result()) {
std::cout << a << " is less than " << b << std::endl;
} else {
std::cout << a << " is NOT less than " << b << std::endl;
}
}
You should always initialize variables. Using the value of uninitialized variables is undefined behavior and can happen easily (as in your code) when you do not initialize variables. Instead of if (condition) {} if (!condition){} you can use if (condition) {} else {}. Instead of if (result() == true) you can write if (result()). And return 0; is implicit in main, you need not write it.
You overall code as it should be.
Explanations in the comments:
int main() {
//if-else statement
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = (a < b); // put this here, because now a and b have
// determined values
std::cout << std::boolalpha << result << std::endl;
if (result) { // or simple if (a < b) and drop result alltogether
std::cout << a << " is less than " << b << std::endl;
}
else { // no need for testing the opposite of result
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}
This code is for recursive function practice. When I run the code, it stops at the "POWER" cout line, then my compiler shows a segmentation error. The function that follows the POWER line is supposed to recursively raise number "a" to the power of number "b". I'm not sure how to fix this, can anyone help?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/**** Recursive backwards print, prints a string starting from last index to first*****/
void printReverse(string s, int i)
{
if(i < s.size())
{
printReverse(s.substr(1), i);
cout<<s[i];
}
else
{
return;
}
}
/**** Recursive power function, computes a^b, where b can be positive or negative*****/
int recPower(double a, int b)
{
int i = b; //i = b, so int a can be multiplied int b times
if (i == 0) //base
return 1;
else //multiply A by B, B times
{
a *= b;
return recPower(a, b); //recursive
i--; //decrement i until it equals 0
}
}
/**** Recursive string replace, replaces all instances of a character in a string with another character*****/
string recReplace(string s2, int i, char old, char neW)
{
if(s2[i] == old) //search for old char
{
i = neW; //replace it
i++; //iterate i
}
recReplace(s2, i, old, neW); //call function
return s2;
}
/**** Recursive list find > Searches if x exists in list, returns true if found, false otherwise*****/
int recListFind(vector<int> v, int i, int x)
{
if(v[i] == x)
{
cout << x << " exists in the vector."<<endl;
i++;
recListFind(v, i, x);
}
return true;
}
int main()
{
cout << "PRINT REVERSE" << endl;
cout << "----------" << endl;
string s1 = "hello world";
cout << "String: " << s1 << endl;
cout << "Reversed: ";
printReverse(s1, 0);
cout << endl;
/* Computes a^b (power function) */
cout << "POWER" << endl;
cout << "----------" << endl;
int a = 2, b = -3;
cout << a << "^" << b << " = ";
cout << recPower(a, b) << endl;
cout << endl;
/* Replaces a character in a string with a new one */
cout << "REPLACE" << endl;
cout << "----------" << endl;
string s2 = "-h-e-l-l-o-";
char oldChar = '-';
char newChar = ' ';
cout << "String: " << s2 << endl;
cout << "> Replace '" << oldChar << "' with '" << newChar << endl;
recReplace(s2, 0, oldChar, newChar);
cout << "String: " << s2 << endl;
cout << endl;
/* Searches for value in vector */
cout << "FIND" << endl;
cout << "----------" << endl;
int x = 7;
cout << "Does " << x << " exist in the vector? "; vector<int> v = {5, 1, 6, 7, 9};
cout << recListFind(v, 0, 7) << endl;
cout << endl;
return 0;
}
The issue is quite straight forward, you are doing the recPower function with b. In the function, if b is not 0, you call recPower with an unmodified value of b (whilst ever modifying a). This will always end up with infinite recursion which is going to overflow your stack.
A solution could be:
int recPower(double a, int b, int times) {
if (times == 0)
return a;
else
return b * recPower(a, b, --times);
}
int recPower(double a, int b) {
return recPower(a, b, b);
}
Even if you fix this, you have another problem. b can be negative, which based on your logic will continue to recurse while decrementing until it overflows and goes back to 0. You will cause this case with your first test case. You should think about the types that are allowed in this function, consider making them unsigned, or dealing explicitly with the negative b case.
So, I'm practising my C++ code by writing a program that creates a matching-pairs game out of a grid with user-specified size. To do this I've separated each action (initialising the grid, drawing the grid, hiding the pairs and finding the pairs from user input) into a function.
Unfortunately, at some point - I can't tell when or how - the program began failing to call the second* and subsequent functions. After calling drawGrid, it should move on to hidePairs immediately - however, it just stops at that step. The cursor in the command window keeps blinking, so the program's running just fine, but nothing I can do will make it progress.
I've checked via debugging, and it does successfully execute drawGridand moves on to the next line in main, but then no more code gets executed. What am I doing wrong?
*EDIT: third function, it successfully draws the grid, THEN stops before hiding the pairs. Unnecessary calls-by-reference removed and all functions added for clarity. My bad :P
#include <iostream>
#include <random>
#include <algorithm>
void drawGrid(int gridX, int gridY, char gridArray[][30]);
void hidePairs(int gridX, int gridY, char pairsArray[][30], int *numPairs);
void findPairs(int gridX, int gridY, char gridArray[][30], char pairsArray[][30], int *numPairs);
void initialiseGrid(int gridX, int gridY, char gridArray[][30], char pairsArray[][30]);
int main()
{
int gridX, gridY, numPairs;
//Ask user for gridX(width) and gridY(height)
std::cout << "Please enter the width and height of the grid you want to use." << std::endl;
bool gridIsNotEven = true;
while (gridIsNotEven == true)
{
std::cin >> gridX >> gridY;
if ((gridX*gridY) % 2 == 0)
{
gridIsNotEven = false;
}
else
{
std::cout << std::endl << "The grid produced by these two numbers has an odd number of spaces." << std::endl;
}
}
if (gridX*gridY > 30)
{
std::cout << "This grid is larger than recommended." << std::endl;
}
gridX++;
gridY++;
char gridArray[30][30];
char pairsArray[30][30];
numPairs = ((gridX*gridY) / 2);
//Func : initialiseGrid
initialiseGrid(gridX, gridY, gridArray, pairsArray);
//Func : drawGrid
drawGrid(gridX, gridY, gridArray);
//Func : hidePairs
hidePairs(gridX, gridY, pairsArray, &numPairs);
//Func : findTreasure
findPairs(gridX, gridY, gridArray, pairsArray, &numPairs);
system("Pause");
return 0;
}
void drawGrid(int gridX, int gridY, char gridArray[][30])
{
int printX, printY;
//For(printX = 0, printX < gridX, printX++)
for (printY = 0; printY < gridY; printY++)
{
//For(printY = 0, printY < gridY, printY++)
for (printX = 0; printX < gridX; printX++)
{
std::cout << gridArray[printX][printY] << " ";
}
//END FOR
//Print new line
std::cout << std::endl;
}
//END FOR
}
void hidePairs(int gridX, int gridY, char pairsArray[][30], int *numPairs)
{
int pairsMade, halfPair, curPairX = 0, curPairY = 0;
char pairSymbol = '!';
for (pairsMade = 0; pairsMade < *numPairs; pairsMade++)
{
halfPair = 0;
while (halfPair < 2)
{
curPairX = rand() % gridX;
curPairY = rand() % gridY;
if (pairsArray[curPairX][curPairY] == '?')
{
pairsArray[curPairX][curPairY] = pairSymbol;
halfPair++;
}
}
pairSymbol++;
}
}
void findPairs(int gridX, int gridY, char gridArray[][30], char pairsArray[][30], int *numPairs)
{
int guess1X = 0, guess1Y = 0, guess2X, guess2Y, printChar, pairsFound = 0;
//Display pairs
char pairSymbol = '!';
printChar = 0;
std::cout << std::endl << "The following symbols will be used in the grid:" << std::endl << std::endl;
while (printChar < *numPairs)
{
std::cout << pairSymbol << std::endl;
pairSymbol++;
printChar++;
}
//while ((guessX != treasureX) OR(guessY != treasureY))
while (pairsFound != *numPairs)
{
// User input : guessX and guessY
std::cout << std::endl << "Please enter the co-ordinates of your first guess (e.g. 'X Y')" << std::endl << std::endl;
std::cin.clear();
std::cin >> guess1X >> guess1Y;
gridArray[guess1X][guess1Y] = pairsArray[guess1X][guess1Y];
drawGrid(gridX, gridY, gridArray);
std::cout << std::endl << "Please enter the co-ordinates of your second guess (e.g. 'X Y')" << std::endl << std::endl;
std::cin.clear();
std::cin >> guess2X >> guess2Y;
gridArray[guess2X][guess2Y] = pairsArray[guess2X][guess2Y];
drawGrid(gridX, gridY, gridArray);
if (guess1X > gridX || guess1X < 1 || guess1Y > gridY || guess1Y < 1)
{
std::cout << std::endl << guess1X << ", " << guess1Y << " does not lie inside the grid. Try again." << std::endl;
continue;
}
else if (gridArray[guess1X][guess1Y] == gridArray[guess2X][guess2Y])
{
pairsFound++;
}
else
{
std::cout << std::endl << "Pair not matching" << std::endl << std::endl;
gridArray[guess1X][guess1Y] = '?';
gridArray[guess2X][guess2Y] = '?';
}
// END IF
}
//Print ‘Success! etc.’
std::cout << std::endl << "Success! You found all the pairs!" << std::endl << std::endl;
}
void initialiseGrid(int gridX, int gridY, char gridArray[][30], char pairsArray[][30])
{
int printX, printY;
for (printY = 0; printY < gridY; printY++)
{
for (printX = 0; printX < gridX; printX++)
{
if ((printX == 0))
{
gridArray[0][printY] = printY + '0';
pairsArray[0][printY] = printY + '0';
}
else if ((printY == 0))
{
gridArray[printX][0] = printX + '0';
pairsArray[printX][0] = printX + '0';
}
else
{
gridArray[printX][printY] = '?';
pairsArray[printX][printY] = '?';
}
}
}
}
You initialised the number of pairs to numPairs = gridX * gridY / 2, but that size (gridX, gridY) contains also the header column and row, that do not play a role in the pairing.
So to fix this, your numPairs should be (gridX-1) * (gridY-1) / 2.
Else, the pairs will have been exhausted, but the pairing function is still looking! This is your infinite loop.
I also advise you to find a better name for gridX and gridY to indicate that the headers are counted, or to be very careful in the rest of your code that you understand what gridX and gridY mean and that the grid only starts being an actual thing at index 1 rather than index 0.
It seams it fails only if you add numbers 30 and higher caused by array size
I dont know your settings but ensure you have compiler setting of language standard like GNU C++11
it should work
Turns out there's an infinite loop in the hidePairs function. It's not reading the correct co-ordinates in the pairsArray, so there are spaces it never fills in. And since the loop is only set to end when all unused spaces are filled, it never stops.
Advice for others: always sanity-check your loops!
For the life of me I can't figure out why the I can't write to a c style string inside of a struct.
College student - can't use string class, haven't learned pointers.
Help? 2 hours at trying to figure this out.
#include <iostream>
using namespace std;
void strCopy(char from[], char to[])
{
for (int i = 0; i < 255; i++)
{
to[i] = from[i];
}
}
struct card
{
char suit[20];
char rank[20];
int cvalue;
char location[20];
};
void printCard(card card)
{
cout << card.rank << " of " << card.suit << endl;
}
int main()
{
// I don't think strCopy()'s the problem, I've used it with my last project.
cout << "Test strCopy()" << endl;
char str1[14] = "abcdefghijklm";
char str2[14];
strCopy(str1, str2);
cout << " " << str2 << endl << endl;
// Now the negative.
card one;
one.cvalue = 2;
strCopy("Somewhere", one.location);
strCopy("Two", one.rank);
strCopy("Hearts", one.suit);
printCard(one);
}
// I don't think strCopy()'s the problem, I've used it with my last
project.
Wrong
for (int i = 0; i < 255; i++)
{
to[i] = from[i];
}
copies 255 characters, however that's not what you meant.
If here :
strCopy(str1, str2);
cout << " " << str2 << endl << endl;
Your're getting "correct" output, then you're just unlucky, since that invokes an undefined behavior, an you're writing off the end of the array.
So essentially what my program does is read in a data stream of words, and count the occurrence of each word, and the total number of unique words. It will will read them into a map. My program works perfectly except for one problem...when I call p.print(), the value for total is still at 0. There seems to be some problem where total is incremented in the for_each statement, but when I p.print, it acts as if was never incremented...My print function is defined as follows:
void print_words(const map<string,int> &aMap) {
PRN p(aMap.size());
for_each(aMap.begin(), aMap.end(), p);
p.print();
}
I have a class that is in charge of processing each word, here is the definition:
//CLASS PRN FUNCTIONS
// constructor
PRN::PRN(const int& s, const int& c, const int& t) {
sz=s;
cnt=c;
total=t;
}
// overloaded operator, where P is defined as
// typedef pair < string, int > P;
void PRN::operator()(const P& p) {
if(cnt%NO_ITEMS == 0 && cnt != 0)
cout << '\n';
cout << setw(ITEM_W) << left << p.first << " : " << setw(NO_W) << left << p.second;
total += p.second;
cnt++;
}
// to printout final value of total
void PRN::print() const {
cout << '\n' << '\n';
cout << "no of words in input stream : " << total << endl;
cout << "no of words in output stream : " << sz << endl;
}
Figured it out...I need to have
p = for_each(aMap.begin(), aMap.end(), p);
No better feeling then figuring out your own problem!