#include <stdlib.h>
#include <iostream>
#include <cstdint>
#include <cstring>
using namespace std;
/*
Simplify the implementation below as much as you can.
Even better if you can also improve performance as part of the simplification!
FYI: This code is over 35 lines and over 300 tokens, but it can be written in
5 lines and in less than 60 tokens.
*/
char *func1(char *s, char a, char b)
{
char *aptr;
char *bptr;
char *res;
int i;
if (s[0] == '\0')
{
if ((a == '\0') || (b == '\0'))
return &(s[0]);
else
return NULL;
}
i = 0;
aptr = NULL;
bptr = NULL;
while (aptr == NULL && bptr == NULL)
{
if (s[i] == a)
aptr = s + i;
if (s[i] == b)
bptr = s + i;
if (s[i] == '\0')
{
if ((aptr != s + i) && (bptr != s + i))
return NULL;
}
i++;
}
if (aptr == NULL)
res = bptr;
else if (bptr == NULL)
res = aptr;
else if (aptr < bptr)
res = aptr;
else if (bptr < aptr)
res = bptr;
else
res = aptr;
return res;
}
//-----------------------------------------------------------------------------------
char *func2(char *s, char a, char b) {
char *aptr = strchr(s, a),
*bptr = strchr(s, b);
return 0 == strlen(s) ? (((a == 0) || (b == 0)) ? s : NULL) :
((NULL == aptr) && (NULL == bptr)) ? NULL :
aptr == NULL ? bptr :
bptr == NULL ? aptr :
bptr < aptr ? bptr : aptr;
}
//-----------------------------------------------------------------------------------
struct test {
const char *str;
char a, b;
friend inline ostream& operator << (ostream& stream, test& obj) {
stream << '<' << (obj.str ? obj.str : "NULL") << "|'";
if (isprint(obj.a)) stream << obj.a;
else stream << '\\' << int(obj.a);
stream << "'|'";
if (isprint(obj.b)) stream << obj.b;
else stream << '\\' << int(obj.b);
stream << "'>";
return stream;
}
};
void strshow(char* s, const char* s1) {
if (NULL == s) cout << "NULL";
else if ('\0' == *s) cout << "\"\"";
else cout << (char)*s << "[" << s - s1 << "]";
}
int main(int argc, char **argv) {
test at[] = {
{ "123456789", '7', '3' },
{ "123456789", '7', '8' },
{ "123455432", '7', '3' },
{ "123456789", '5', 'A' },
{ "123456789", 'B', '6' },
{ "123456789", 'x', 'y' },
{ "", 2, 3 },
{ "", 5, 0 },
};
for (int i = 0; i < sizeof(at) / sizeof(at[0]); i++) {
char *pf1 = func1((char*)at[i].str,
at[i].a, at[i].b),
*pf2 = func2((char*)at[i].str,
at[i].a, at[i].b);
cout << i + 1 << " : " << at[i] << " => ";
strshow(pf1, at[i].str);
cout << " ... ";
strshow(pf2, at[i].str);
cout << endl;
}
return 0;
}
Ну и результат выполнения теста тогда нужно показать для полноты картины:
$ ./strsimpl
1 : => 3[2] ... 3[2]
2 : => 7[6] ... 7[6]
3 : => 3[2] ... 3[2]
4 : => 5[4] ... 5[4]
5 : => 6[5] ... 6[5]
6 : => NULL ... NULL
7 : => NULL ... NULL
8 : => "" ... ""
Кстати…
Наши израильские друзья считают такое решение неверным – они мечтали о чём-то более кошерном ;-)
Хотя, с другой стороны, я считаю, что они просто не умеют точно формулировать свои мечты о кошерности.
Вот дословно их условие задачи:
Simplify the implementation below as much as you can.
Even better if you can also improve performance as part of the simplification!
FYI: This code is over 35 lines and over 300 tokens, but it can be written in 5 lines and in less than 60 tokens.
Тестирование показывает полную эквивалентность func1() и func2().
Тем не менее, этот эпизод подсказывает, что задача может иметь несколько интересных вариантов решения. Предлагаю желающим активно заняться их поисками!
Задача состоит в оптимизации кода, ваше же решение обычное переписывание предложенного алгоритма с целью уменьшения количества строк.
” код задачи нужно бы упростить почти не разбираясь что этот код должен делать — по правилам формального синтаксиса C++.”
Но это не очень соответствует условию в самом задании – там вроде нужно упростить саму реализацию. А значит, следует сначала постараться понять смысл функции, и тогда лучшее решение станет очевидным:
Чуть-чуть поправил. В вашем варианте, не проверяется условие, когда один из параметров a и b равен ‘\0′, а второй не найден в s, а параметр s != “\0”.
short i=0;
do {
if (s[i]==a || s[i]==b) return s+i;
} while (s[i++]!=’\0’);
return NULL;