Хотел бы задать такой вопрос, как можно вычислить длину строки, без использования функции вычисления длины строки strlen()?
9 Answers
Можно. Длиной строки по сути является номер позиции символа '\0':
size_t my_strlen(const char *s) {
const char* cur = s;
for (; *cur; ++cur);
return cur - s;
}
- 11,683
- 25
- 38
-
-
9
-
1@navi1893, my_strlen() это функция. Нужно взять учебник по С/С++, почитать что такое функции и как их вызывать. – insolor Jun 09 '12 at 18:16
-
4
sиcurнужно местами поменять в конце. Ещё можно, чтобы за границу строки не выходить:for ( ; *cur; ++cur ); return cur - s;Код для цикла тот же получается – jfs Feb 12 '15 at 22:44 -
3@jfs, спасибо, поправил. Грустно, что такое провисело 3 года, да еще и кучу голосов получило. – dzhioev Jan 30 '16 at 00:27
-
-
@Qwertiy Представьте
*cur=='\0', тогда после*cur++;как в изначальном варианте вreturn,curбудет указывать за границу строки. Сравните сfor (;*cur;++cur), где++curне выполняется, если*cur=='\0'и поэтомуcurпродолжает на конец строки указывать (на ноль). – jfs Sep 29 '16 at 17:54 -
-
-
@jfs, выхода за границу строки не было, т. к. указатель не разыменовывается. Он получает значение, указывающее на следующий за концом строки элемент - стандарт разрешает использовать такой указатель (ровно на 1 элемент), если нет разыменования, поэтому указывать туда и использоваться он имеет право. Тут нет противоречия, это две разные мысли. – Qwertiy Sep 29 '16 at 18:40
-
@Qwertiy: да, выхода за границу в смысле разыменования не было. Фразу "чтобы за границу строки не выходить" я неточно применил. Хотел сказать, "чтобы
curза границу не указывал". Хотя, в этом случае, ничего плохого в лишнемсur++нет, так как именно поддержка полу-открытых интервалов в циклах могла быть мотивацией для включения "one past the last element of the array object" правила в стандарт. (учитывая что код содержал баг c арифметикой указателей, я пытался упростить ситуацию настолько, насколько это возможно—даже если компилятор один и тот же код генерировал бы в итоге) – jfs Sep 29 '16 at 19:42
Можно путем итерирования указателя (с начало строки и до терминирующего символа \0) и подсчета числа этих самых итераций - то же, что делает strlen(). Но только зачем это?
- 1,923
-
-
4Вполне нормальное условие, думаю он хочет чтобы вы сами поняли как работает strlen. – AlexDenisov Jun 08 '12 at 08:57
-
Ясно. Видимо, следующим заданием будет обращение строки "своими руками". – vladimir_ki Jun 08 '12 at 08:58
-
Прикол будет, если длина строки будет выше чем пара десятков символов. Скажем, миллион символов. Вот за это я и не люблю С-строки. – PaulD Jun 09 '12 at 11:28
-
-
3
думаю он хочет чтобы вы сами поняли как работает
поддерживаю, учитель - умничка
– northerner Jun 09 '12 at 15:45 -
@AlexDenisov Вполне нормальная ситуация. Насколько я помню ( может где то ошибся ) в файле 1МБ 1048576 символа. Возьмите любой текстовый файл с сотню МБ и получите эту самую ситуацию. В последнее время я с ними частенько работаю ) – Kamo Petrosyan Nov 04 '15 at 12:53
int size_s(char *s)
{
int i;
for (i = 0; s[i] != '\0'; i++);
return i;
}
когда-то я писал примерно так.
- 51,426
- 87
- 267
- 507
- 1,823
-
@Илья Михневич, а если в строке есть нулевые символы, но после них есть что-то ещё? "\0" - не всегда показатель конца строки... – neo Feb 12 '15 at 13:30
-
2
-
2@Kristya: Строка C по определению заканчивается на
\0. Точнее, она заканчивается перед ним,\0не принадлежит самой строке. (Отсюда следует, что C-строка не может содержать\0). В других языках, даже в C++ — не так, строки могут содержать любые символы. (Для случая C++ я имею в виду идиоматическийstd::string.) – VladD Feb 12 '15 at 17:22 -
1лучше использовать
size_t, чтобы избежать переполнения в общем случае, например, в распространённых lp64 и llp64 моделях, гдеint32-битный, а указатели иsize_t64-битные. – jfs Feb 12 '15 at 23:03 -
Строка в C таки-да заканчивается на \0, а вот строка в C++ — не обязательно. – VladD Nov 04 '15 at 13:04
На 32-битных процессорах так получается быстрее:
size_t strlen( const char *s )
{
const char *p = s;
for (;;)
{
uint32 c = *((uint32*)p);
if ( (c - 0x01010101u) & 0x80808080u )
{
if ((c & 0x000000ffu) == 0) return p-s+0;
if ((c & 0x0000ff00u) == 0) return p-s+1;
if ((c & 0x00ff0000u) == 0) return p-s+2;
if ((c & 0xff000000u) == 0) return p-s+3;
}
p += 4;
}
}
Тут предполагается, что входная строка выровнена до 32-битной границы (конечно, будет работать и без выравнивания, но тогда весь смысл теряется).
- 9
-
Комментарий про strict aliasing, и необязательно четырёхбайтный uint32_t, и возможное нарушение требований по выравниванию. – wololo Jan 13 '18 at 09:33
-
Я сюда этот код размсестил не для того, чтобы его бездумно копипастили, а с целью показать, что строку можно анализировать не только посимвольно, но и блоками по 4 символа (или по 8, если шина данных 64-битная), и это будет намного быстрее. – Костя Jan 19 '18 at 13:22
Файлик main.c
#include <stdio.h>
int main(int argc, char argv[]){
int i = 1;
for(;i<argc;i++){
char pStr = argv[i];
int length = 0;
while(*pStr++ != '\0'){
length++;
}
printf("%d\n", length);
}
}
Собираем
gcc main.c
Запускаем
./a.out some_string
Будет подсчитана длина всех строк, переданных в качестве параметров (some_string)
Итерация начинается с единицы, т.к. первый параметр всегда имя программы.
Собственно strlen так работает =)
- 6,442
- 1
- 21
- 29
-
-
перменные, которые позволяют обрабатывать параметры переданные в приложение извне – AlexDenisov Jun 08 '12 at 10:01
-
1
-
2@1101_debian правильно и заминусовали, зачем у тебя дополнительная операция сложения в цикле. – Jun 09 '12 at 09:36
-
2Вы это о length++? Ну простите, хотел понятней написать, а не мегаоптимальней... – AlexDenisov Jun 09 '12 at 10:28
Способ без циклов и указателей , бесплатно (изначально делал для числовых массивов , но и для строк тоже подойдет , нужно только отнять терминирующий ноль )
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0])-1)
- 1
Вот таким не хитрым способом можно:
size_t strlen(const char *s) {
const char *p;
for (p = s; *p; ++p);
return p - s;
}
- 1,180
Ну а как же могли забыть это? Хоть и платформенно-специфичное, конечно :)
xor eax, eax
mov ecx, -1
mov edi, some_string
mov ebx, edi
cld
push ds
pop es
repne scasb
mov eax, edi
sub eax, ebx
dec eax
- 9,056
#include <iostream>
#include <string>
using namespace std;
int number(string chislosimvolov, int i);
int main()
{
string chisla;
int i;
cout << "\nEnter stroky:";
cin >> chisla;
cout << "Number of symbols in it is: "<< number(chisla, int (chisla.size()));
}
int number(string chislosimvolov, int i)
{
int t;
if (i== -1) t = 0;
else
t = number(chislo,i-1)
;
return t;
}
string::length. http://www.cplusplus.com/reference/string/string/length/ – andrybak Feb 12 '15 at 13:41