Оператор switch

Задания раздела 5.3.2
5.9. Напишите программу, использующую серию операторов if для подсчета количества гласных букв в тексте, прочитанном из потока cin.
5.10. Программа подсчета гласных имеет одну проблему: она не учитывает заглавные буквы как гласные. Напишите программу, которая подсчитывает гласные буквы как в верхнем, так и в нижнем регистре. То есть значение счетчика aCnt должно увеличиваться при встрече как символа 'a', так и символа 'A' (аналогично для остальных гласных букв).
5.11. Измените рассматриваемую программу так, чтобы она подсчитывала также количество пробелов, символов табуляции и новой строки.
5.12. Измените рассматриваемую программу так, чтобы она подсчитывала количество встреченных двухсимвольных последовательностей ff, f1, fi.
5.13. Каждая из приведенных ниже программ содержит распространенную ошибку. Выявите и исправьте каждую из них.

Программы 5.13

(a) unsigned aCnt=0, eCnt=0, iouCnt=0;
char ch=next_text();
switch (ch) {
case 'a': aCnt++;
case 'e': eCnt++;
default: iouCnt++;
}
(b) unsigned index=some_value();
switch (index) {
case 1:
int ix=getvalue();
ivec[ix]=index;
break;
degault:
ix=ivec.size()-1;
ivec [ix]=index;
}
(c) unsigned evenCnt=0, oddCnt=0;
int digit=get_num() % 10;
switch (digit) {
case 1,3,5,7,9:
oddcnt++;
break;
case 2,4,6,8,10:
evencnt++;
break;
}
(d) unsigned ival=512, jval=1024, kval=4096;
unsigned bufsize;
unsigned swt=get_bufCnt();
switch (swt) {
case ival:
bufsize=ival*sizeof(int);
break;
case jval:
bufsize=jval*sizeof(int);
break;
case kval:
bufsize=kval*sizeof(int);
break;
}

5.3.2


Оператор switch предоставляет удобный способ выбора одной из множества альтернатив.
Синтаксис:
switch (выражение)
case 1:
break;
case 2:
break;

Оператор switch вычисляет результат выражения (или объявление инициализированной переменной). Выражение  преобразуется в целочисленный тип. Результат сравнивается со значением, ассоциированным с каждым оператором case.

После обнаружения соответствующей метки case выполнение начинается с нее и через все последующие метки case до конца или до прерывания. После каждого case обычно ставят прерывание break, если только не нужно специально этого избежать.

default - это метка, которая выполняется в том случае, если ни одна из меток case не сработала.
switch (выражение)
case 1:
break;
default:
break;

Метка default не может быть автономной, она должна предшествовать оператору или другой метке case. Если оператор switch заканчивается разделом default, в котором не осуществляется никаких действий, за меткой default должен следовать пустой оператор или пустой блок.

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

5.9. Напишите программу, использующую серию операторов if для подсчета количества гласных букв в тексте, прочитанном из потока cin.
#include <iostream>
#include <string>
int main()
{
std::string s;
getline(std::cin, s);
std::string::iterator it=s.begin();
unsigned aCnt=0;
unsigned eCnt=0;
unsigned uCnt=0;
unsigned iCnt=0;
unsigned oCnt=0;
while(it!=s.end()){
if (*it=='a') ++aCnt;
else if (*it=='e') ++eCnt;
else if (*it=='u') ++uCnt;
else if (*it=='i') ++iCnt;
else if (*it=='o') ++oCnt;
++it;
}
std::cout << "a="<< aCnt << std::endl;
std::cout << "e="<< eCnt << std::endl;
std::cout << "u="<< uCnt << std::endl;
std::cout << "i="<< iCnt << std::endl;
std::cout << "o="<< oCnt << std::endl;
return(0);
}

5.10. Программа подсчета гласных имеет одну проблему: она не учитывает заглавные буквы как гласные. Напишите программу, которая подсчитывает гласные буквы как в верхнем, так и в нижнем регистре. То есть значение счетчика aCnt должно увеличиваться при встрече как символа 'a', так и символа 'A' (аналогично для остальных гласных букв).
Из предыдущего упражнения программу беру и меняю цикл на следующий:
while(it!=s.end()){
if (*it=='a' || *it=='A' ) ++aCnt;
else if (*it=='e' || *it=='E') ++eCnt;
else if (*it=='u' || *it=='U') ++uCnt;
else if (*it=='i' || *it=='I') ++iCnt;
else if (*it=='o' || *it=='O') ++oCnt;
++it;

5.11. Измените рассматриваемую программу так, чтобы она подсчитывала также количество пробелов, символов табуляции и новой строки.
При работе с символами строки была функция, которая выглядела так:
isspace(c) /* Возвращает значение true, если с - символ отступа (пробел, табуляция, вертикальная табуляция, возврат, новая строка или прогон станицы) */
Если использовать char, то пробелы не сосчитать, если вектор, то в его элемент записывается все, что набрал до нажатия enter. Соответственно к подсчету пробелов и табуляций просто добавлю количество элементов.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string s;
std::vector<std::string> vstring;
while(getline(std::cin, s))
vstring.push_back(s);
unsigned aCnt=0;
unsigned eCnt=0;
unsigned uCnt=0;
unsigned iCnt=0;
unsigned oCnt=0;
unsigned space=0;
auto it=vstring.begin();
int cnt=0;
while(it!=vstring.end()){
std::string s=vstring[cnt];
for (auto i: s) {
if (i=='a' || i=='A' ) ++aCnt;
else if (i=='e' || i=='E') ++eCnt;
else if (i=='u' || i=='U') ++uCnt;
else if (i=='i' || i=='I') ++iCnt;
else if (i=='o' || i=='O') ++oCnt;
else if (isspace(i) ) ++space; }
++it; ++cnt;
}
std::cout << "a="<< aCnt << std::endl;
std::cout << "e="<< eCnt << std::endl;
std::cout << "u="<< uCnt << std::endl;
std::cout << "i="<< iCnt << std::endl;
std::cout << "o="<< oCnt << std::endl;
std::cout << "space, tab or enter="<< space+vstring.size() << std::endl;
return(0);
}
Цикл в программе можно сделать так:
while(it!=vstring.end()){
std::string s=vstring[cnt];
for (int i=0; i!=s.size();++i) {
if (s[i]=='a' || s[i]=='A' ) ++aCnt;
else if (s[i]=='e' || s[i]=='E') ++eCnt;
else if (s[i]=='u' || s[i]=='U') ++uCnt;
else if (s[i]=='i' || s[i]=='I') ++iCnt;
else if (s[i]=='o' || s[i]=='O') ++oCnt;
else if (isspace(s[i]) ) ++space; }
++it; ++cnt;
}

5.12. Измените рассматриваемую программу так, чтобы она подсчитывала количество встреченных двухсимвольных последовательностей ff, f1, fi.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string s;
std::vector<std::string> vstring;
while(getline(std::cin, s))
vstring.push_back(s);
unsigned ffCnt=0;
unsigned flCnt=0;
unsigned fiCnt=0;
auto it=vstring.begin();
int cnt=0;
while(it!=vstring.end()){
std::string s=vstring[cnt];
for (int i=0; i!=s.size();++i) {
if (s[i]=='f' && s[i+1]=='f') {++ffCnt; ++i;}
else if (s[i]=='f' && s[i+1]=='l') { ++flCnt; ++i;}
else if (s[i]=='f' && s[i+1]=='i') { ++fiCnt; ++i;}
}
++it; ++cnt;
}
std::cout << "ff="<< ffCnt << std::endl;
std::cout << "fl="<< flCnt << std::endl;
std::cout << "fi="<< fiCnt << std::endl;
return(0);
}

5.13. Каждая из приведенных ниже программ содержит распространенную ошибку. Выявите и исправьте каждую из них.
(a) unsigned aCnt=0, eCnt=0, iouCnt=0;
char ch=next_text();
switch (ch) {
case 'a': aCnt++;
case 'e': eCnt++;
default: iouCnt++;
}
Пропущен оператор break;
unsigned aCnt=0, eCnt=0, iouCnt=0;
char ch=next_text();
switch (ch) {
case 'a':  aCnt++;
break
case 'e': eCnt++;
break;
default: iouCnt++;
break;
}
так как default в конце, то break вроде как не обязателен, но рекомендуют ставить, чтобы не запутаться.

(b) unsigned index=some_value();
switch (index) {
case 1:
int ix=getvalue();
ivec[ix]=index;
break;
degault:
ix=ivec.size()-1;
ivec [ix]=index;
}

(b) unsigned index=some_value();
switch (index) {
case 1:
int ix;
ix=get_value(); /* одновременно объявлять и инициализировать нельзя внутри метки оператора switch, но можно сначала объявить, потом инициализировать */
ivec[ix]=index;
break;
default:
ix=ivec.size()-1;
ivec[ix]=index;
break;
}

(c) unsigned evenCnt=0, oddCnt=0;
int digit=get_num() % 10;
switch (digit) {
case 1,3,5,7,9:
oddcnt++;
break;
case 2,4,6,8,10:
evencnt++;
break;
}

unsigned evenCnt=0, oddCnt=0;
int digit=get_num() % 10;
switch (digit) {
case 1: case 3: case 5: case 7: case 9: // перечисление меток только так
oddCnt++; // регистр значимый
break;
case 2: case 4: case 6: case 8: case 10: // перечисление меток только так
evenCnt++; // регистр значимый
break;
}

(d) unsigned ival=512, jval=1024, kval=4096;
unsigned bufsize;
unsigned swt=get_bufCnt();
switch (swt) {
case ival:
bufsize=ival*sizeof(int);
breal;
case jval:
bufsize=jval*sizeof(int);
break;
case kval:
bufsize=kval*sizeof(int);
break;
}

Так-то в теме об этом ни слова, но
unsigned const ival=512, jval=1024, kval=4096; - вот так работает. То есть, если используется как метка, то должна быть константной переменной.

Добавить комментарий