How to pass and simply iterate...C/C++
-
wrote on 4 Mar 2023, 01:41 last edited by
As Vinie Barbarino i used to say " I am sooo confused ..."
I want to simply pass a ":bunch of QString(s)" and iterate thru them...
There is
"QStringList" -so do I define / pass
"QStringList list"Or "QStrngList list[MAX_LIST]"?
?
define as
QStringList verify = { "Discovery started", "SPP_CA" };of
QStringList verify[16] = { "Discovery started", "SPP_CA" };
?QString result = BTUL->ProcessCommand(command,verify); ??
Now I want to iterate
for ( auto ???? : verify ) .... ???
[
......??
]but there is
QStringListIteraror - FOR "Java style " ???this works
QRegularExpressionMatchIterator i = re.globalMatch(line);
while (i....and I do not believe it is "for Java style :...
-
As Vinie Barbarino i used to say " I am sooo confused ..."
I want to simply pass a ":bunch of QString(s)" and iterate thru them...
There is
"QStringList" -so do I define / pass
"QStringList list"Or "QStrngList list[MAX_LIST]"?
?
define as
QStringList verify = { "Discovery started", "SPP_CA" };of
QStringList verify[16] = { "Discovery started", "SPP_CA" };
?QString result = BTUL->ProcessCommand(command,verify); ??
Now I want to iterate
for ( auto ???? : verify ) .... ???
[
......??
]but there is
QStringListIteraror - FOR "Java style " ???this works
QRegularExpressionMatchIterator i = re.globalMatch(line);
while (i....and I do not believe it is "for Java style :...
Lifetime Qt Championwrote on 4 Mar 2023, 03:49 last edited by Chris Kawa 3 Apr 2023, 05:25QString foo;
- one string
QStringList foo
- list of strings
QStringList foo[MAX];
- array of lists of stringsFor "bunch of strings" use the middle one:
QStringList list {"abc", "xyz", "foo", "bar"};
If you want to pass it to some method then pass it via const reference, e.g.
void SomeClass::someMethod(const QStringList& list) { ... }
You didn't say what "ProcessCommand" is or what it returns, but to go over every element of a list you can simply use a range for loop:
for (const QString& s: list) { qDebug() << s; // s is a single string }
or use the older "STL style" iterator:
for (auto it = list.begin(); it != list.end(); ++it) { qDebug() << *it; // *it is a single string }
or "Java style" iterator:
QListIterator<QString> it(list); while (it.hasNext()) { qDebug() << = it.next(); // next() returns a reference to single string }
"Java style" just means this style of OOP programming, where you create an iterator object initialized with the container, was popular in Java language at some point, where C++ more commonly used the "STL style" type of iterators. Either one is fine. I would go for the range for loop, but any of those is fine.
-
QString foo;
- one string
QStringList foo
- list of strings
QStringList foo[MAX];
- array of lists of stringsFor "bunch of strings" use the middle one:
QStringList list {"abc", "xyz", "foo", "bar"};
If you want to pass it to some method then pass it via const reference, e.g.
void SomeClass::someMethod(const QStringList& list) { ... }
You didn't say what "ProcessCommand" is or what it returns, but to go over every element of a list you can simply use a range for loop:
for (const QString& s: list) { qDebug() << s; // s is a single string }
or use the older "STL style" iterator:
for (auto it = list.begin(); it != list.end(); ++it) { qDebug() << *it; // *it is a single string }
or "Java style" iterator:
QListIterator<QString> it(list); while (it.hasNext()) { qDebug() << = it.next(); // next() returns a reference to single string }
"Java style" just means this style of OOP programming, where you create an iterator object initialized with the container, was popular in Java language at some point, where C++ more commonly used the "STL style" type of iterators. Either one is fine. I would go for the range for loop, but any of those is fine.
wrote on 4 Mar 2023, 12:35 last edited by@Chris-Kawa Chris, I really appreciate your reply. I will freely admit - I have never fully understand the "passing by reference ..."
Here is my latest attempt and I would appreciate any suggestion to make it more C++ oriented.
I will eventually need to pass "multilevel array lists " using pointers....
However, I need to fully understand "single list " first...As you can see - there is no "&" and it works, but I am not sure why.
PS Reason I have the "iterator" twice - I am trying to find why my whole code does not do expected, so ignore it.
declaration QString ProcessCommand(char *, QStringList ); definition QString BT_Utility_Library::ProcessCommand ( char* command, QStringList verify ) { text = "Process command..."; text += Q_FUNC_INFO; qDebug() << text; //#ifdef BYPASS // verify list for (auto verify_list : verify) { text = "verify list "; text += verify_list; qDebug() << text; } //#endif // verify list for (auto verify_list : verify) { text = "verify list "; text += verify_list; qDebug() << text; }
-
@Chris-Kawa Chris, I really appreciate your reply. I will freely admit - I have never fully understand the "passing by reference ..."
Here is my latest attempt and I would appreciate any suggestion to make it more C++ oriented.
I will eventually need to pass "multilevel array lists " using pointers....
However, I need to fully understand "single list " first...As you can see - there is no "&" and it works, but I am not sure why.
PS Reason I have the "iterator" twice - I am trying to find why my whole code does not do expected, so ignore it.
declaration QString ProcessCommand(char *, QStringList ); definition QString BT_Utility_Library::ProcessCommand ( char* command, QStringList verify ) { text = "Process command..."; text += Q_FUNC_INFO; qDebug() << text; //#ifdef BYPASS // verify list for (auto verify_list : verify) { text = "verify list "; text += verify_list; qDebug() << text; } //#endif // verify list for (auto verify_list : verify) { text = "verify list "; text += verify_list; qDebug() << text; }
@AnneRanch said:
I have never fully understand the "passing by reference ..."
There's not much to it.
This makes an unnecessary copy of the parameter:QString ProcessCommand(char *, QStringList );
and this passes the parameter as is, meaning there's no copy:
QString ProcessCommand(char *, const QStringList& );
Both would work in your case, the first one is just slower.
-
@AnneRanch said:
I have never fully understand the "passing by reference ..."
There's not much to it.
This makes an unnecessary copy of the parameter:QString ProcessCommand(char *, QStringList );
and this passes the parameter as is, meaning there's no copy:
QString ProcessCommand(char *, const QStringList& );
Both would work in your case, the first one is just slower.
wrote on 5 Mar 2023, 16:10 last edited byI am way over my head again.
I have added two dimensional array and need to pass an access to specific one.
My call to function passes by compiler , but my iterator is now complaining about/mnt/RAID_124/PROJECTS_MAR3_CONFIG/CCC_SOURCE/BT_Utility_Library/bt_utility_library.cpp:108: error: expected expression
bt_utility_library.cpp:108:41: error: expected expression
for (auto verify_list : verify[]) {
^QString BT_Utility_Library::ProcessCommand ( char* command, QStringList verify[] ) { text = "Process command..."; text += Q_FUNC_INFO; qDebug() << text; text = "Command ..."; text += command; qDebug() << text; //#ifdef BYPASS // verify list for (auto verify_list : verify[]) { text = "verify list "; text += verify_list; qDebug() << text; }
This satisfied the compiler - temporary adding the index
for (auto verify_list : verify[1]) {
text = "verify list ";
text += verify_list;
qDebug() << text;Do i have to pass the array index as a parameter or is there a way i can retrieve it in the function itself ?
-
I am way over my head again.
I have added two dimensional array and need to pass an access to specific one.
My call to function passes by compiler , but my iterator is now complaining about/mnt/RAID_124/PROJECTS_MAR3_CONFIG/CCC_SOURCE/BT_Utility_Library/bt_utility_library.cpp:108: error: expected expression
bt_utility_library.cpp:108:41: error: expected expression
for (auto verify_list : verify[]) {
^QString BT_Utility_Library::ProcessCommand ( char* command, QStringList verify[] ) { text = "Process command..."; text += Q_FUNC_INFO; qDebug() << text; text = "Command ..."; text += command; qDebug() << text; //#ifdef BYPASS // verify list for (auto verify_list : verify[]) { text = "verify list "; text += verify_list; qDebug() << text; }
This satisfied the compiler - temporary adding the index
for (auto verify_list : verify[1]) {
text = "verify list ";
text += verify_list;
qDebug() << text;Do i have to pass the array index as a parameter or is there a way i can retrieve it in the function itself ?
Well first of all this is a very poor style. You shouldn't pass arrays without specifying their size. The function that takes the array has no way of knowing how big the array is so doing [0], [1] or anything like that is inherently dangerous, because you might be indexing out of the array. At the very least you should pass the size of the array too and check that you're not indexing above it.
But honestly, in modern C++ you shouldn't be using C arrays at all. C++ has a std::array type that knows the size. So instead of
QStringList foo[SIZE];
you would do
std::array<QStringList, SIZE> foo;
and you would have access to methods like
foo.size()
.As for indexing. This
for (auto verify_list : verify[])
basically means "hey compiler, iterate over something, but I'm not gonna tell you over what", so of course it's not gonna compile.
If you have an array of lists, so something like this:{ {"abc", "def"}, {"uvw", "xyz"} }
The compiler can't guess which row you want. You have to tell it.
If you want{"abc", "def"}
thenfor (const auto& verify_list : verify[0])
Note that I'm using
const auto&
like I mentioned before. Justauto
will do a lot of unnecessary copies.If you want
{"uvw", "xyz"}
thenfor (const auto& verify_list : verify[1])
If you want both then you need two loops:
for (int i=0; i < sizeOfTheArray; ++i) { for (const auto& verify_list : verify[i]) { // do stuff } }
and you have to pass
sizeOfTheArray
as an argument. If you used std::array you could just sayverify.size()
instead of passing size as argument.Do i have to pass the array index as a parameter or is there a way i can retrieve it in the function itself ?
If you want only one index then you have to know the index. I don't know your program or what it does, so I can't tell you where to get it from. You can pass it as a parameter, you can have a constant, you can have it as a member of your class... whatever you want.
But also, if you want just one list from the array I would just pass that one list as the argument and not the entire array. You wouldn't have to worry where to get the index from inside the function.
-
Well first of all this is a very poor style. You shouldn't pass arrays without specifying their size. The function that takes the array has no way of knowing how big the array is so doing [0], [1] or anything like that is inherently dangerous, because you might be indexing out of the array. At the very least you should pass the size of the array too and check that you're not indexing above it.
But honestly, in modern C++ you shouldn't be using C arrays at all. C++ has a std::array type that knows the size. So instead of
QStringList foo[SIZE];
you would do
std::array<QStringList, SIZE> foo;
and you would have access to methods like
foo.size()
.As for indexing. This
for (auto verify_list : verify[])
basically means "hey compiler, iterate over something, but I'm not gonna tell you over what", so of course it's not gonna compile.
If you have an array of lists, so something like this:{ {"abc", "def"}, {"uvw", "xyz"} }
The compiler can't guess which row you want. You have to tell it.
If you want{"abc", "def"}
thenfor (const auto& verify_list : verify[0])
Note that I'm using
const auto&
like I mentioned before. Justauto
will do a lot of unnecessary copies.If you want
{"uvw", "xyz"}
thenfor (const auto& verify_list : verify[1])
If you want both then you need two loops:
for (int i=0; i < sizeOfTheArray; ++i) { for (const auto& verify_list : verify[i]) { // do stuff } }
and you have to pass
sizeOfTheArray
as an argument. If you used std::array you could just sayverify.size()
instead of passing size as argument.Do i have to pass the array index as a parameter or is there a way i can retrieve it in the function itself ?
If you want only one index then you have to know the index. I don't know your program or what it does, so I can't tell you where to get it from. You can pass it as a parameter, you can have a constant, you can have it as a member of your class... whatever you want.
But also, if you want just one list from the array I would just pass that one list as the argument and not the entire array. You wouldn't have to worry where to get the index from inside the function.
wrote on 5 Mar 2023, 17:59 last edited by@Chris-Kawa Ok, as I thought - I need to pass the array index as a separate parameter so the iteration will go thru correct array. .
The iteration is limited to size of the array, so it is not in danger to "run over".
. -
@Chris-Kawa Ok, as I thought - I need to pass the array index as a separate parameter so the iteration will go thru correct array. .
The iteration is limited to size of the array, so it is not in danger to "run over".
.wrote on 6 Mar 2023, 08:30 last edited by@AnneRanch If you know that
ProcessCommand()
is just called with a single QStringList, it is better to have just a single QStringList as parameter and provide the correct QStringList from the array when calling this function. Then you don't have to pass the index to the function (ProcessCommand does not have any stakes in knowing it is processing an entry from an array).This would look like this:
// function declaration: QString BT_Utility_Library::ProcessCommand(char *command, const QStringList &verify); // calling the function BT_Utility_Library btul; char *command = ...; QStringList verify[MAX_LIST] = ...; ... btul.ProcessCommand(command, verify[0]);
Note that I again defined the QStringList parameter as reference. The difference to Java is that in Java everything is already a reference. This is why you don't have to specify it in Java. Almost always you are correct in using a const reference when passing objects. If you don't do this you will have copies all over the place which eventually slows down your application significantly.
-
wrote on 6 Mar 2023, 22:37 last edited by
One more question .
I am trying to have two dimensional array and cannot get the
for ( ....) to retrieve the members - it retrieves only the first sub array.// verify two dimensional list
for (auto &verify_list : *verify[index]) {
text = "verify list ";
text += verify_list;
qDebug() << text;
}then I get this error
/mnt/RAID_124/PROJECTS_MAR6_BAD_RECOVERY/CCC_SOURCE/BT_Utility_Library/bt_utility_library.cpp:95: error: indirection requires pointer operand ('QStringList' invalid)
bt_utility_library.cpp:95:40: error: indirection requires pointer operand ('QStringList' invalid)
for (auto &verify_list : *verify[index]) {
^~~~~~~~~~~~~~I do not know know how to implement "pointer operand" .
Help would be appreciated. -
One more question .
I am trying to have two dimensional array and cannot get the
for ( ....) to retrieve the members - it retrieves only the first sub array.// verify two dimensional list
for (auto &verify_list : *verify[index]) {
text = "verify list ";
text += verify_list;
qDebug() << text;
}then I get this error
/mnt/RAID_124/PROJECTS_MAR6_BAD_RECOVERY/CCC_SOURCE/BT_Utility_Library/bt_utility_library.cpp:95: error: indirection requires pointer operand ('QStringList' invalid)
bt_utility_library.cpp:95:40: error: indirection requires pointer operand ('QStringList' invalid)
for (auto &verify_list : *verify[index]) {
^~~~~~~~~~~~~~I do not know know how to implement "pointer operand" .
Help would be appreciated.@AnneRanch
indirection requires pointer operand
This means
*
(indirection operator) can be used on pointers and what you have here is QStringList, so not a pointer. You don't need*
here.it retrieves only the first sub array
See my previous response where I posted how to iterate over both dimensions.
for (auto &verify_list : *verify[index]) {
text = "verify list ";
text += verify_list;
qDebug() << text;
}Note that you're overwriting text in each loop iteration. If you want to join the strings from the list and display it as one string you would do it like this:
QString joined = verify[index].join(' '); qDebug() << joined;
If you want to display each string separately do it like this:
for (const auto& str : verify[index]) { text = "verify list " + str; qDebug() << text; }
-
wrote on 7 Mar 2023, 00:40 last edited by
@Chris-Kawa said in How to pass and simply iterate...C/C++:
for (const auto& verify_list : verify[0])
Here is my problem
'debug (verify) clearly reads correct array - index[1] , but the iterator (verify_list)
"prints" the wrong one - index [0] .What am I doing wrong?
-
@Chris-Kawa said in How to pass and simply iterate...C/C++:
for (const auto& verify_list : verify[0])
Here is my problem
'debug (verify) clearly reads correct array - index[1] , but the iterator (verify_list)
"prints" the wrong one - index [0] .What am I doing wrong?
Lifetime Qt Championwrote on 7 Mar 2023, 01:34 last edited by Chris Kawa 3 Jul 2023, 01:35@AnneRanch I see nothing wrong. From what I can tell from your picture the content of your structure is:
verify[0]
isQStringList { "Discovery started", "SPP_CA" }
verify[1]
isQStringList { "Controller", "Agent registered" }
The debugger shows
index
is 1 so the output showsverify list Controller verify list Agent registered
as expected. Are you maybe confused about what
*verify
is in the debug window? Since it's an array*verify
is the same asverify[0]
, so it's all as expected. -
@AnneRanch I see nothing wrong. From what I can tell from your picture the content of your structure is:
verify[0]
isQStringList { "Discovery started", "SPP_CA" }
verify[1]
isQStringList { "Controller", "Agent registered" }
The debugger shows
index
is 1 so the output showsverify list Controller verify list Agent registered
as expected. Are you maybe confused about what
*verify
is in the debug window? Since it's an array*verify
is the same asverify[0]
, so it's all as expected.wrote on 7 Mar 2023, 05:02 last edited by Anonymous_Banned275 3 Jul 2023, 05:04Here is how the array looks and under index 1 the iterator should return
"Discovery started ' and "SPP_CA" - it does not. iT returns index 0.
. -
Here is how the array looks and under index 1 the iterator should return
"Discovery started ' and "SPP_CA" - it does not. iT returns index 0.
.Lifetime Qt Championwrote on 7 Mar 2023, 05:18 last edited by Chris Kawa 3 Jul 2023, 05:20@AnneRanch But that's not the same thing as what you have on the previous screenshot, so either the contents of the array are changing each time or I don't know what you're posting, because those two posts don't match.
And what iterator are you talking about? There are no iterators in that for loop you posted previously.You do a lot of copy pasting. Maybe you have two different variables with the same name in different places or something?
-
@AnneRanch But that's not the same thing as what you have on the previous screenshot, so either the contents of the array are changing each time or I don't know what you're posting, because those two posts don't match.
And what iterator are you talking about? There are no iterators in that for loop you posted previously.You do a lot of copy pasting. Maybe you have two different variables with the same name in different places or something?
wrote on 7 Mar 2023, 17:01 last edited by Chris Kawa 3 Jul 2023, 17:21@Chris-Kawa I am making some very basic mistake defining the array, but I just cannot see it.
I have added plain for(...) loop and forced the verify index to 0 and 1
The plain loop results does not make sense - the results are "reversed " .
The key . in my opinion, is in my definition of the two dimensional array- somewhere I am making a mistake ...
//#ifdef BYPASS // verify two dimensional list' for (const auto& verify_list : verify[index]) { //for (const auto &verify_list : *verify[index]) { text = "verify list "; text += verify_list; qDebug() << text; } int size = 2; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[index][Loop_index]; qDebug() << text; } text = "Process index...zero "; text += QString::number(index); // _FUNC_INFO; qDebug() << text; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[0][Loop_index]; qDebug() << text; } text = "Process index...one "; text += QString::number(index); // _FUNC_INFO; qDebug() << text; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[1][Loop_index]; qDebug() << text; } return result;
"Process command...QString BT_Utility_Library::ProcessCommand_Index(char *, QStringList *, int)" "Process command...QString BT_Utility_Library::ProcessCommand_Index(char *, QStringList *, int)" "Process index...1" "verify list Controller" "verify list Agent registered" "Controller" "Agent registered" "Process index...zero 1" "Discovery started" "SPP_CA" "Process index...one 1" "Controller" "Agent registered" "void MainWindow_Bluetooth::Process_Menu_Index(int)"
#define MAX_ARRAY_VERIFY 16 QStringList verify[MAX_ARRAY_VERIFY] = { { // verify Agent registered "Controller", "Agent registered" }, { // verify Agent registered // temporqry MN "Discovery started", "SPP_CA" }, { // verify Agent registered "Controller", "Agent registered" } };
-
@Chris-Kawa I am making some very basic mistake defining the array, but I just cannot see it.
I have added plain for(...) loop and forced the verify index to 0 and 1
The plain loop results does not make sense - the results are "reversed " .
The key . in my opinion, is in my definition of the two dimensional array- somewhere I am making a mistake ...
//#ifdef BYPASS // verify two dimensional list' for (const auto& verify_list : verify[index]) { //for (const auto &verify_list : *verify[index]) { text = "verify list "; text += verify_list; qDebug() << text; } int size = 2; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[index][Loop_index]; qDebug() << text; } text = "Process index...zero "; text += QString::number(index); // _FUNC_INFO; qDebug() << text; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[0][Loop_index]; qDebug() << text; } text = "Process index...one "; text += QString::number(index); // _FUNC_INFO; qDebug() << text; for(int Loop_index =0; Loop_index != size ; Loop_index++) { text = verify[1][Loop_index]; qDebug() << text; } return result;
"Process command...QString BT_Utility_Library::ProcessCommand_Index(char *, QStringList *, int)" "Process command...QString BT_Utility_Library::ProcessCommand_Index(char *, QStringList *, int)" "Process index...1" "verify list Controller" "verify list Agent registered" "Controller" "Agent registered" "Process index...zero 1" "Discovery started" "SPP_CA" "Process index...one 1" "Controller" "Agent registered" "void MainWindow_Bluetooth::Process_Menu_Index(int)"
#define MAX_ARRAY_VERIFY 16 QStringList verify[MAX_ARRAY_VERIFY] = { { // verify Agent registered "Controller", "Agent registered" }, { // verify Agent registered // temporqry MN "Discovery started", "SPP_CA" }, { // verify Agent registered "Controller", "Agent registered" } };
Lifetime Qt Championwrote on 7 Mar 2023, 17:39 last edited by Chris Kawa 3 Jul 2023, 17:40@AnneRanch That output does not match the code. You must be iterating over a different array or
verify
in the loops is not the same variable as the one in the array declaration.Where do you get the
verify
variable? Is it still from the function argument
ProcessCommand ( char* command, QStringList verify[] )
?
What do you pass to that function when you call it? Maybe you passed a pointer to second element by mistake.Put this just before the first loop:
qDebug() << verify[0] << verify[1] << verify[2];
to make sure the contents of the array are what you think they are, because it looks like the array you are actually iterating over doesn't have that first list in it.
-
@AnneRanch That output does not match the code. You must be iterating over a different array or
verify
in the loops is not the same variable as the one in the array declaration.Where do you get the
verify
variable? Is it still from the function argument
ProcessCommand ( char* command, QStringList verify[] )
?
What do you pass to that function when you call it? Maybe you passed a pointer to second element by mistake.Put this just before the first loop:
qDebug() << verify[0] << verify[1] << verify[2];
to make sure the contents of the array are what you think they are, because it looks like the array you are actually iterating over doesn't have that first list in it.
wrote on 7 Mar 2023, 19:07 last edited by@Chris-Kawa ```
Found it and as expected it was a very stupid mistake.
I have changed the array to a class available, but I was passing it indexed - as local variable - to my function.
Hence when I passed index 1 it became FIRST entry - 0 - in my test iteration...
Chris , thanks very much for all you help.
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
"void MainWindow::menu_slot_indexed(int)"
"add it as subwindow "
"Run bluetootctl... \n void MainWindow_Bluetooth::on_actionBluetooth_service_enable_triggered()"
"void MainWindow_Bluetooth::Process_Menu_Index(int)"
("Controller", "Agent registered") ("Discovery started", "SPP_CA") ("Controller", "Agent registered")
"1"
"Process command...QString BT_Utility_Library::ProcessCommand_Index(char *, QStringList *, int)"
("Discovery started", "SPP_CA") ("Controller", "Agent registered") ()
"void MainWindow_Bluetooth::Process_Menu_Index(int)"
1/17