UPDATE:
Исходный ответ устарел. Mongodb теперь поддерживает расширенный полнотекстовый поиск со многими функциями.
ОРИГИНАЛЬНЫЙ ОТВЕТ:
Следует отметить, что поиск с регистрозависимым регистром нечувствителен / i означает, что mongodb не может искать по индексу, поэтому запросы к большим наборам данных могут занять много времени.
Даже с небольшими наборами данных это не очень эффективно. Вы делаете гораздо больший бит процессора, чем ваши ордера на запрос, что может стать проблемой, если вы пытаетесь достичь масштаба.
. В качестве альтернативы вы можете хранить заглавную копию и искать ее. Например, у меня есть таблица User, у которой есть имя пользователя, которое является смешанным случаем, но идентификатор является заглавной копией имени пользователя. Это гарантирует, что дублирование, чувствительное к регистру, невозможно (иметь возможность «Foo» и «foo» не будет разрешено), и я могу выполнить поиск по id = username.toUpperCase (), чтобы получить поиск по имени пользователя без регистра.
Если ваше поле большое, например тело сообщения, дублирование данных, вероятно, не является хорошим вариантом. Я считаю, что использование альтернативного индексатора, такого как Apache Lucene, является лучшим вариантом в этом случае.
Будет проще использовать указатели, если вы отделите указатель строки от его символьного указателя. Кроме того, 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 . . .
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()
.
Во-первых, (*(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;
}
Если бы вы не навязывали странные и бесполезные ограничения на кодирование, вы сможете быстро увидеть проблемы с вашим кодом или даже вообще не создавать их. Проблема состоит в том, что следующее утверждение не имеет смысла - вы сравниваете char *
с char
, поскольку вы только раз ссылаетесь на str
один раз.
if ((*(str + i) + j) >= max)
Это то же самое, что написать
if ((str[i] + j) >= max)
, в котором вы можете увидеть очевидную ошибку, поскольку то, что вы пытаетесь написать, эквивалентно
if ((str[i][j]) >= max)
, которое будет
if (*(*(str + i) + j) >= max)
Ваш компилятор должен выдавать предупреждения, потому что сравнение между указателем и целым числом редко является чем-то, что вы хотели бы сделать.
Вы можете использовать указатели в качестве индикаторов положения и продвигать их по мере необходимости.
#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;
}