Почему бы не сделать:
void f<T>(T o1, T o2) {
if (o1.GetType() != o2.GetType()) return;
// can I assert that t is not null ??
}
Для того, что я понимаю, вы хотите, проверив if (o1.GetType() != o2.GetType()) return;
, чтобы убедиться, что o2
имеет тип T
, а не производный тип. Так что o2
должно быть типа T
, и у вас нет проблем с приведением типов.
Я бы предложил лучший способ сделать это - перевернуть строку и сравнить первые n символов.
Существует множество примеров использования функций перестановки строк (даже Джоэл называет это стандартным вопросом для интервью), поэтому просто реализуйте один из них, затем выполните шаг для сравнения перевернутых строк.
РЕДАКТИРУЙТЕ в ответ на отрицательные голоса. Хорошо, да, этот подход требует дополнительного ЦП или памяти для реализации, но спрашивающий не указывает никаких таких ограничений, и он явно попросил элегантное решение. Реверсирование струн и сравнение спереди гораздо более элегантно, чем возиться с поиском конца струн и работать в обратном направлении. И следующему программисту намного проще понять и поддерживать тоже.
Не вызывайте strlen более одного раза для каждой строки.
int EndsWith(const char *str, const char *suffix)
{
if (!str || !suffix)
return 0;
size_t lenstr = strlen(str);
size_t lensuffix = strlen(suffix);
if (lensuffix > lenstr)
return 0;
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
int EndsWithFoo(const char *str) { return EndsWith(str, ".foo"); }
EDIT: добавлена проверка NULL для педантичного. Для ультрапедантичного, обсудите, должен ли он возвращать ненулевое значение, если и str, и суффикс имеют значение NULL.
Если всегда есть что-то за точкой, мы могли бы потворствовать некоторой арифметике указателей:
int EndsWithFoo (char *str)
{
int iRetVal = 0;
char * pchDot = strrchr (str, '.');
if (pchDot)
{
if (strcmp (pchDot+1, "foo") == 0)
{
iRetVal = 1;
}
}
return iRetVal;
}
Конечно, вы, вероятно, хочу добавить немного strlen, чтобы проверить, есть ли что-то за точкой: -)
NB - я не запускал это, чтобы проверить это, но для меня это выглядит нормально.
Может быть ...
bool endswith (const char* str, const char* tail)
{
const char* foo = strrstr (str, tail);
if (foo)
{
const int strlength = strlen (str);
const int taillength = strlen (tail);
return foo == (str + strlength - taillength);
}
return false;
}
endswith (str, ".foo");
Кстати, решение в оригинальном вопросе выглядит отлично, кроме повторяющегося strlen вызовы.
Вы также можете обобщить следующим образом:
int endsWith(const char* text, const char* extn)
{
int result = 1;
int len = strlen(text);
int exprLen = strlen(extn);
int index = len-exprLen;
int count = 0;
if(len > exprLen)
{
for( ; count < exprLen; ++count)
{
if(text[index + count] != extn[count])
{
result = 0;
break;
}
}
}
else
{
result = 0;
}
return result;
}
Протестированный код, включает в себя тест:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ends_with_foo(const char *str)
{
char *dot = strrchr(str, '.');
if (NULL == dot) return 0;
return strcmp(dot, ".foo") == 0;
}
int main (int argc, const char * argv[])
{
char *test[] = { "something", "anotherthing.foo" };
int i;
for (i = 0; i < sizeof(test) / sizeof(char *); i++) {
printf("'%s' ends %sin '.foo'\n",
test[i],
ends_with_foo(test[i]) ? "" : "not ");
}
return 0;
}
strlen (". Foo")
не требуются. Если вы действительно хотите, чтобы он был гибким, вы могли бы использовать sizeof ".foo" - 1
- постоянную времени компиляции.
Кроме того, проверка на нулевую строку была бы хорошей.
Если вы можете изменить сигнатуру своей функции, попробуйте изменить ее на
int EndsWith(char const * str, char const * suffix, int lenstr, int lensuf);
. Это приведет к повышению безопасности. , более многократно используемый и более эффективный код:
Мы можем определить функцию следующим образом:
int EndsWith(char const * str, char const * suffix, int lenstr, int lensuf)
{
if( ! str && ! suffix ) return 1;
if( ! str || ! suffix ) return 0;
if( lenstr < 0 ) lenstr = strlen(str);
if( lensuf < 0 ) lensuf = strlen(suffix);
return strcmp(str + lenstr - lensuf, suffix) == 0;
}
Очевидный контраргумент для дополнительных параметров заключается в том, что они подразумевают больше шума в коде или менее выразительный код .
У меня нет доступа к компилятору прямо сейчас, так может кто-нибудь сказать мне, если это работает?
#include <stdio.h>
#include <string.h>
int EndsWithFoo(const char* s);
int
main(void)
{
printf("%d\n", EndsWithFoo("whatever.foo"));
return 0;
}
int EndsWithFoo(const char* s)
{
int ret = 0;
if (s != NULL)
{
size_t size = strlen(s);
if (size >= 4 &&
s[size-4] == '.' &&
s[size-3] == 'f' &&
s[size-2] == 'o' &&
s[size-1] == 'o')
{
ret = 1;
}
}
return ret;
}
В любом случае, убедитесь, что параметр квалифицирован как const
, он говорит всем (включая компилятор), что вы не собираетесь изменять строку.
int EndsWithFoo( char *string )
{
string = strrchr(string, '.');
if( string != NULL )
return( strcmp(string, ".foo") );
return( -1 );
}
Вернет 0, если заканчивается ".foo".