Алфавитное сравнение без strcmp ()? - PullRequest
2 голосов
/ 16 июня 2011

Я пытаюсь написать пользовательскую функцию strcmp () без использования встроенной функции. Пока что мой код кажется немного запутанным. По сути, я хочу, чтобы порядок символов был таким:

  1. Специальные символы (в порядке их появления)
  2. Цифры
  3. Буквенные символы по порядку, но сначала заглавные буквы, т. Е. "AaBbCcDd"

Возвращать 1, если строка1 предшествует строке2, -1, если строка2 предшествует строке1, и 0, если они равны.

Вот код, который у меня есть:

int strcmp(char * string1, char * string2)
{
    while((*string1 != '\0') && (*string2 != '\0') && (*string1 == *string2))
    {
        ++string1;
        ++string2;
    }

    //If both are now zero, they are equal
    if (*string1 == *string2 == '\0') { return 0; }

    //If string1 is comes before, return 1
    //If string2 is comes before, return -1
    int type1 = (isalpha(string1) ? 2 : (isnum(string1) ? 1 : 0))
    int type2 = (isalpha(string2) ? 2 : (isnum(string2) ? 1 : 0))
    return ((type1 < type2) 1 : ((type2 < type1) -1 :
        (((*string1 >= 'a') ? (*string1 - 'a')*2+1 : (*string1 - 'a')*2) < 
        ((*string2 >= 'a') ? (*string2 - 'a')*2+1 : (*string2 - 'a')*2) ? 1 : -1)));
}

Есть две вещи, в которых я не уверен:

  1. Является ли присвоение «категорий» правильным подходом. Прямо сейчас я назначаю тип 0 специальным символам, тип 1 - цифрам, а тип 2 - буквам. Таким образом, я могу быстро сравнить типы.
  2. Подходит ли мой подход к использованию алгебраических операций для установления порядка букв алфавита.

Это хорошие подходы? Там лучше? Пожалуйста, имейте в виду, что я максимизирую эффективность.

Ответы [ 4 ]

2 голосов
/ 16 июня 2011

Предполагая 8-битные символы, вы можете заполнить таблицу поиска. Используйте существующий код сравнения, чтобы отсортировать таблицу всех возможных значений символов, а затем составьте таблицу с индексами для каждого символа.

Тогда ваш внутренний цикл должен только найти 1 порядковый номер для каждого символа в строке и сравнить целые числа.

#include <stdio.h>

static int my_strcmp_order[256]; // you fill this in

int my_strcmp(const char *s1, const char *s2)
{
        while (*s1 == *s2++) {
                if (*s1++ == '\0') return 0;
        }
        return my_strcmp_order[*(const unsigned char*)s1]
                - my_strcmp_order[*(const unsigned char*)(s2-1)];
}

int main()
{
        for (int i=0; i<256; i++) {
                my_strcmp_order[i] = i; // native sort order - you fill it your way
        }

        const char *s1 = "Abc";
        const char *s2 = "Abcd";
        const char *s3 = "";
        printf("s1 <=> s2 = %d\n", my_strcmp(s1, s2));
        printf("s1 <=> s3 = %d\n", my_strcmp(s1, s3));
        printf("s3 <=> s2 = %d\n", my_strcmp(s3, s2));
}
0 голосов
/ 02 декабря 2012

Вот моя попытка.Я фактически копирую обычную функцию strcmp (), поэтому, если строки не совпадают, она возвращает разницу между первым элементом каждой строки.Например, strcmp («яблоко», «зебра») возвращает 25, а strcmp («зебра», «яблоко») возвращает -25

#include <stdio.h>
#include <string.h>

int my_strcmp(char* arg1, char* arg2) {
  while(arg1++ == arg2++);
  return (--arg1==--arg2&&strlen(arg1)==strlen(arg2))?0:arg2[0]-arg1[0];
}

int main(int argc, char* argv[]) {
  printf("%d\n",my_strcmp(argv[1],argv[2]));
}
0 голосов
/ 16 июня 2011

try

int strcmp(const char * string1, const char * string2)
{

while (*string1 == *string2++)
    if (*string1++ == 0)
        return (0);
    // then check for the ordering according to taste

}

Пока символы одинаковы, вы увеличиваете s2, затем проверяете, является ли следующий символ s1 нулевым, увеличивая его при проверке.Это приводит к увеличению обоих указателей при одновременном внедрении быстрого выхода, если вы бежите до конца строки.Он должен упаковываться в сборку довольно плотно.

Это оставляет вас с упрощенным сценарием, где вам нужно только определить, какой следующий символ по отношению к другому

0 голосов
/ 16 июня 2011

Очевидная проблема, которую я вижу, это следующая строка.

if (*string1 == *string2 == '\0') { return 0; }

Это не будет работать, как ожидалось.Это не вернет ноль, если они равны.Если string1 и string2 равны, то *string1 == *string2 имеет значение true или эквивалентно ненулевому значению и, следовательно, никогда не будет равно \0.Это условие должно быть

if ((*string1 == '\0') && (*string2 == '\0')) {}

И не использовать троичные операторы таким образом, поскольку они приводят к менее читаемому коду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...