Как сравнить концы строк в C?

Почему бы не сделать:

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, и у вас нет проблем с приведением типов.

34
задан 13 April 2009 в 17:51
поделиться

10 ответов

Я бы предложил лучший способ сделать это - перевернуть строку и сравнить первые n символов.

Существует множество примеров использования функций перестановки строк (даже Джоэл называет это стандартным вопросом для интервью), поэтому просто реализуйте один из них, затем выполните шаг для сравнения перевернутых строк.

РЕДАКТИРУЙТЕ в ответ на отрицательные голоса. Хорошо, да, этот подход требует дополнительного ЦП или памяти для реализации, но спрашивающий не указывает никаких таких ограничений, и он явно попросил элегантное решение. Реверсирование струн и сравнение спереди гораздо более элегантно, чем возиться с поиском конца струн и работать в обратном направлении. И следующему программисту намного проще понять и поддерживать тоже.

-3
ответ дан 27 November 2019 в 16:36
поделиться

Не вызывайте 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.

47
ответ дан 27 November 2019 в 16:36
поделиться

Если всегда есть что-то за точкой, мы могли бы потворствовать некоторой арифметике указателей:

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 - я не запускал это, чтобы проверить это, но для меня это выглядит нормально.

0
ответ дан 27 November 2019 в 16:36
поделиться

Может быть ...

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 вызовы.

0
ответ дан 27 November 2019 в 16:36
поделиться

Вы также можете обобщить следующим образом:

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;
}
0
ответ дан 27 November 2019 в 16:36
поделиться

Протестированный код, включает в себя тест:

#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;
}
2
ответ дан 27 November 2019 в 16:36
поделиться

strlen (". Foo") не требуются. Если вы действительно хотите, чтобы он был гибким, вы могли бы использовать sizeof ".foo" - 1 - постоянную времени компиляции.

Кроме того, проверка на нулевую строку была бы хорошей.

2
ответ дан 27 November 2019 в 16:36
поделиться

Если вы можете изменить сигнатуру своей функции, попробуйте изменить ее на

int EndsWith(char const * str, char const * suffix, int lenstr, int lensuf);

. Это приведет к повышению безопасности. , более многократно используемый и более эффективный код:

  1. Добавленные квалификаторы const гарантируют, что вы не по ошибке измените входные строки. Эта функция является предикатом, поэтому я предполагаю, что она никогда не имеет побочных эффектов.
  2. Суффикс для сравнения передается в качестве параметра, поэтому вы можете сохранить эту функцию для последующего повторного использования с другими суффиксами.
  3. Эта подпись даст вам возможность передавать длины строк, если вы их уже знаете. Мы называем это динамическим программированием .

Мы можем определить функцию следующим образом:

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;
}

Очевидный контраргумент для дополнительных параметров заключается в том, что они подразумевают больше шума в коде или менее выразительный код .

3
ответ дан 27 November 2019 в 16:36
поделиться

У меня нет доступа к компилятору прямо сейчас, так может кто-нибудь сказать мне, если это работает?

#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 , он говорит всем (включая компилятор), что вы не собираетесь изменять строку.

7
ответ дан 27 November 2019 в 16:36
поделиться
int EndsWithFoo( char *string )
{
  string = strrchr(string, '.');

  if( string != NULL )
    return( strcmp(string, ".foo") );

  return( -1 );
}

Вернет 0, если заканчивается ".foo".

11
ответ дан 27 November 2019 в 16:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: