I have a menu pointer that I want to be able to change between 2 different char arrays. My goal is to be able to change the global menu and then be able to call it but i'm having trouble assigning the menu variable.
This is the error I'm getting:
cannot convert ‘const char* (*)[11]’ to ‘char*’ in initialization
const char *chapterSelect[] = {"Chapter 1", "Chapter 2", "Chapter 3", "Chapter 4", "Chapter 5", "Chapter 6", "Chapter 7", "Chapter 8", "Chapter 9", "Chapter 10", "Chapter 11"};
const char *chapter1[] = {"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", "Level 7", "Level 8", "Level 9", "Level 10", "Level 11"};
char* menu = &chapterSelect;
drawMenuItems(menu);
menu = &chapter1;
drawMenuItems(menu);
void drawMenuItems(const char *Items[])
{}
Problem 1: Your use of const is inconsistent.
Problem 2: To point at the first item of an array of pointers to char, you need to use (const) char**.
Problem 3: &chapterSelect doesn't make any sense since it gives a pointer to the type of the array, not of the first element.
Solution:
const char** menu = chapterSelect;
Or equivalent:
const char** menu = &chapterSelect[0];
The type of &chapterSelect is const char* (*)[11] and since there is no implicit conversion from const char* (*)[11] to a char*, we get the mentioned error. Basically, there is a type mismatch on the left and right side.
To solve this you can make sure that the type on the lhs and rhs are same:
//-----------------vvvvvvvvvvvvvvvvvvvvvv-------->changed type to this
void drawMenuItems(const char*(*Item)[11])
{
}
int main()
{
const char *chapterSelect[] = {"Chapter 1", "Chapter 2", "Chapter 3", "Chapter 4", "Chapter 5", "Chapter 6", "Chapter 7", "Chapter 8", "Chapter 9", "Chapter 10", "Chapter 11"};
const char *chapter1[] = {"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", "Level 7", "Level 8", "Level 9", "Level 10", "Level 11"};
//--vvvvvvvvvvvvvvvvvvvvvv------------------->changed type to this
const char*(*menu)[11] = &chapterSelect;
drawMenuItems(menu); //or drawMenuItems(&chapterSelect);
menu = &chapter1;
drawMenuItems(menu); // or drawMenuItems(&chapter1);
}
working demo
C++20
Note that with C++20 we're allowed to do this for array of different sizes. This means that you can change menu's declaration to:
//---------------------v---------------------->works with C++20, NO SIZE GIVEN HERE!!
const char*(*menu)[] = &chapterSelect;
c++ 20 demo
I will start with answering your question but will follow with additional suggestion:
The error you see is because you are taking an address of const char* which in practice means the returned value should be const char**.
Instead of:
char* menu = &chapterSelect;
use:
char** menu = (char**) &chapterSelect;
Note there are 2 points of change. One for menu type and one for explicit const-cast-away.
Although the above will solve the compilation error - I want to raise a few suggestions:
I don't understand the need for char** menu as you can pass the arrays' addresses directly to drawMenuItems(). If the function that from its name means it prints the array as menu - then it shouldn't alter the array and should receive a const char**.
It is not good practice to cast-away const. The compiler is considering you did a coding mistake and the right side const-cast-away is telling both compiler and other developers that you are casting-away-const on purpose.
When your code includes a call to a function (drawMenuItems()), it is good to provide at least the function declaration for clearer understanding of the readers.
I hope this resolves the issue raised.
Related
In QString, contains() method works like this:
QString s = "long word";
s.contains("long"); // -> True
I would assume that QStringList works similarly, but it does not:
QStringList s;
s << "long word";
s << "longer word";
s.contains("long"); // -> False
QStringList contains searches for the exact match, which does not work like I want it to. Is there an easy way to find a part of a string in a QStringList? I could of course loop through the QStringList and use contains() there, but is there a better way?
You can use the function QStringList::filter() :
QStringList QStringList::filter(const QString &str,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const
Returns a list of all the strings containing the substring str.
and check that the list returned is not empty.
In your case:
QStringList s;
s << "long word";
s << "longer word";
s.filter("long"); // returns "long word", and also "longer word" since "longer" contains "long"
I am learning from C++ Primer Plus book, and I've recently done this exercise from the book. I have a problem: when the user hits enter without any sign, then in the next entry to display any of these functions he has to hit enter again, because if not it'll still display "Wrong choice" and "Next Choice:" all the time. Can you tell me what's wrong with this code, and what should I add?
Thanks in advance.
/*When you join the Benevolent Order of Programmers, you can be known at BOP
meetings by your real name, your job title, or your secret BOP name.Write a program
that can list members by real name, by job title, by secret name, or by a member’s
preference. Base the program on the following structure:
// Benevolent Order of Programmers name structure
struct bop {
char fullname[strsize]; // real name
char title[strsize]; // job title
char bopname[strsize]; // secret BOP name
int preference; // 0 = fullname, 1 = title, 2 = bopname
};
In the program, create a small array of such structures and initialize it to suitable
values. Have the program run a loop that lets the user select from different alternatives:
a. display by name b. display by title
c. display by bopname d. display by preference
q. quit
302 Chapter 6 Branching Statements and Logical Operators
Note that “display by preference” does not mean display the preference member; it
means display the member corresponding to the preference number. For instance, if
preference is 1, choice d would display the programmer’s job title.A sample run
may look something like the following:
Benevolent Order of Programmers Report
a. display by name b. display by title
c. display by bopname d. display by preference
q. quit
Enter your choice: a
Wimp Macho
Raki Rhodes
Celia Laiter
Hoppy Hipman
Pat Hand
Next choice: d
Wimp Macho
Junior Programmer
MIPS
Analyst Trainee
LOOPY
Next choice: q
Bye!*/
Solution:
#include <iostream>
void text();
void name();
void title();
void secret();
void prefr();
const int strSize = 23;
const int People = 4;
char ch;
struct bop {
char fullname[strSize]; // real name
char title[strSize]; // job title
char bopname[strSize]; //secret BOP name
int preference; // 0 = fullname, 1 = title, 2 = bopname
};
bop people[People] //array of 4 structures
{
{"Tony Hawk", "Junior Programmer", "Novice",2}, //first member
{"Bill Gates", "Founder of Microsoft", "Billionaire",1}, //second member
{"Pop Leather", "Graphic Designer", "Fast and Furious",2}, //third member
{"Steve Jobs", "Apple Leader", "Undead Dragon",0} //fourth member
};
int main()
{
text(); //call a text function
std::cin.get(ch); //get a character
int i=0;
while(ch!='q')
{
switch(ch)
{
case 'a':
name();
break;
case 'b':
title();
break;
case 'c':
secret();
break;
case 'd':
prefr();
break;
default: std::cout << "Wrong choice\n";
}
std::cout << "Next choice: \n";
std::cin.get();
std::cin.get(ch);
}
std::cout<<"Bye!";
return 0;
}
void text()
{
std::cout<<"Benevolent Order of Programmers Report\n"
"a. display by name b. display by title\n"
"c. display by bopname d. display by preference\n"
"q. quit\n"
"Enter your choice:";
}
void name()
{
for(int i=0;i<People;i++)
std::cout<<people[i].fullname<<std::endl;
}
void title()
{
for(int i=0;i<People;i++)
std::cout<<people[i].title<<std::endl;
}
void secret()
{
for(int i=0;i<People;i++)
std::cout<<people[i].bopname<<std::endl;
}
void prefr()
{
for(int i=0;i<People;i++)
{
if(people[i].preference==0)
std::cout<<people[i].fullname<<std::endl;
else if(people[i].preference==1)
std::cout<<people[i].title<<std::endl;
else if(people[i].preference==2)
std::cout<<people[i].bopname<<std::endl;
}
}
I think the problem lies here:
std::cin.get();
std::cin.get(ch);
If there was indeed a character, the first get will clean the newline, and the second will perform another read.
If there was no character to begin with, the first get will consume the actual input, and ch end up as a newline.
A solution to that is: don't treat input as valid if you're not sure it's valid. In particular, you're expecting two characters of input: any character except newline followed by newline.
There are two rather simple ways to solve your problem:
Don't use characters: simply work on std::string and treat empty string as invalid.
Check if the first character was a newline and don't skip an additional character then.
A more advanced solution would be to experiment more with functions. Could you wrap the input to return optional<char>? Or even better, optional<Choice>, where Choice is an enum class?
Or perhaps you could create a function that loops automatically, prompting for a proper input every time, and separate it from the main program logic?
I have been working on a program that will output a given playing card. I am using the Ace of Spades just to start out. This isn't the entire program use by no means, but this is just to see if I am on the right track.
For purposes beyond what I am about to show, I need to create a string that has "Ace of HeartsSpades" stored in it from one string that contains "Ace" and one that contains "Spades"
string toString(string myRank, string mySuit)
{
string halfCard, fullCard;
halfCard = myRank; //Ace
fullCard = halfCard.append(mySuit); //AceSpades
fullCard.insert(3, " of "); //Ace of Spades
return fullCard;
}
There is the method that I have so far. I know that not every card is going to work with a position of 3 in my fullCard.insert line, so is there another way to make this work so that this method becomes universal for all cards in a deck (jokers are not used in the deck).
I am sorry if my explanation of things were not clear.
I believe you could do something like:
string toString(string myRank, string mySuit)
{
return myRank + " of " + mySuit;
}
It's easier than that (assuming you're using std::string)
std::string toString(const std::string& myRank, const std::string& mySuit)
{
return myRank + " of " + mySuit;
}
Note that I've changed your argument to be references, which will avoid unecessary string object copies.
I am trying to make a program to print the names of an array, the array represents the first row of the chess board. My attempt is with the following program but the only thing that I can achieve is printing numbers :( .
#include <iostream>
using namespace std;
void main()
enum pions // giving the names in pions
{
Tower=1 ,
Horse ,
Officer ,
Princes ,
King };
int Chess [0][8]={Tower , Horse , officer , Princes , King , Officer , Horse , Tower };
// putting the names of each coordinate in the array (above ) .
cout << " in this place the pion that is placed is the " << chess [0][1] << endl;
I know that the program will print the number 2 , but how can I make it print the word "Horse" instead of 2 ???
The cout command is written by the creator of the program (me :P) how i can give the option to the user to choose the part of the array that is going to be printed ?
Thanks in advance for your time and effort, a big sorry in case I am not clear, its my first post :D .
Any recommendations are welcome.
You need to write a function that takes a parameter of type Chess and returns a string. Here's one that would work:
const char *chessPieceName(Chess piece)
{
switch(piece) {
case Tower:
return "Tower";
break;
case Horse:
return "Horse";
break;
// etc.
default:
return "Not a valid piece";
break;
}
}
You can call then call this function from main:
cout << " in this place the pion that is placed is the " << chessPieceName(chess[0][1]) << endl;
Having said that, you have numerous other issues in your code that should prevent it from compiling. I'm not going to go through them, since you seem to just be interested in the question you asked.
You could have a translator function that takes the int value and transforms it into a printable string value:
string translate(int piecenum){
string [5] ref = { "Tower", "Horse", "Officer", "Princes" "King"}
return ref[piecenum];
}
You can print them out using cout << translate(chess[0][1]) << endl
You cannot print out identifiers of the enum.
You need to create a different function which takes your enum as an input parameter and returns an std::string with the name you want. For example, if you pass it pions::Tower, it will return "Tower". If you pass it pions::Horse, it will return "Horse". Etc.
Hint: Use a switch statement in the body of that function, as godel9's answer illustrates.
Either use C# instead of C++ or define yourself an array of chess figure names. For example
enum pions // giving the names in pions
{
Tower = 0 , // <== I prefer to use 0 instead of 1
Horse ,
Officer ,
Princes ,
King };
const char *name = { "Tower", "Horse", "Officer", "Princes", "King" };
//...
for ( int i : chess[0] ) std::cout << name[i] << std::endl;
message.Text() is a QString.
I want to remove some text.
The text can be:
Normal: "This is a text"
With a label: "<label1>something</label1>This is a text"
First, I find if the text has the label:
!message.Text().contains("<label1>", Qt::CaseInsensitive))
So, if it has, I want to remove the first part, to have a normal text "This is a text".
I tried this:
first=message.Text().indexOf("<label1>");
last=message.Text().lastIndexOf("</label1>");
message.Text().remove(first,last);
But I got Compiler Error C2663.
I also know that the message.Text().remove(QChar('<label1'), Qt::CaseInsensitive); is another way to do it. But in my case, the part between the label is unkwnow.
It can be <label1>something</label1> or <label1>oisdioadj</label> or <label1>7</label1>....
Any idea?
Regards.
Try the following:
#include <iostream>
using std::cout; using std::endl;
#include <QString>
int main()
{
QString message = "<label1>something</label1>This is a test";
const QString labelClose = "</label1>";
const int labelCloseSize = labelClose.size();
cout << "message: " << qPrintable(message) << endl;
const int closePosition = message.lastIndexOf(labelClose);
QString justText = message.remove(0, closePosition + labelCloseSize);
cout << "just text: " << qPrintable(justText) << endl;
}
My advice here: keep things simple in your code, it will help making things simple in your head.
It seems what you want to achieve is more related to strings, than to label.
I suggest you get the text from your label, then work on it independently, then associate it back to your label:
QString text = message.text();
/* Do whatever you need to do here with text */
message.setText(text);
Also, the error you're having is probably due to the fact that you try to modify directly message.text() which is a const reference: obviously you can't modify something that is const.
I believe what you try to achieve can be done using QString::replace(). You'll have to use regular expressions for that, so if you're not familiar with it, it might be difficult.