Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.72/89: Рейтинг темы: голосов - 89, средняя оценка - 4.72
0 / 0 / 0
Регистрация: 09.03.2020
Сообщений: 25

Найти длину строки, без использования функции strlen()

02.04.2020, 13:50. Показов 20070. Ответов 115
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Написать функцию, которая получает строку и возвращает длину строки. Без использования функции strlen ()
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.04.2020, 13:50
Ответы с готовыми решениями:

Узнать длину строки не щитая функции strlen
Как узнать длину строки не щитая функции strlen?

Написать программу, которая определяет длину строки - strlen (число символов без завершающего нуль-символа)
Написать программу с помощью символьных строк и функции обработки строк. Библиотечные функции обработки строк: strlen-определить...

Функция strlen возвращает неверную длину строки
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int main () { wchar_t x; char str; ...

115
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,308
02.04.2020, 23:24
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Argus19 Посмотреть сообщение
Если таким же образом передать string в строке:
C++
1
while (s[ln])
возникает ошибка: "выражение должно иметь тип bool (или тип с возможностью преобразования в bool).
Вы что-то выдумываете. Такой ошибки не возникает. Все прекрасно компилируется и работает: http://coliru.stacked-crooked.... 514dbfa823

Цитата Сообщение от Argus19 Посмотреть сообщение
C++
1
2
3
unsigned int count(string str){
...
while (str[i] != string::npos )
Если уж вы собрались вычислять длину std::string руками, то завершающим символом строки будет символ \0. А вы почему-то взялись проверять на string::npos, который тут совершенно ни к месту.

Цитата Сообщение от Argus19 Посмотреть сообщение
C++Выделить код
C++
1
while(str[i] != '\0')
вызывают string subscript out of range.
Вы что-то выдумываете. Никакого "string subscript out of range" они не вызывают.

Цитата Сообщение от Argus19 Посмотреть сообщение
Странно, завершающего ноля нет, а стало отрабатывать правильно.
Как это "нет"? Есть, конечно.

---

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Он есть. В дебаге просто проверяется, что индекс меньше size().
Класс std::string уже давно допускает указание индекса size() и гарантирует возврат \0. Поэтому в "дебаге" проверяется, что индекс меньше либо равен size().
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
02.04.2020, 23:25
C++
1
2
3
4
5
6
7
size_t len(const string &S){
    return S.end() - S.begin();
}
 
size_t len(const char* S){
    return strchr(S,0) - S;
}
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
02.04.2020, 23:29
Цитата Сообщение от Argus19 Посмотреть сообщение
IGPIGP, только в одной статье интернета нашел, что предложенный вами способ инициализации вектора применим только со стандарта С++11.
Создайте массив и отдайте вектору начало и конец.
C++
1
2
int a[]={1,2,3};
vector<int> va(a, a+sizeof(a)/sizeof(*a));
Цитата Сообщение от Argus19 Посмотреть сообщение
мне этот код пока непонятен
Это шанс сделать шаг вперёд) Там всё просто, - указатель перемещается по строке пока не встретит '\0' - символ, включительно. Указатели поддерживают вычитание и это возможность найти расстояние в символах от нуля до начала. Единицу приходится сбрасывать и это значит, что один инкремент был лишним) Можно этого избежать но будет чуть многословнее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
size_t StringLen(const char  *s)
{
    if(!*s)return 0;
 
    const char  *p=s ;
    while (*++p) ;
    return p-s;
}
 
int main()
{
//раз такая пьянка то строк можно не экономить)))
cout<<StringLen("mamanya")<<endl;
cout<<StringLen("maman")<<endl;
cout<<StringLen("mama")<<endl;
cout<<StringLen("mam")<<endl;
cout<<StringLen("ma")<<endl;
cout<<StringLen("")<<endl;
return 0;
}
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,308
02.04.2020, 23:32
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Класс std::string уже давно допускает указание индекса size() и гарантирует возврат \0. Поэтому в "дебаге" проверяется, что индекс меньше либо равен size().
P.S. "Уже давно" означает "с C++11". Однако даже в изначальном C++98 разрешалось вызывать operator [] с индексом size() для константной версии оператора. То есть если параметр объявлен как const std::string или const std::string &, то выхода за пределы не происходит даже в C++98.

P.P.S. Кстати, пример того, как "ничего не значащий" const на объявлении параметра может (мог) иметь серьезные последствия с точки зрения функциональности кода.
2
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
02.04.2020, 23:37
Цитата Сообщение от Argus19 Посмотреть сообщение
передача строки по значению в некоторых случаях может создать проблему
В данном случае дело совсем не в этом.

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
В данном случае дело совсем не в этом.
А вот в этом:
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
То есть если параметр объявлен как const std::string или const std::string &, то выхода за пределы не происходит даже в C++98.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,308
02.04.2020, 23:40
Цитата Сообщение от IGPIGP Посмотреть сообщение
Можно этого избежать но будет чуть многословнее:
C++
1
2
3
4
5
6
7
size_t StringLen(const char  *s)
{
    if(!*s)return 0;
const char  *p=s ;
    while (*++p) ;
    return p-s;
}
Это "избежание" не имеет никакого смысла. Зачем? Код стал более многословным и менее эффективным.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
02.04.2020, 23:53
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это "избежание" не имеет никакого смысла. Зачем? Код стал более многословным и менее эффективным.
P приращается на 1 меньше и не нужно вычитать в конце. За это приходится расплачиваться проверкой на пустую строку. Зато пустые строки обрабатываются быстрее. Впрочем, тут важно вести диалог с ТС, чтобы ему легче было прочесть и понять. Переинкрементация и вычитание 1 не является очевидной вещью для начинающего. Видя оба варианта он быстрее разберёт. Во всяком разе я надеюсь на это)
0
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
03.04.2020, 00:00
IGPIGP,
C++
1
2
3
4
5
6
size_t StringLen(const char  *s)
{
    const char  *p=s ;                  указателю присваивается значение указателя на первый символ строки.
    while (*p++) ;                       цикл идёт пока указатель не достигнет конца строки   
    return p-s-1;                          от указателя на конец строки отнимаем указатель на начало переданной строки и лишнюю итерацию
}
Я правильно понял?
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Вы что-то выдумываете. Никакого "string subscript out of range" они не вызывают.
Миниатюры
Найти длину строки, без использования функции strlen()  
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.04.2020, 00:08
Цитата Сообщение от Argus19 Посмотреть сообщение
Я правильно понял?
Да)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,308
03.04.2020, 00:12
Цитата Сообщение от Argus19 Посмотреть сообщение
C++
1
2
return p-s-1;                          от указателя на конец строки отнимаем указатель на начало переданной строки и лишнюю итерацию
}
Я правильно понял?
Не совсем. В комментарии вы упоминаете "лишнюю итерацию". Но этот цикл не делает никакой "лишней итерации". Просто в результате финальной проверки условия цикла возникает лишний инкремент значения p.

---

Бесполезно показывать скриншоты ошибок, не показывая кода, который вы исполняли и настроек компилятора, который вы использовали.

Как я сказал выше, такая ошибка возможна в "старинном" языке С++, но для этого нужно специально постараться использовать именно его.

---

Мне более интересно было бы увидеть ваше

Цитата Сообщение от Argus19 Посмотреть сообщение
Если таким же образом передать string в строке:
C++
1
while (s[ln])
возникает ошибка: "выражение должно иметь тип bool (или тип с возможностью преобразования в bool).
1
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
03.04.2020, 00:27
Цитата Сообщение от IGPIGP Посмотреть сообщение
Да)
Расту над собой!


Добавлено через 13 минут
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Бесполезно показывать скриншоты ошибок, не показывая кода
код в посте №17. Выше писал, что работаю в VS2010
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Мне более интересно было бы увидеть ваше
Я много чего перепробовал и уже забыл, как именно делал.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.04.2020, 00:35
Цитата Сообщение от Argus19 Посмотреть сообщение
Расту над собой!
Вот!
Argus19, вот тут:
Цитата Сообщение от Argus19 Посмотреть сообщение
цикл идёт пока указатель не достигнет конца строки
есть тонкость, понимание которой потом поможет при знакомстве с итераторами. Итерирование с открытой границей - итерирование не до конца, а аж за конец. Терминатор это часть структуры c-строка, но мы не считаем его значащим символом и поэтому длина его не учитывает. То есть, он находится за концом строки.
А итерация на нём и заканчивается. А пост инкремент догоняет (он неумолим) и прибавляет ещё единицу -см. пояснение от TheCalligrapher. Остальное логично. Если бы он последний раз не инкрементировался то указывал бы за последний символ и разница давала бы точно то, что нужно. Если разрушить понт с while без тела (Чеширский while - люблю его ) то в теле можно проверить а потом или break или инкрементировать дальше (тут же в теле). Тогда в условии придётся оставить true или 1. Это вам для раздумий)
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,308
03.04.2020, 00:40

Не по теме:

Цитата Сообщение от Argus19 Посмотреть сообщение
Выше писал, что работаю в VS2010
Так а почему? Очень многое поменялось в языке с тех пор. Использование устаревшей версии языка, без явного предупреждения участников форума, ведет только к бесполезной трате времени на разбор ситуации и к волне неверных выводов



Добавлено через 2 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В комментарии вы упоминаете "лишнюю итерацию". Но этот цикл не делает никакой "лишней итерации". Просто в результате финальной проверки условия цикла возникает лишний инкремент значения p.
... и если вы добавите в тело цикла какую-то отладочную печать (напр. std::cout << "*";) то увидите, что количество итераций цикла всегда строго равно длине строки. То есть никакой "лишней итерации" цикл не делает.
0
03.04.2020, 00:57

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
без явного предупреждения участников форума
пост №15.

0
03.04.2020, 01:13

Не по теме:

Цитата Сообщение от Argus19 Посмотреть сообщение
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
без явного предупреждения участников форума
пост №15.
Слово "предупредить" в данном контексте мною использовано в значении "уведомить заранее". "Заранее" здесь - ключевое слово. Тот факт, что нам понадобилось ждать до "поста №15" как раз и является иллюстрацией той проблемы, о которой я веду речь.

0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
03.04.2020, 01:16
Argus19, резюмируя: в VS 2010 (которая опирается на стандарты С++98/03) использовать код, который смотрит за конец строки std::string без использования константной версии operator[], запрещено. Именно этот запрет проверяет assert внутри неконстантной версии operator[] (который у вас перехватывается средой в качестве SEH-исключения). Верный вариант представлен в #19.
1
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
03.04.2020, 01:34
Цитата Сообщение от DrOffset Посмотреть сообщение
резюмируя:
Спасибо. Изменил код. И в Debug и в Release всё работает без ошибок. Добавил важные комментарии. Ваши, IGPIGP и TheCalligrapher . Использовал все предложенные варианты, кроме варианта с вектором. Получился пример с "поминальным синодиком" (не помню откуда цитата). Надеюсь поможет ТС, мне и тому, кого заинтересует:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <string>
using namespace std;
//Функции подсчёта символов в строках
/*в VS 2010 (которая опирается на стандарты С++98/03) использовать код,
который смотрит за конец строки std::string без использования 
константной версии operator[], запрещено. Именно этот запрет проверяет
assert внутри неконстантной версии operator[] (который перехватывается
средой в качестве SEH-исключения).*/
unsigned int count(const string str){
    unsigned int i = 0;
    while(str[i] != 0){
        i++;}
    return i;
}
 
unsigned int counter(const string &str){
    unsigned int i = 0;
    while(str[i] != 0){
        i++;}
    return i;
}
 
size_t StringLen(const char  *s)
{
    size_t ln = 0;
    while (s[ln])
        ++ln;
    return ln;
}
 
size_t len(const string &S){
    return S.end() - S.begin();
}
 
size_t leng(const char* S){
    return strchr(S,0) - S;
}
/*есть тонкость, понимание которой потом поможет при знакомстве с итераторами.
Итерирование с открытой границей - итерирование не до конца, а аж за конец. 
Терминатор это часть структуры C-строка, но мы не считаем его значащим символом
и поэтому длина его не учитывает. То есть, он находится за концом строки.
А итерация на нём и заканчивается. А пост-инкремент догоняет (он неумолим)
и прибавляет ещё единицу - (в результате финальной проверки условия цикла возникает
лишний инкремент значения p.) . Остальное логично. Если бы он последний раз 
не инкрементировался то указывал бы за последний символ и разница давала бы точно то,
что нужно. Если разрушить понт с while без тела
 то в теле можно проверить а потом или break или инкрементировать дальше 
 (тут же в теле). Тогда в условии придётся оставить true или 1.*/ 
size_t StringLeng(const char  *s)
{
    const char  *p=s ;      //указателю присваивается значение указателя на первый символ строки.
    while (*p++) ;          //цикл идёт пока указатель не достигнет конца строки   
    return p-s-1;           //от указателя на конец строки отнимаем указатель на начало переданной строки и лишнюю итерацию
}
int main()
{
      setlocale (LC_ALL, "rus");
    string str = "На берёзе выросли 2 яблока и 3 груши";
    string str1 = "Сидел на ёлке дятел, досиделся - спятил.";
    string str3 = "По глади озера скользили три воробья и ворона";
    string str4 = "Мряка и Бряка расдрусили пусик.";
    string str5 = "Отплякиваясь от сурых пляк, каждый хамсик шмыряет на глын по 5 гнусиков.";
    string str6 = "Клюша наклюсюкал 256 парфусиков.";
    cout << str << endl;
      cout << "Количество символов в строке : " << count (str) << endl;
     cout << str1 << endl;  
      cout << "Количество символов в строке : " << StringLen(str1.c_str()) << endl;
     cout << str3 << endl;
      cout << "Количество символов в строке : " << counter (str3) << endl;
     cout << str4 << endl;
      cout << "Количество символов в строке : " << StringLeng (str4.c_str()) << endl;
     cout << str5 << endl;
      cout << "Количество символов в строке : " << len (str5) << endl;
     cout << str6 << endl;
      cout << "Количество символов в строке : " << leng (str6.c_str()) << endl;
      system("pause");
return 0;
}
Так же спасибо всем, принявшим участие в обсуждении, казалось бы, простого вопроса.
1
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
03.04.2020, 01:49
Цитата Сообщение от Argus19 Посмотреть сообщение
простого вопроса
Не могу не упомянуть, что вопрос на самом деле крайне простой, и для получения соответствующих верных выводов достаточно прочесть справку к оператору[]: https://en.cppreference.com/w/... perator_at
Вот случаи, помеченные как until C++11 (т.е. до C++11)
If pos == size(), the behavior is undefined.
- для неконстантной версии.
If pos == size(), a reference to the character with value CharT() (the null character) is returned.
- для константной.
Всем новичкам нужно вырабатывать навыки чтения документации, это первостепенная вещь.
0
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
03.04.2020, 01:57
Цитата Сообщение от DrOffset Посмотреть сообщение
Всем новичкам нужно вырабатывать навыки чтения документации
Для этого надо нормально знать английский язык. Машинный перевод зачастую забавляет.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.04.2020, 02:02
Цитата Сообщение от Argus19 Посмотреть сообщение
На берёзе выросли 2 яблока и 3 груши
Нечётное количество, - дурная примета. Теперь понятно хоть зачем кому-то может придти в голову пойти и белую берёзу заломати. Фруктов добыть алчут люди по весне. Авитаминоз
Argus19, count и counter по коду идентичны. Какой-то - не жилец, похоже)
А вообще, литература годная, бутявки (не кузявые) должны разбежаться, спрятаться и выжить, имхо)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.04.2020, 02:02

Подскажите функцию, которая возвращает длину строки (string), strlen не подходит.
Подскажите функцию, которая возвращает длину строки (string), strlen не подходит!!!!!!

При попытке вычислить длину строки стандартной функцией strlen возникает ошибка
Есть код, в котором объявлена volatile-переменная c_buf, представляющая собой массив символов: unsigned int l; volatile char c_buf =...

Извлечение подстроки из строки (без использования библиотек функции)
Извлечение подстроки из строки (без использования библиотек функций). Помогите чем кто может, заранее спасибо:)

Удаление символов из строки без использования стандартной функции delete
Как удалить символы из строки без использования стандартной функции delete? конкретно моя задача: Дана строка. Удалить из неё все...

Найти максимальную длину строки в текстовом файле и распечатать все строки файла, имеющие такую длину
Найти максимальную длину строки в текстовом файле и распечатать все строки файла, имеющие такую длину.С++


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Расчёт периметра прямоугольника по координатам вершин
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Вычислить периметр прямоугольника, заданного координатами своих вершин на плоскости. Решение: Создан документ со следующими. . .
Подсчёт частоты трёхбуквенных слов в тексте
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Выясните, сколько раз в предложенном тексте встречается каждое трехбуквенное слово. Решение: Создан документ с единственным. . .
Сумма и количество положительных элементов в чётных строках массива
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Вычислить сумму и количество положительных элементов массива, расположенных в четных строках. Решение: Создан документ с. . .
Поиск произведения положительных чётных чисел в последовательности
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Дана произвольная последовательность целых чисел. Найти произведение положительных четных чисел данной последовательности. . . .
Обработка трёх чисел: утроение и возведение в степень
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Даны три действительных числа. Утроить те из них, значения которых неотрицательны, и возвести в четвертую степень отрицательные. . . .
Расчёт стоимости яблок по весу
Maks 18.07.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Написать программу вычисления стоимости некоторого количества (по весу) яблок. Решение: Создан документ, с табличной частью. . .
сукцессия 30. Фосфорный и азотный замки по "честному" закону лимитирования Либиха
anaschu 16.07.2026
Основные достижения за последние дни 1. Механизм отложенного высвобождения фосфора Добавлен специальный пул для медленного разложения меланизированных гиф ЕСМ Реализована разная скорость. . .
Запрет пометки на удаление и отмены проведения
Maks 16.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "ПутевойЛист" разработанного в КА2. Задача: запретить помечать на удаление и отменять проведения путевого листа при условии, если он сдан. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru