Как эффективно вычислять длину строки в C?
Как рассчитать длину строки в C эффективно (по времени)?
Сейчас я делаю:
int calculate_length(char *string) {
int length = 0;
while (string[length] != '\0') {
length++;
}
return length;
}
Но он очень медленный по сравнению с strlen(), например, есть ли другой способ сделать это?
Спасибо.
EDIT: я работаю в автономной среде, мне не разрешено использовать любую внешнюю библиотеку, включая "string.h".
Ответы
Ответ 1
Из исходного кода FreeBSD:
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s);
return(s - str);
}
По сравнению с вашим кодом, это, вероятно, очень хорошо сопоставляется с инструкцией ассемблера, которая может объяснить большую разницу в производительности.
Ответ 2
Взгляните на исходный код strlen в стандартном libc. Функции в стандартных библиотеках, как правило, сильно оптимизированы. Проверьте здесь (закодирован в сборке) - это из GNU libc.
size_t
DEFUN(strlen, (str), CONST char *str)
{
int cnt;
asm("cld\n" /* Search forward. */
/* Some old versions of gas need `repne' instead of `repnz'. */
"repnz\n" /* Look for a zero byte. */
"scasb" /* %0, %1, %3 */ :
"=c" (cnt) : "D" (str), "0" (-1), "a" (0));
return -2 - cnt;
}
Ответ 3
strlen()
. Коэффициенты, если кто-то нашел лучший, более быстрый общий метод, strlen был бы заменен этим.
Ответ 4
Взгляните на библиотека GNU C strlen()
source.
Он использует ряд неочевидных трюков, чтобы получить скорость, не отбрасывая на сборку, включая:
- получение символа, который правильно выравнивается
- чтение этих выровненных частей строки в int (или некоторый более крупный тип данных) для чтения нескольких символов за раз
- с помощью бит-трюков, чтобы проверить, равен ли один из символов, встроенных в этот блок символов,
и др.
Ответ 5
Самый простой способ - вызвать strlen()
. Шутки в сторону. Он уже оптимизирован вашими поставщиками компилятора и/или библиотеки как можно быстрее для вашей архитектуры.
Одна общая оптимизация заключается в том, чтобы удалить необходимость увеличения счетчика и вычислить длину указателя:
size_t my_strlen(const char *s)
{
const char *anchor = s;
while(*s)
s++;
return s - anchor;
}
Ответ 6
Строки C по сути неэффективны, есть две причины для использования соглашения ASCIZ:
- Стандартная библиотека C использует его
- Компилятор использует его для строковых строковых констант
Первый из них является академическим в этом случае, поскольку вы не используете стандартную библиотеку, второй легко преодолевается путем создания функций или макросов, которые обеспечивают преобразования из строк C в более эффективное соглашение, такое как строки Pascal. Дело в том, что вам не нужно быть подчиненным к соглашению C, если вы не используете библиотеку C.
Ответ 7
Еще одним способом ускорения подсчета char является использование векторизации!
Вот пример того, как это сделать в отношении строк с кодировкой UTF8:
Еще более быстрый подсчет символов UTF-8,
http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html
Ответ 8
В i386-процессорах libc часто использует ультра-оптимизированную версию strlen
, часто написанную на ассемблере. В документе "" Длина строки" объясняется, как они работают.
Вот одна оптимизированная версия для OpenBSD. (У них также есть портативная версия .) Вот версия для GNU libc.
Ответ 9
Некоторые из вышеперечисленных ответов очень хороши, и это мой прием.
Существует ключевое слово, известное как "регистр"
#include <stdio.h>
size_t strlenNew(char *s);
int main(int argc, char* argv[])
{
printf("Size of \"Hello World\" is ::\t%d",strlenNew("Hello World"));
return 0;
}
size_t strlenNew(char *s)
{
register int i=0;
while(s[i]!='\0') i++;
return i;
}
Читайте здесь: http://gustedt.wordpress.com/2010/08/17/a-common-misconsception-the-register-keyword/ и http://msdn.microsoft.com/en-us/library/482s4fy9(v=vs.80).aspx
Из первой ссылки:
Это может быть особенно полезно для переменных массива. Переменная массива легко смешивается с переменной указателя. Если за ним не последует a [expr] или с его размером оценивается по адресу первого элемент. Если вы объявите регистр массива, все эти запрещено; мы получаем доступ только к отдельным элементам или запрашиваем размер. Такой массив регистров может быть намного проще использовать, как если бы он просто был набор переменных оптимизатором. Нет псевдонимов (доступ одна и та же переменная через разные указатели).
Таким образом, иногда могут возникать колебания производительности. Лично это одна из моих реалистичных реализаций, но Sudhanshu и Andomar также обеспечивают хорошую реализацию:)
Ответ 10
У меня была та же проблема, и я решил. Ключ является вторым условием цикла for:
int longitud(char cad[]){
int i, cont;
cont = 0;
for(i = 0; i < 30 && cad[i] != '\0'; i++){
if(cad[i] != '\0'){
if(cad[i] != ' '){
cont++;
}
}
}
cont--;
return cont;
}
Ответ 11
Я не нашел лучшего:
рядный size_t mystrlen (char * _)
{ return ((_ == NULL) ? (_[0] != '\0')) ? 0 : (1 + mystrlen(_ + 1)); }
Ответ 12
Программа Basic C для вычисления длины строки.
#include <stdio.h>
/**
* Method to calculate string length.
* Returns -1 in case of null pointer, else return string length.
**/
int length(char *str) {
int i = -1;
// Check for NULL pointer, then return i = -1;
if(str == NULL) return i;
// Iterate till the empty character.
while (str[++i] != '\0');
return i; // Return string length.
}
int main (int argc, char **argv) {
int len = 0;
char abc[] = "hello";
len = length(abc);
printf("%d", len);
return 0;
}
ПРИМЕЧАНИЕ. Для лучшего способа мы всегда должны передавать размер массива, чтобы избежать утечки памяти. Например, прототип метода ** должен быть *: *
/**
* @desc calculate the length of str.
* @param1 *str pointer to base address of char array.
* @param2 size = capacity of str to hold characters.
* @return int -1 in case of NULL, else return string length.
**/
int length (char *str, int size);
Ответ 13
Я не совсем уверен, что вы хотите сделать.
Вы хотите переписать strlen
, чтобы ваш код совместим со стандартной c-библиотекой или вы хотите управлять строками.
В первом случае, я думаю, вам лучше использовать стандартные библиотеки.
Интересен другой случай: вы должны взглянуть на строковый класс С++, который реализует стратегию признаков (позволяя быстро манипулировать очень большими строками).
Ответ 14
Я покажу вам, как вычислять строку без использования встроенной функции в ** С# **
enter code here
String s1;
String s2;
Console.WriteLine("Enter The String 1");
s1 = Console.ReadLine();
int count = 0, i = 0;
s2 = s1 + "\0"; // calculating for s3...STRING 1
while (s2[i] != '\0')
{
count++;
i++;
}
Console.WriteLine("count "+count );
Ответ 15
int max;
max = sizeof(str);
return (--max);