Единственный способ сделать это быстрее - с помощью таблицы поиска.Главное, что делает это не самым быстрым из возможных, состоит в том, что код превращается в кучу сравнений, что-то вроде:
if(ch == 'A') goto isvowel;
else if(ch == 'E') goto isvowel;
else if(ch == 'I') goto isvowel;
.
.
.
isvowel: putchar(ch);
, но это настолько несущественно, что в реальной жизни кого это волнует?
Но способ сделать это быстрее - использовать таблицу:
int isvowel[] = {1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0};
Теперь вам просто нужно поменять букву на число от 0 до 26. Во-первых, если вы посмотрите на внутреннюю структуру ASCIIВы видите, что строчная буква отличается от заглавной буквы только одной буквой.Таким образом, вы всегда можете сделать что-то в верхнем регистре всегда так:
ch & 0xFFDF;
Чтобы преобразовать в число, вы просто вычтите значение первой буквы:
(ch & 0xFFDF) - 'A'.
Затем, чтобы увидеть, еслиэто значение, вы просто тестируете массив в этой позиции: 1
:
if(isvowel[(ch & 0xFFDF) - 'A')
Обратите внимание, что если ch
не символ, наша математика не будет работать, поэтому нам нужноОстерегайтесь этого.
Таким образом, полный код становится примерно таким:
#include <stdio.h>
int main(){
char ch = 0;
int isvowel[] = {1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0};
while(ch != '\n'){
ch = getchar();
unsigned int ord = (ch & 0xFFDF) - 'A';
if( ord < 26 && isvowel[ord])
putchar(ch);
}
putchar('\n');
}
Причина, по которой это (очень немного) быстрее (но не быстрее), заключается в том, что вы делаете только два сравненияи не десять.Если вы посмотрите на старую версию, внутренне она выглядит примерно так:
compare to 'A'
compare to 'E'
compare to 'I'
compare to 'O'
compare to 'U'
compare to 'a'
compare to 'e'
compare to 'i'
compare to 'o'
compare to 'u'
С таблицей она становится
and with 0xFFDF
subtract 'A'
compare with 26
dereference table
compare
Таким образом, примерно половина операций.Но с современными процессорами мы говорим об наносекундах в любом случае, поэтому я действительно удивляюсь, почему это возникнет во вводном назначении.
Обратите внимание, что именно так стандартные методы библиотеки, такие как isalpha () обычно реализуются.Для isalpha()
существует таблица с 256 записями, в которой каждое буквенное значение в ASCII установлено в значение true, а каждое значение не установлено в значение false.Это делает их чрезвычайно быстрыми, более быстрыми, чем моя реализация здесь, поскольку им не нужно преобразовывать их в верхний регистр или проверять на наличие границ.
Но я хочу подчеркнуть: Вам не следует беспокоиться о такихнесущественные различия. Это то, что вы делаете, проведя недели с профилировщиком в производственном коде, а не в студенческих заданиях!.
Приложение:
Если вы используете gcc, вы можете сгенерировать код ASM с помощью gcc -S
.Это полезно для просмотра необработанного кода, до которого компилируется программа.Переключатель в вашем оригинале выглядит следующим образом в ASM:
movsbl -5(%rbp), %eax
movl %eax, %edx
subl $65, %edx
movl %eax, -12(%rbp) ## 4-byte Spill
movl %edx, -16(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_7
LBB0_7: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $69, %eax
movl %eax, -20(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_8
LBB0_8: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $73, %eax
movl %eax, -24(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_9
LBB0_9: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $79, %eax
movl %eax, -28(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_10
LBB0_10: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $85, %eax
movl %eax, -32(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_11
LBB0_11: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $97, %eax
movl %eax, -36(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_12
LBB0_12: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $101, %eax
movl %eax, -40(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_13
LBB0_13: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $105, %eax
movl %eax, -44(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_14
LBB0_14: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $111, %eax
movl %eax, -48(%rbp) ## 4-byte Spill
je LBB0_3
jmp LBB0_15
LBB0_15: ## in Loop: Header=BB0_1 Depth=1
movl -12(%rbp), %eax ## 4-byte Reload
subl $117, %eax
movl %eax, -52(%rbp) ## 4-byte Spill
jne LBB0_4
jmp LBB0_3
LBB0_3: ## in Loop: Header=BB0_1 Depth=1
jmp LBB0_1
LBB0_4: ## in Loop: Header=BB0_1 Depth=1
С таблицей это выглядит так:
movsbl -117(%rbp), %eax
andl $65503, %eax ## imm = 0xFFDF
subl $65, %eax
movl %eax, -124(%rbp)
cmpl $26, -124(%rbp)
jae LBB0_5
## %bb.3: ## in Loop: Header=BB0_1 Depth=1
movl -124(%rbp), %eax
movl %eax, %ecx
cmpl $0, -112(%rbp,%rcx,4)
je LBB0_5
## %bb.4: ## in Loop: Header=BB0_1 Depth=1