Подтвердить что ты не робот

Как эффективно вычислять длину строки в C?

Как рассчитать длину строки в C эффективно (по времени)?

Сейчас я делаю:

int calculate_length(char *string) {
    int length = 0;
    while (string[length] != '\0') {
        length++;
    }
    return length;
}

Но он очень медленный по сравнению с strlen(), например, есть ли другой способ сделать это?

Спасибо.

EDIT: я работаю в автономной среде, мне не разрешено использовать любую внешнюю библиотеку, включая "string.h".

4b9b3361

Ответ 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);