mersenneforum.org Simple C/C++ programming questions (mostly about arrays)
 Register FAQ Search Today's Posts Mark Forums Read

 2019-06-26, 22:48 #1 ixfd64 Bemusing Prompter     "Danny" Dec 2002 California 45568 Posts Simple C/C++ programming questions (mostly about arrays) I recently started working on small improvements for mfakto. I'm a little embarrassed to ask these questions, but it's been quite a while since I worked with C/C++. 1. How can I do a foreach loop through an array of C strings in C++? I'm defining strings using char pointers (to keep consistency with mfakto) and arrays of strings like this: Code: char *str_arr[] = { "blah", "blah blah", ... } However, for (char *s : str_arr) results in a compiler error. What's the syntax of a foreach loop in this case? 2. I also want to get the number of elements in an array of strings. However, sizeof() always returns 8 as I'm defining strings using char pointers. sizeof(str_arr)/sizeof(str_arr[0]) doesn't work either and always returns 1. Is there another solution? 3. This is more of a question about style: I have an array of strings (mainly GPU names) that only need to be accessed once. Is it OK to move them to the header file? Thanks! Last fiddled with by ixfd64 on 2019-06-26 at 22:51
2019-06-27, 01:54   #2
rogue

"Mark"
Apr 2003
Between here and the

2·3,217 Posts

Quote:
 Originally Posted by ixfd64 I recently started working on small improvements for mfakto. I'm a little embarrassed to ask these questions, but it's been quite a while since I worked with C/C++. 1. How can I do a foreach loop through an array of C strings in C++? I'm defining strings using char pointers (to keep consistency with mfakto) and arrays of strings like this: Code: char *str_arr[] = { "blah", "blah blah", ... } However, for (char *s : str_arr) results in a compiler error. What's the syntax of a foreach loop in this case? 2. I also want to get the number of elements in an array of strings. However, sizeof() always returns 8 as I'm defining strings using char pointers. sizeof(str_arr)/sizeof(str_arr[0]) doesn't work either and always returns 1. Is there another solution? 3. This is more of a question about style: I have an array of strings (mainly GPU names) that only need to be accessed once. Is it OK to move them to the header file? Thanks!
You can use vector<string> and add members to the vector in a constructor (or in main()). You can loop with an iterator object and use size() to get the number of elements. Here is an example (assuming I didn't fubar it in some way):

Code:
   vector<string>::iterator it = myVector.begin();
string element;

while (it != myVector.end())
{
element = *it;
. . . do something with element . . .
it++;
}
You can also use a string (or char *) array like you have, but use NULL as the last member of the array.

You could also use:

Code:
char *str_arr[MY_ARRAY_SIZE] = {
"blah",
"blah blah",
...
}
and #define MY_ARRAY_SIZE if you know that the number of elements in the array won't change.

Question, why do you need an array of GPU names? Assuming that you are writing some logic in your C/C++ to determine which GPU code to execute, there must be some APIs where you can ask the GPU what features it supports.

BTW, is your source open? Is it possible that you could build your code upon the mtsieve framework (which supports OpenCL workers)? That might save you a lot of work if you are rewriting your C/C++.

 2019-06-27, 07:07 #3 Nick     Dec 2012 The Netherlands 175110 Posts 1. At a C level, if you mark the end of the array with a 0 (or NULL) then you could do it like this: Code: char *str_arr[ ] = { "blah", "blah blah", ...,0 }; int n; for (n=0;str_arr[n];++n) { ...use str_arr[n]... } 2. Do you mean the number of elements allocated or the number in use? The basic C level array does not remember its own size. You would have to store it separately (or use a constant value if it doesn't change). 3. If I remember correctly, putting initial values in a variable makes the declaration a definition which therefore reserves storage. You don't want this to be done by every file including the header! Last fiddled with by Nick on 2019-06-27 at 07:13 Reason: Typo
2019-06-27, 12:18   #4
Chris Card

Aug 2004

2×5×13 Posts

Quote:
 Originally Posted by ixfd64 I recently started working on small improvements for mfakto. I'm a little embarrassed to ask these questions, but it's been quite a while since I worked with C/C++. 1. How can I do a foreach loop through an array of C strings in C++? I'm defining strings using char pointers (to keep consistency with mfakto) and arrays of strings like this: Code: char *str_arr[] = { "blah", "blah blah", ... } However, for (char *s : str_arr) results in a compiler error. What's the syntax of a foreach loop in this case? 2. I also want to get the number of elements in an array of strings. However, sizeof() always returns 8 as I'm defining strings using char pointers. sizeof(str_arr)/sizeof(str_arr[0]) doesn't work either and always returns 1. Is there another solution? 3. This is more of a question about style: I have an array of strings (mainly GPU names) that only need to be accessed once. Is it OK to move them to the header file? Thanks!
This works fine for me using gcc 8.3.1
Code:
#include <iostream>

int main(int argc, char* argv[])
{
const char* str_arr[] = { "blah", "blah blah", "a b c d e" };
for (const char* s : str_arr)
{
std::cout << s << std::endl;
}

return 0;
}

2019-06-27, 23:31   #5
ixfd64
Bemusing Prompter

"Danny"
Dec 2002
California

2·17·71 Posts

Quote:
 Originally Posted by rogue Question, why do you need an array of GPU names? Assuming that you are writing some logic in your C/C++ to determine which GPU code to execute, there must be some APIs where you can ask the GPU what features it supports. BTW, is your source open? Is it possible that you could build your code upon the mtsieve framework (which supports OpenCL workers)? That might save you a lot of work if you are rewriting your C/C++.
I'm trying to make the GPU detection code in mfakto more organized. Currently, the code looks like this:

Code:
if (strstr(deviceinfo.d_name, "Capeverde")  ||    // 7730, 7750, 7770, 8760, 8740, R7 250X
strstr(deviceinfo.d_name, "Pitcairn")   ||    // 7850, 7870, 8870
strstr(deviceinfo.d_name, "Bonaire")    ||    // 7790, R7 260, R7 260X
strstr(deviceinfo.d_name, "Oland")      ||    // 8670, 8570, R9 240, R9 250
strstr(deviceinfo.d_name, "Sun")        ||    // 85x0M
strstr(deviceinfo.d_name, "Mars")       ||    // 86x0M, 87x0M
strstr(deviceinfo.d_name, "Venus")      ||    // 88x0M
strstr(deviceinfo.d_name, "Saturn")     ||    // 8930M, 8950M
strstr(deviceinfo.d_name, "Neptune")    ||    // 8970M, 8990M
strstr(deviceinfo.d_name, "Curacao")    ||    // R9 265, R9 270, R9 270X
strstr(deviceinfo.d_name, "Tonga")      ||    // R9 285
strstr(deviceinfo.d_name, "Hainan")      ||    // R9 285
strstr(deviceinfo.d_name, "Kalindi")          // GCN APU, Kabini, R7 ???
)
{
mystuff.gpu_type = GPU_GCN;
}
I want to make it so that the GPU names are in an array of strings, so anyone who wants to make changes only has to add a string to an array instead of having to modify the conditionals. It won't make a big difference to developers, but I think it's good programming practice.

Quote:
 This works fine for me using gcc 8.3.1 Code: #include int main(int argc, char* argv[]) { const char* str_arr[] = { "blah", "blah blah", "a b c d e" }; for (const char* s : str_arr) { std::cout << s << std::endl; } return 0; }
Unfortunately, this doesn't work for me. I'm getting the following error:

Code:
cannot build range expression with array function
parameter 'device_class' since parameter with array type 'char *[]' is
treated as pointer type 'char **'
This is my code for reference:

Code:
const char *TYPE_GCN[] = {
"Capeverde",
"Pitcairn",
"Bonaire",
"Oland",
"Sun",
"Mars",
"Venus",
"Saturn",
"Neptune",
"Curacao",
"Tonga",
"Hainan",
"Kalindi"
};

[...]

/* check if device name contains a string in the array */
int name_contains(char *device_name, char *device_class[]) {
for (const char *device : device_class) {
if (strstr(device_name, device)) {
return 1;
}
}
return 0;
}

Last fiddled with by ixfd64 on 2019-06-27 at 23:40

 2019-06-27, 23:58 #6 ewmayer ∂2ω=0     Sep 2002 República de California 101101100011002 Posts As others have noted sizeof() is useless for getting number of array elements. In that sense, a C++ vector is preferable. Strictly in C, you need some kind of end-of-array sentinel. Here an example using an empty string (which will still occupy storage via the resulting string-terminator char), with 2 ways to iterate over the string array: Code: #include #include #define STRNEQ(s1,s2) ( strcmp(s1,s2)) int main() { char *str_arr[] = {"foo","bar",""}; char **curr_str; for(curr_str = str_arr; STRNEQ(*curr_str,""); curr_str++) printf("curr_strA = %s\n",*curr_str); int i; for(i = 0; STRNEQ(str_arr[i],""); i++) printf("curr_strB = %s\n",str_arr[i]); return 0; }
 2019-06-28, 00:42 #7 rogue     "Mark" Apr 2003 Between here and the 2×3,217 Posts Making a check for specific GPU names is not future-proof. For OpenCL you can use clGetDeviceInfo() to determine the features available to the GPU. You can then use those features to determine which kernel you want to execute. My knowledge of OpenCL is only strong enough for me to use it with some of the programs using the mtsieve framework. I wouldn't be surprised if your OpenCL skills were much better.
2019-06-28, 01:21   #8
ixfd64
Bemusing Prompter

"Danny"
Dec 2002
California

2·17·71 Posts

Quote:
 Originally Posted by rogue Making a check for specific GPU names is not future-proof. For OpenCL you can use clGetDeviceInfo() to determine the features available to the GPU. You can then use those features to determine which kernel you want to execute.
Thanks for the information. That looks like an even better way to handle kernel features.

Quote:
 My knowledge of OpenCL is only strong enough for me to use it with some of the programs using the mtsieve framework. I wouldn't be surprised if your OpenCL skills were much better.
Unfortunately, I actually don't have any OpenCL experience at all. :\

Last fiddled with by ixfd64 on 2019-06-28 at 01:29

2019-06-28, 08:01   #9
ldesnogu

Jan 2008
France

2·52·11 Posts

Quote:
 Originally Posted by ewmayer As others have noted sizeof() is useless for getting number of array elements. In that sense, a C++ vector is preferable. Strictly in C, you need some kind of end-of-array sentinel. Here an example using an empty string (which will still occupy storage via the resulting string-terminator char), with 2 ways to iterate over the string array: Code: #include #include #define STRNEQ(s1,s2) ( strcmp(s1,s2)) int main() { char *str_arr[] = {"foo","bar",""}; char **curr_str; for(curr_str = str_arr; STRNEQ(*curr_str,""); curr_str++) printf("curr_strA = %s\n",*curr_str); int i; for(i = 0; STRNEQ(str_arr[i],""); i++) printf("curr_strB = %s\n",str_arr[i]); return 0; }
You don't really need a sentinel for an array declared at compile time. You can get the numbers of elements with something like sizeof(array)/sizeof(array[0]):
Code:
#include <stdio.h>

int main()
{
char *str_arr[] = {"foo","bar"};
for (int i = 0; i < sizeof(str_arr) / sizeof(str_arr[0]); i++)
printf("curr_strA = %s\n", str_arr[i]);
return 0;
}

Last fiddled with by ldesnogu on 2019-06-28 at 08:04

2019-06-28, 13:34   #10
rogue

"Mark"
Apr 2003
Between here and the

2×3,217 Posts

Quote:
 Originally Posted by ixfd64 Thanks for the information. That looks like an even better way to handle kernel features. Unfortunately, I actually don't have any OpenCL experience at all. :\
In that case I might be able to help you. Feel free to reach out to me via PM.

2019-06-28, 23:43   #11
ixfd64
Bemusing Prompter

"Danny"
Dec 2002
California

1001011011102 Posts

Quote:
 Originally Posted by ldesnogu You can get the numbers of elements with something like sizeof(array)/sizeof(array[0]): Code: #include int main() { char *str_arr[] = {"foo","bar"}; for (int i = 0; i < sizeof(str_arr) / sizeof(str_arr[0]); i++) printf("curr_strA = %s\n", str_arr[i]); return 0; }
I tried that too, but it always returns 1.

 Similar Threads Thread Thread Starter Forum Replies Last Post siegert81 Factoring 12 2016-05-28 18:36 Xyzzy Programming 76 2015-01-24 04:35 pinhodecarlos Programming 2 2012-07-23 18:17 lorgix Miscellaneous Math 9 2010-12-08 22:22 alaa Homework Help 12 2007-06-12 22:17

All times are UTC. The time now is 04:16.

Mon Oct 25 04:16:24 UTC 2021 up 93 days, 22:45, 0 users, load averages: 1.26, 1.52, 1.41