int main()
{
char j[] = "abc";
print(j);
}
When I define print like this:
void print(const char *cp)
{
if (cp)
{
while (*cp)
{
int i = *cp;
cout << *cp;
// cout << *cp << endl;
cp++;
}
}
}
The console is something like this (I can not copy the result property, so I use a screenshot)
The % like character is quite expected
However, when I put the endl the wired % character disappear
void print(const char *cp)
{
if (cp)
{
while (*cp)
{
int i = *cp;
// cout << *cp;
cout << *cp << endl;
cp++;
}
}
}
Could anyone help explain what happen?
I do not think % is not part of the prompt
I change my prompt the a text 'a', and the % still present
Related
main():
char inp[] = "(A+B)/(C*D))";
Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
Here is Infix constructor:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
Infix is inheriting from a class 'Stack':
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
When I run the code in main, it displays unusual output:
Element In Stack: (
Operator Array: /*-+%
In main: +%
Stack Object Destroyed!
But, when in main, if the comment the line declaring 'Infix' object declaration, the code runs fine:
In main: (A+B)/(C*D))
EDITS:
Stack Class
#include<iostream>
using namespace std;
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
bool Stack:: push(char elementToPush) {
if(top > 98) {
cout << "\nStack Overflow!!";
return false;
} else {
arr[++top] = elementToPush;
return true;
}
}
char Stack:: pop() {
if(top <= -1) {
cout << "\nStack Underflow!!";
return ' ';
} else {
return (arr[top--]);
}
}
char Stack:: peek() {
if(top > 98) {
cout << "\nStack Overflow!!";
return ' ';
} else {
return arr[top];
}
}
bool Stack:: isEmpty() {
return (top <= 0);
}
void Stack:: displayAll() {
if(top <= -1) {
cout << "null";
return;
}
int i = top;
while (i >= 0) {
cout << arr[i] << " ";
--i;
}
cout << "\n";
}
Infix Class
#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>
using namespace std;
class Infix : public Stack {
string outputString;
char operatorArray[];
public:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
string infixToPostfix(char *, int);
bool manupulateOperator(char, int);
int checkPrecedence(char);
~Infix() {
cout << "\nStack Object Destroyed!" << endl;
}
};
string Infix:: infixToPostfix(char *str, int size) {
cout << "\nGiven String: " << str << endl;
int x;
for(int i = 0; i < size; ++size) {
x = str[i];
if(x != ' ') {
if(x == ')') {
while(returnTop() != '(') {
cout << pop() << " popped!\n";
}
cout << pop() << " popped!\n";
} else if(isalpha(x)) {
cout << x;
} /* else{ // scanned character is an operator
if(manupulateOperator(x, i)) {
} else {
return " ";
}
} */
}
}
return outputString;
}
bool Infix::manupulateOperator(char c, int position) {
try {
char topElement = *returnElement(returnTop());
if(checkPrecedence(c) == -1) {
cout << "\nErr\n";
}else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
push(c);
cout << c << " pushed!\n";
}
} catch(std::exception e) {
std::cerr << e.what() << '\n';
return false;
} catch (char* Ce) {
cout << Ce << endl;
}
return true;
}
int Infix::checkPrecedence(char c) {
/*
+ -> 1
- -> 1
* -> 2
/ -> 2
% -> 2
*/
switch(c) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '%':
return 2;
default:
// throw "Illegal Operator Detected!";
cout << "Illegal Operator Detected: " << c << endl;
return -1;
}
}
int main() {
cout << endl;
int x = 1;
char inp[] = "(A+B)/(C*D))";
//Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
// cout << i.infixToPostfix(input + ')', sizeof(input));
/* for(int i = 0; i < strlen(inp); ++i) {
cout << inp[i];
}
*/
return 0;
}
You are declaring operatorArray as an array of char but you are not assigning any memory for it! So, when you then call strcpy(operatorArray, "/*-+%"); in your Infix constructor, you are causing undefined behaviour by attempting to copy the given string constant to memory that hasn't been assigned - and this appears to be overwriting the inp[] array declared in your main.
To fix this, I would suggest giving your operatorArray member a specific size, which will be large enough to accommodate whatever string you want to copy to it - 8 characters will work in the sample code you've given:
class Infix : public Stack {
string outputString;
char operatorArray[8]; // Make this member a REAL array of characters.
//..
Your variable char operatorArray[] have no memory allocated when your constructor is called. When you use strcpy, you write to a place where you don't have permissions in your memory, and therefore on other informations.
To find these kinds of mistakes, I recommend using valgrind.
char operatorArray[]; is not allowed in Standard C++.
If you didn't see an error message then I would recommend adjusting compiler settings to follow the standard form of the language, this would have saved you a lot of time.
I have this header:
MvProjectQueue & operator >> (char *);
And I have to write a function meeting this spec. (my function should "return" an array of chars using >> operator)
I have to change the passed argument, i.e. I get an array of char when my function is called and I have to modify it (in place).
Normally I would use
MvProjectQueue & operator >> (char **);
got a pointer to char * and I would solved it easily, using something like this:
#include <iostream>
using namespace std;
class SimpleShowcaseObject
{
public:
SimpleShowcaseObject(){};
~SimpleShowcaseObject(){};
SimpleShowcaseObject & operator >> (char ** p_ch)
{
*p_ch = "changed";
cout << "in scope: " << *p_ch << endl;
return *this;
}
};
int main(void)
{
char *ch = new char[10];
ch = "hello";
SimpleShowcaseObject o = SimpleShowcaseObject();
cout << "original: " << ch << endl;
o >> &ch;
cout <<"changed: " << ch << endl;
delete[] ch;
cin.get();
return 0;
}
But this:
#include <iostream>
using namespace std;
class SimpleShowcaseObject
{
public:
SimpleShowcaseObject(){};
~SimpleShowcaseObject(){};
SimpleShowcaseObject & operator >> (char *ch)
{
ch = "changed";
cout << "in scope: " << ch << endl;
return *this;
}
};
int main(void)
{
char *ch = new char[10];
ch = "hello";
SimpleShowcaseObject o = SimpleShowcaseObject();
cout << "original: " << ch << endl;
o >> ch;
cout <<"changed: " << ch << endl;
delete[] ch;
cin.get();
return 0;
}
executes and prints:
original: hello
in scope: changed
changed: hello
and I would like to have
original: hello
in scope: changed
changed: changed
(edited several times, big thanks to everyone for trying to help!)
Your function receive what should be a buffer you can write to:
SimpleShowcaseObject & operator >> (char *ch)
{
//ch = "changed";// with this you are changing the value of the pointer, not what you want
strcpy (ch, "changed");
cout << "in scope: " << ch << endl;
return *this;
}
As other have already pointed out, this is not a good design: your operator >> has to write a string (char[]) in a buffer, without knowing the lenght of input buffer; not a nice scenario.
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.
Hello I've got some troubles to delete a member string of my class which is isn't null and which points to the right location since I can display my string "hello world" just before.
I call the function mystringclass::alloc() from another member function afterwards this->str was supposed to get another string content larger.
The process worked fine a first time when I resized the same way "hello" to get "hello world". But now I want to enlarge it again it doesn't. So I'm confused.
Please help me.
void mystringclass::alloc(long newsize) //newsize includes the +1 char
{
cout << "old size was: " << this->size << endl; //displays "12"
if(this->str) cout << this->str << endl; //displays "hello world" all is right till here
if(this->str) delete [] this->str ; //it crashes here
cout << "str deleted\n"; //never show up on screen
this->str = new char[newsize + 1];
this->size = newsize;
this->str[0] = 0;
}
Thanks for your answers, I tried to clear my code to post it here. My bug disappeared but another one came up and having something to do with the rule of three:
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
return 0;
}
I display info all along procedures So the problem is that str2 is already equal to "hello" even before affecting the content of str in my copy constructor. And is empty after the copy. What's wrong? As some may say, I learned c++ in a magicbox. I'm using codeblocks 10.05
Full code :
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
class stringclass
{
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
char * mystring;
long memsize;
long length;
void alloc(long newsize);
void reset();
void copy(const stringclass & other);
stringclass() {reset(); }
stringclass(const stringclass & other) {copy(other); }
stringclass(const char str[]);
~stringclass() {delete [] mystring;}
inline long get_length() { if(mystring) length = strlen(mystring); return length;}
inline long get_memsize() const { return memsize; }
friend ostream& operator << (ostream& out, stringclass & sc){out << sc.mystring; return out;}
stringclass & operator = (stringclass & other) { copy(other); return *this;}
};
void stringclass::reset()
{
delete [] mystring;
mystring = NULL;
length = 0;
memsize = 0;
}
void stringclass::alloc(long newsize)
{
cout<< "\nalloc(long newsize)... \n" << endl;
cout << "memsize was : " << memsize << endl;
cout << "length was : " << length << endl;
if(mystring) cout << "mystring = " << mystring << endl;
delete [] mystring;
cout << "mystring deleted...\n";
mystring = new char[newsize];
cout << "mystring has been resized\n";
mystring[0] = 0;
memsize = newsize;
length = strlen(mystring);
cout << "memsize is now : " << memsize << endl;
cout << "length is now : " << length << endl;
cout<< "\nend of alloc()... " << endl;
cout << "\n";
}
void stringclass::copy(const stringclass & other)
{
cout << "\n";
cout << "copy(const stringclass & other)...\n" << endl;
cout << "other.mystring = "<< other.mystring << endl;
if(other.mystring == NULL || other.memsize == 0)
{
reset();
return;
}
alloc(other.memsize);
strcpy(mystring, other.mystring);
cout << "mystring = "<< mystring;
length = strlen(mystring);
cout << "length: " << length << endl;
cout<< "\nend of copy()... " << endl;
cout << "\n";
}
stringclass::stringclass(const char str[]) : mystring(NULL), memsize(0), length(0)
{
if(str == NULL) reset();
else
{
alloc(strlen(str) + 1);
strcpy(mystring, str);
length = strlen(mystring);
}
}
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
cout << "\nback to main()...\n";
cout << "str = " << str << "\n";
cout << "str2 = " << str2 << "\n";
cout << endl;
system("PAUSE");
return 0;
}
Result on screen :
alloc(long newsize)...
memsize was : 0
length was : 0
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
copy(const stringclass & other)...
other.mystring = Hello
alloc(long newsize)...
memsize was : 3214960
length was : 2293560
mystring = Hello
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
mystring = length: 0
end of copy()...
back to main()...
str =
str2 =
Appuyez sur une touche pour continuer...
I've just realized that the following code isn't necessary for you :
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
So I put off these two functions and this variable, and guess what.. all worked fine, no bug. They are not even used once. I put it back and the problem came back as well. How could you explain that?! I'm already losing my hairs.
The fact that you can "display" a string says absolutely nothing unfortunately. De-allocating the string will still make it printable, most likely until it's overwritten by a new llocation and initialization.
Just try to print the string after you've delete[]d it and see.