Как пройти через массив строк, используя только указатели

UPDATE:

Исходный ответ устарел. Mongodb теперь поддерживает расширенный полнотекстовый поиск со многими функциями.

ОРИГИНАЛЬНЫЙ ОТВЕТ:

Следует отметить, что поиск с регистрозависимым регистром нечувствителен / i означает, что mongodb не может искать по индексу, поэтому запросы к большим наборам данных могут занять много времени.

Даже с небольшими наборами данных это не очень эффективно. Вы делаете гораздо больший бит процессора, чем ваши ордера на запрос, что может стать проблемой, если вы пытаетесь достичь масштаба.

. В качестве альтернативы вы можете хранить заглавную копию и искать ее. Например, у меня есть таблица User, у которой есть имя пользователя, которое является смешанным случаем, но идентификатор является заглавной копией имени пользователя. Это гарантирует, что дублирование, чувствительное к регистру, невозможно (иметь возможность «Foo» и «foo» не будет разрешено), и я могу выполнить поиск по id = username.toUpperCase (), чтобы получить поиск по имени пользователя без регистра.

Если ваше поле большое, например тело сообщения, дублирование данных, вероятно, не является хорошим вариантом. Я считаю, что использование альтернативного индексатора, такого как Apache Lucene, является лучшим вариантом в этом случае.

2
задан Shames 18 January 2019 в 13:41
поделиться

5 ответов

Будет проще использовать указатели, если вы отделите указатель строки от его символьного указателя. Кроме того, max должен быть сброшен для каждой строки, и вы писали последний терминатор строки за пределами выделенной памяти. Вы также используете NULL, где вы должны использовать символ '\0'.

Наконец, функция возвращала первый символ новой строки (который я позже free).

#include <stdio.h>
#include <stdlib.h>

#define SIZE 4

char *bigLetters(char *str[], int size)
{
    char *strNew = malloc(size + 1);                    // no cast or sizeof necessary

    for (int i = 0; i < size; i++)
    {
        char ch;
        char max = 'a';                                 // moved inside loop
        char *ptr = *(str + i);                         // use a separate pointer
        for (int j = 0; (ch = *(ptr + j)) != '\0'; j++) // pull out the character
        {
            if (ch > max)                               // >= is not necessary
            {
                max = ch;
            }

        }
        *(strNew + i) = max;
    }
    *(strNew + size) = '\0';                            // correct the bounds error
    return strNew;                                      // just the pointer not its target
}    

int main(void)                                          // correct signature
{
    char *strArr[SIZE] = { "hello", "and", "good", "morning" };
    char *res = bigLetters(strArr, SIZE);
    printf("The new string is --> %s\n", res);
    free(res);                                          // clean up
    system("pause");
}

Выход программы

The new string is --> onor
Press any key to continue . . .
0
ответ дан Weather Vane 18 January 2019 в 13:41
поделиться

str[i] эквивалентно *(str + i) и str[i][j] эквивалентно *(*(str + i) + j).
В вашем коде вы используете (*(str + i) + j), что неверно.

Когда char *[] перейдет к функции, оно уменьшится до char **. Итак, в bigLetters() вы можете указать char **str в качестве параметра. Кроме того, это соответствует вашему требованию - запрещено использовать оператор [] .

Вместо жесткого кодирования измерения SIZE в char *strArr[SIZE], вы можете дать пустое [] и позволить компилятору назначить измерение на основе размера инициализатора. В вашем случае размер инициализатора равен 4, как вы дали 4 строк в инициализаторе strArr. Вы можете вычислить размер strArr следующим образом:

sizeof(strArr)/sizeof(strArr[0]);

Вы можете сделать:

#include <stdio.h>
#include <stdlib.h>

char *bigLetters(char **str, size_t size) {

        char *strNew = calloc(size + 1, 1); // sizeof(char) is always 1
                                            // calloc will initialize all bytes in the allocated storage to zero.
                                            // You dont need to add the null terminating character at the end of strNew
        if (strNew == NULL)
                exit(EXIT_FAILURE);

        for (size_t i = 0; i < size; i++) {
                for (size_t j = 0; *(*(str + i)+j) != '\0'; j++) {
                        if (*(*(str + i) + j) > *(strNew + i)) {
                                // You can directly fill the allocated memory with biggest ASCII
                                *(strNew + i) = *(*(str + i) + j);
                        }
                }
        }

        return strNew;
}

int main(void) {
        char *strArr[] = { "hello", "and", "good", "morning" };

        char *res = bigLetters(strArr, sizeof(strArr)/sizeof(strArr[0]));

        if (res != NULL) {
                printf("The new string is --> %s\n", res);
                free (res);
        }
        else
                printf("bigLetters returned NULL\n");

        return 0;
}

Обратите внимание, что void тип возвращаемого значения main() не соответствует стандарту. Вместо этого вы должны использовать int в качестве возвращаемого типа main().

0
ответ дан H.S. 18 January 2019 в 13:41
поделиться

Во-первых, (*(str + i)+j) не очень хороший путь.

Вы можете заменить все

(*(str + i) + j)

на:

str[i][j]

Затем вам нужно сбросить max на «а», потому что это «о», когда вы выходите из цикла, поэтому ваше состояние становится str[i][j] >= o, что не то, что вы хотите. Сделайте это до второго for.

И я бы использовал while вместо for для первого цикла.

Я отредактировал ваш код, и эта версия отлично работает для меня:

#include <stdlib.h>


char *bigLetters(char *str[], int size)
{
    char *strNew = (char *)malloc((size + 1) * sizeof(char));
    int i = 0;

    while (i < size) {
        char max = 'a';
        for (int j = 0; str[i][j]; j++) {
            if (str[i][j] >= max) {
                max = str[i][j];
            }
        }
        strNew[i] = max;
        i++;
    }
    strNew[i] = '\0';
    return strNew;
}    

void main()
{
    char *strArr[5] = { "hello", "and", "good", "morning"};
    char *res = bigLetters(strArr, 4);
    printf("The new string is --> %s\n", res);
    return 0;
}
0
ответ дан Titouan Le Floch Riche 18 January 2019 в 13:41
поделиться

Если бы вы не навязывали странные и бесполезные ограничения на кодирование, вы сможете быстро увидеть проблемы с вашим кодом или даже вообще не создавать их. Проблема состоит в том, что следующее утверждение не имеет смысла - вы сравниваете char * с char, поскольку вы только раз ссылаетесь на str один раз.

if ((*(str + i) + j) >= max)

Это то же самое, что написать

if ((str[i] + j) >= max)

, в котором вы можете увидеть очевидную ошибку, поскольку то, что вы пытаетесь написать, эквивалентно

if ((str[i][j]) >= max)

, которое будет

if (*(*(str + i) + j) >= max)

Ваш компилятор должен выдавать предупреждения, потому что сравнение между указателем и целым числом редко является чем-то, что вы хотели бы сделать.

0
ответ дан Chris Turner 18 January 2019 в 13:41
поделиться

Вы можете использовать указатели в качестве индикаторов положения и продвигать их по мере необходимости.

#include <stdio.h>
#include <stdlib.h>
#define SIZE 4

char
biggest_ascii(char* str)
{
 char c = 0;
 int i;

 for (i = 0; *str; str++)
    if (*str > c)
        c = *str;
 return c;
}


int
main()
{
 int i;
 char* strArr[SIZE] = {"hello", "and", "good", "morning"};
 char** ppch;// current string
 char res_str[SIZE + 1] = {0};/* resulting string, 
            initilized to 0 to be 0-terminated */
 char* pch;// current char position

 for (i = 0, ppch = strArr, pch = res_str; i < SIZE; i++, ppch++, pch++)
    *pch = biggest_ascii(*ppch);

 printf("%s\n", res_str);   
 return 0;
}
0
ответ дан purec 18 January 2019 в 13:41
поделиться
Другие вопросы по тегам:

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