Вывести все слова, имеющие три и более одинаковых символа.

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

А ты проверил, или просто так написал, бросив один взгляд на код? :)

Рекомендую проверить.

А когда пройдёт первое удивление, что ничего не падает, то почитать вот тут :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Кстати, поковырялся в дизассемлинге студии. Действительно генерируется неожиданный код, и в ecx попадает неверное значение. Видимо, программа не падает исключительно по везению, так как в студии char всё же signed по умолчанию.

Вот первый дизассемблинг:

Код: Выделить всё

; ++table[str[i]]
00BA144C  mov         eax,dword ptr [ebp+8]  
00BA144F  add         eax,dword ptr [i]  
00BA1455  movsx       ecx,byte ptr [eax]  
00BA1458  mov         dl,byte ptr [ebp+ecx-108h]  
00BA145F  add         dl,1  
А вот дизассемблинг поправленного варианта:

Код: Выделить всё

; ++table[(unsigned char)str[i]]
010F144C  mov         eax,dword ptr [ebp+8]  
010F144F  add         eax,dword ptr [i]  
010F1455  movzx       ecx,byte ptr [eax]  
010F1458  mov         dl,byte ptr [ebp+ecx-108h]  
010F145F  add         dl,1 
Видно, что команда movsx (копирование со знаковым расширением) изменилась на movzx (копирование с нулевым расширением), что отразилось на значении ecx.

Итого, подтверждаю, что критика для студии действительно актуальна, и правильной будет строка:

Код: Выделить всё

++table[(unsigned char)str[i]]
Однако отмечу, что gcc и mingw работают корректно и без кастинга.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Decoder
Сообщения: 308
Зарегистрирован: 19 фев 2008, 23:11
Откуда: Moscow

Если ещё выбросить из функции определение длины строки за ненадобностью, а так же убрать счётчик итераций, то получится примерно следующая реализация...

Код: Выделить всё

bool has_three_or_more_equal_symbols(const char* str)
{
	if (str != nullptr)
	{
		short table[256] = {0};
		while (*str != 0)
		{
			if (++table[(unsigned char) *str++] > 2)
				return true;
		}
	}

	return false;
}
Поумнеть несложно, куда труднее от дури избавиться.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Большинство изменений одобряю. Я не написал на указателях лишь потому, что хотел, чтобы код был максимально прозрачен для человека, который ещё не глубоко погружён в С++.

Но одно изменение мне не нравится. Зачем тип элементов table с char изменён на short? Переполнить char мы всё равно не сможем, так как максимально возможное значение элемента - это 3. Получается лишняя трата стековой памяти.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить