\$\begingroup\$
\$\endgroup\$
3
I want to change the legacy C-style code by using stl:
for (posEmptyItem = startAt; strlen(collection[posEmptyItem]) > 10; posEmptyItem++) {}
std::cout << posEmptyItem << std::endl;
This code seems a bit hard to read. Anyway to do better?
auto it = std::find_if(collection + startAt,
collection + COLLECTION_SIZE,
[](const char* line) { return strlen(line) <= 10; });
int idx = std::distance(collection, it);
Below a complete example:
#include <cstring>
#include <iostream>
#include <algorithm>
#define COLLECTION_SIZE 250
int main()
{
const char* collection[COLLECTION_SIZE]{ "time11,time2,time3",
"time12,time2,time3",
"time13,time2,time3",
"time14,time2,time3",
"time15,time2,time3",
"x\n",
"" };
auto startAt = 2;
int posEmptyItem;
// legacy code
for (posEmptyItem = startAt; strlen(collection[posEmptyItem]) > 10; posEmptyItem++) {}
std::cout << posEmptyItem << std::endl;
// replace the loop to search an index by calling to standard library
auto it = std::find_if(collection + startAt,
collection + COLLECTION_SIZE,
[](const char* line) { return strlen(line) <= 10; });
posEmptyItem = std::distance(collection, it);
std::cout << posEmptyItem << std::endl;
return 0;
}
200_success
146k22 gold badges190 silver badges478 bronze badges
1 Answer 1
\$\begingroup\$
\$\endgroup\$
4
For "easier readability" you could extern the lambda expression form the find_if()
:
auto pred = [](const char* line) { return strlen(line) <= 10; };
auto it = std::find_if(collection + startAt,
collection + COLLECTION_SIZE,
pred);
Also make use of std::begin()
and std::end()
:
auto it = std::find_if(std::begin(collection) + startAt,
std::end(collection),
pred);
At least (but probably not last), don't use raw arrays. Rather change collection
to a std::array
:
std::array<const char*,COLLECTION_SIZE> collection
{ "time11,time2,time3"
, "time12,time2,time3"
, "time13,time2,time3"
, "time14,time2,time3"
, "time15,time2,time3"
, "x\n"
, ""
};
// Note my formatting style above, which makes it easier to extend the array
Here's the fully refactored code:
#include <cstring>
#include <iostream>
#include <algorithm>
#include <array>
const size_t COLLECTION_SIZE = 250; // rather use a const variable than a macro
int main()
{
std::array<const char*,COLLECTION_SIZE> collection
{ "time11,time2,time3"
, "time12,time2,time3"
, "time13,time2,time3"
, "time14,time2,time3"
, "time15,time2,time3"
, "x\n"
, ""
};
size_t startAt = 2; // care about the correct type. auto would leave you with int
// replace the loop to search an index by calling to standard library
auto pred = [](const char* line) { return strlen(line) <= 10; };
auto it = std::find_if(std::begin(collection) + startAt,
std::end(collection),
pred);
auto posEmptyItem = std::distance(std::begin(collection), it);
std::cout << posEmptyItem << std::endl;
return 0;
}
answered May 11, 2017 at 18:25
-
\$\begingroup\$ Thanks for your help. I am learning the standard library and want to be check that my code is ok. \$\endgroup\$Less White– Less White2017年05月11日 18:28:10 +00:00Commented May 11, 2017 at 18:28
-
\$\begingroup\$ @LessWhite if you find the answer helpful you can upvote it ;-) \$\endgroup\$t3chb0t– t3chb0t2017年05月11日 18:35:04 +00:00Commented May 11, 2017 at 18:35
-
\$\begingroup\$ I don't think that
std::array
is a good substitute. No type traits work on it, even (ironically)std::is_array
. \$\endgroup\$Incomputable– Incomputable2017年05月11日 20:16:51 +00:00Commented May 11, 2017 at 20:16 -
\$\begingroup\$ @Incomputable Feel free to make a better proposal for that particular case. \$\endgroup\$πάντα ῥεῖ– πάντα ῥεῖ2017年05月11日 20:17:53 +00:00Commented May 11, 2017 at 20:17
lang-cpp
std::distance
(I don't get where you did gettingstd::dist
from. Maybe a MSVC specific typedef??) \$\endgroup\$