Эффективность цикла - C++

Вопрос о новичках, на эффективности цикла. Я начал программировать в C++ (мой первый язык) и использовал 'Принципы и Практику Используя C++' Bjarne Stroustrup. Я пробивался через более ранние главы и был просто представлен понятию циклов.

Первое осуществление относительно циклов спрашивает меня следующее: символ 'b' является символом (+1), 'c' является символом (+2) и т.д. Используйте цикл для выписывания таблицы символов с их соответствующими целочисленными значениями:

97, b 98..., z 122

Хотя, я использовал верхний регистр, я создал следующее:

int number = 64; //integer value for @ sign, character before A
char letter = number;//converts integer to char value
int i = 0;

while (i<=25){
    cout << ++letter << "\t" << ++number << endl;
    ++i;
    }

Я должен стремиться только к наличию 'я' присутствовать в цикле, или разве это просто не возможно при преобразовании между типами? Я не могу действительно думать ни о каком другом способе, в который вышеупомянутое может быть сделано кроме наличия символьного значения, преобразовываемого, он - целочисленный дубликат (т.е. противоположность существующего метода) или просто не наличие преобразования вообще, и имейте хранилище буквы.

8
задан SlackerByNature 22 January 2010 в 09:26
поделиться

8 ответов

Вы должны сначала стремиться к ясности, и вы стараетесь вместо этого Micro оптимизировать. Вы можете лучше переписать, что как для цикла:

const int offsetToA = 65;
const int numberOfCharacters = 26;
for( int i = 0; i < numberOfCharacters; ++i ) {
    const int characterValue = i + offsetToA;
    cout << static_cast<char>( characterValue  ) << characterValue << endl;
}

, и вы можете конвертировать между различными типами - это называется отливками ( Static_Cast , конструируйте в код выше).

8
ответ дан 5 December 2019 в 04:55
поделиться

Следует от JK, вы можете даже использовать саму букву в петле (буква <= 'z'). Я также использовал петлю для цикла, но это только я.

for( char letter = 'a'; letter <= 'z'; ++letter )
    std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
22
ответ дан 5 December 2019 в 04:55
поделиться

Так как никто больше не упоминал об этом: Имея фиксированное количество итераций, это также кандидат на постусловную итерацию с do...while .

char letter = 'a';
do {
    std::cout << letter << "\t" << static_cast<int>( letter ) << std::endl;
} while ( ++letter <= 'z' );

Однако, как показано в ответе Патрика идиома для часто бывает короче (в данном случае в количестве строк).

1
ответ дан 5 December 2019 в 04:55
поделиться

Нет ничего особо неэффективного о том, как вы это делаете, но это, безусловно, возможно просто преобразовать между Chars и IntS (CHAR - это целочисленный тип). Это будет означать, что вам нужно только хранить 1 счетчик, а не 3 (я, буква + номер), у вас в курсе

также, для зацикливания с фиксированного начала, чтобы закончить петлю «для», возможно, более идиоматична (хотя это возможно Ты еще не встретил этого!)

2
ответ дан 5 December 2019 в 04:55
поделиться

Увеличение трех отдельных переменных, вероятно, немного запутано. Вот возможность:

for (int i = 0; i != 26; ++i)
{
    int chr = 'a' + i;
    std::cout << static_cast<char>(chr) << ":\t" << chr << std::endl;
}

Обратите внимание, что использование для цикла удерживает все логику настройки, тестирования и увеличения переменной петли в одном месте.

0
ответ дан 5 December 2019 в 04:55
поделиться

Это не плохой способ сделать это, но вы можете сделать это только с одной переменной петли, как это:

char letter = 65;

while(letter <= 65+25){
  printf("%c\t%d\n", letter, letter);
  ++letter;
}
2
ответ дан 5 December 2019 в 04:55
поделиться
[11598774-

Если вы обеспокоены эффективностью вашего цикла, я бы побудил вас попробовать:

Получите этот код скомпилированным и запущенным под IDE, такие как Visual Studio, и установить Выровняйте точку в начале. Когда вы попадаете туда, перейдите на просмотр по разборке (представление инструкции) и начните ударить клавишу F11 (STOW STEP) и сохраняйте ментальный счетчик того, сколько раз вы его попадаете.

Вы увидите, что он входит в цикл, сравнивает I против 25, а затем начинает выполнять код для Cout Cout . Это включает в себя увеличение буква , а затем входит в << << [126047] для Cout. Там делает ряд вещей, возможно, идет глубже в подпрограммы и т. Д., И, наконец, возвращается, возвращая объект. Затем он толкает «\ T» как аргумент и передает его к этому объекту и восходит назад и делает все это делали раньше. Тогда это занимает номер , увеличивает его и передает его в Coutine :: << COUT :: << Рутина, которая принимает целое число, вызывает функцию для преобразования его в строку (которая включает в себя петлю ), то все это делало, прежде чем расти, чтобы цитать эту строку в выходной буфер и возврат.

Устали? Вы еще не закончены. EndL должен быть выведен, а когда это произойдет, он не только ставится «\ N» в буфере, но он вызывает системную рутину для промывания этого буфера в файл или консоль, где вы отправляете ввод / вывод. Вы, вероятно, не можете в этом, но отдых уверены, что требуется много циклов и не возвращается до тех пор, пока ввод / вывод.

К настоящему времени ваш счет F11 должен быть в непосредственной близости от нескольких тысяч, более или менее.

Наконец, вы выходите и добираетесь до оператора ++ I , который занимает 1 или 2 инструкции и переходит назад к верхней части цикла, чтобы начать следующую итерацию.

Теперь вы все еще беспокоитесь о эффективности цикла?


Есть более простой способ сделать этот момент, и это так же, как поучительный. Оберните бесконечную петлю вокруг всего кода, чтобы он работает навсегда. Хотя он работает, нажмите кнопку «Пауза» в IDE и посмотрите на стек вызовов. (это называется «StackShot».) Если вы делаете это несколько раз, вы получаете хорошее представление о том, как это проводит время. Вот пример:

NTDLL! 7c90e514()
KERNEL32! 7c81cbfe()
KERNEL32! 7c81cc75()
KERNEL32! 7c81cc89()
MSVCRTD! 1021bed3()
MSVCRTD! 1021bd59()
MSVCRTD! 10218833()
MSVCRTD! 1023a500()
std::_Fputc() line 42 + 18 bytes
std::basic_filebuf<char,std::char_traits<char> >::overflow() line 108 + 25 bytes
std::basic_streambuf<char,std::char_traits<char> >::sputc() line 85 + 94 bytes
std::ostreambuf_iterator<char,std::char_traits<char> >::operator=() line 304 + 24 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Putc() line 633 + 32 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Iput() line 615 + 25 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::do_put() line 481 + 71 bytes
std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::put() line 444 + 44 bytes
std::basic_ostream<char,std::char_traits<char> >::operator<<() line 115 + 114 bytes
main() line 43 + 96 bytes
mainCRTStartup() line 338 + 17 bytes

Я сделал это куча раз, и не развернул его в коде для внешнего i <= 25 цикла. Таким образом, оптимизация того, что цикл похож на чью-то отличную метафору: «Получение стрижки, чтобы похудеть».

2
ответ дан 5 December 2019 в 04:55
поделиться

На данный момент я бы не стал беспокоиться о микро-оптимизациях, таких как эффективный способ написания небольшого цикла, как этот. То, что у вас есть, позволяет циклу для делать эту работу хорошо, но если вам удобнее использовать в то время как , вы должны использовать это. Но я не уверен, что это ваш вопрос.

Я не думаю, что вы правильно поняли вопрос. Вы пишете код, зная, что 'A' - это 65. Весь смысл этого упражнения заключается в том, чтобы распечатать значение от 'A' до 'Z' в вашей системе, не зная, какое значение они имеют.

Теперь, чтобы получить целое значение для символа c, можно сделать: static_cast(c). Думаю, это то, о чем вы просите.

Я не писал никакого кода, потому что это должно быть веселее для вас.

Вопрос для экспертов: В Си я знаю, что 'а'... 'z' не обязательно должны иметь непрерывные значения (то же самое для 'A'... 'Z'). То же самое верно и для C++? Я бы так и думал, но тогда кажется крайне маловероятным, что книга Струстрапа предполагает это.

0
ответ дан 5 December 2019 в 04:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: