Россия, г. Санкт-Петербург |
Препроцессор, оформление программы и средства ввода/вывода
В этом случае, несмотря на то, что в Си нет динамических массивов и их размер должен указываться при инициализации, при передаче параметров допускается указывать "открытые" массивы. Но тогда разработчик должен самостоятельно позаботиться о том, чтобы сообщить функции размер конкретного массива, который передается в ходе работы программы. В приведенном примере передаваемая строка всегда заканчивается символом конца строки '\0', поэтому можно последовательно перебирать элементы массива, пока не встретится символ '\0', и не опасаться выйти за границы массива. Если же конечного символа не предусматривается (в большинстве случаев в массиве хранятся не строки, а единообразные данные, не заканчивающиеся никаким специальным элементом), то размер массива следует передать дополнительно:
void encodeAtbash(char str[], int arrayLength) { int i; for (i = 0; i < arrayLength; i++) { . . . } . . . }
А теперь вернемся к задаче, рассмотренной ранее в разделе 2, и посмотрим, как будет выглядеть реализация программы, соответствующая сформулированным требованиям.
Чтение строки может быть выполнено аналогично приведенному примеру кодирования строки алгоритмом "Атбаш", но считывать необходимо не 11, а 81 символ. Последний 81-й символ нужен, чтобы обработать ситуацию, когда пользователь ввел более 80-ти символов.
/******************************************************* Date: 10 January 2013 Description: string reading and encoding sample 2 *****************************************************/ #include <stdio.h> /******************************************************* * Name : isEnglishLetter * * Purpose : сhecks whether the symbol belongs to * English alphabet * Input : c - symbol * Output : none * Return : 1 – belongs, 0 – do not belongs * *****************************************************/ int isEnglishLetter(char c) { if( (c >= 'a') && ( c <= 'z' ) ) { return 1; } if ( (c >= 'A') && (c <= 'Z') ) { return 1; } return 0; } /******************************************************* * Name : isRussianLetter * * Purpose : checks whether the symbol belongs to * Russian alphabet * Input : c - symbol * Output : none * Return : 1 – belongs, 0 – do not belongs ******************************************************/ int isRussianLetter(char c) { if( (c >= 'а') && ( c <= 'я' ) ) { return 1; } if ( (c >= 'А') && (c <= 'Я') ) { return 1; } return 0; } /******************************************************* * Name : isNumber * * Purpose : checks whether the symbol is number * Input : c - symbol * Output : none * Return : 1 – number, 0 – not a number ******************************************************/ int isNumber(char c) { if( ((int)c >= (int)'0') && ( (int)c <= (int)'9' ) ) { return 1; } return 0; } /******************************************************* * Name : isDelimeter * * Purpose : checks whether the symbol is a delimiter * Input : c - symbol * Output : none * Return : 1 – delimiter, 0 – not a delimiter ******************************************************/ int isDelimeter(char c) { if( (c == ',') || (c == '.') || (c == ' ') || (c == '\0') ) { return 1; } else { return 0; } } /******************************************************* * Name : testString * * Purpose : test string for correctness * (according requirements) * Input : str (string to check) * Output : none * Return : * -1 bad string * 0 good string (only acceptable characters) ******************************************************/ int testString(char *str) { int start; int goodSymb; int count; count = 0; start = 0; while(*str) { goodSymb = 0; if (isEnglishLetter(*str)) { start = 1; goodSymb = 1; } if (isRussianLetter(*str)) { start = 1; goodSymb = 1; } if (isNumber(*str)) { start = 1; goodSymb = 1; } if ( (*str) == ' ' ) { goodSymb = 1; } if ( (isDelimeter(*str)) && start ) { goodSymb = 1; } if (goodSymb == 0) { return 0; } else { str++; count++; } } if (count > 10) { return 0; } else { return 1; } } /******************************************************* * Name : replaceLineEnd * Purpose : replaces ending '\n' (if exists) * symbol by '\0' symbol * except English small characters * Input : str (string) * Output : str (string) * Return : none ******************************************************/ void replaceLineEnd(char *str) { int i; char temp[2]; for(i=0; ( (*(str+i)!='\n') && (*(str+i)!='\0') ); i++); if ( *(str+i) == '\0' ) { /* empty input buffer */ while (temp[0] != '\n') \ { fgets(temp,2,stdin); } } if ( *(str+i) == '\n' ) { *(str+i) = '\0'; } } /******************************************************* * Name : readString * * Purpose : reads string from keyboard * Input : str (empty string) * Output : str (inputted string) * Return : none ******************************************************/ void readString(char *str) { /* reads only 81 chars from keyboard, 82 sets to '\0' */ fgets(str,82,stdin); replaceLineEnd(str); } /******************************************************* * Name : change231 * Purpose : ncodes word in string str using 231 exchange * Input : str (string), * startPos – position in string * where the word starts from * Output : str (encoded string) * Return : encoded word end position in str ******************************************************/ int change231(char *str, int startPos) { int i; char temp; i = startPos + 1; while (!isDelimeter(str[i])) { temp = str[i]; str[i] = str[i-1]; str[i-1] = temp; i++; if (((i-startPos)%3 == 0) && (!isDelimeter(str[i]))) { i++; } } return i; } /****************************************************** * Name : processString * Purpose : encode words in string * leaving delimiters unchanged * Input : str (string), * Output : str (encoded string) * Return : none ******************************************************/ void processString(char *str) { int i; i = 0; while( *(str+i) != '\0' ) { if (isDelimeter(*(str+i))) { i++; } else { i = change231(str, i); } } } int main() { /* max length 80 + 1 for ending symbol + 1 to test >80 entered symbols */ char str[82]; printf("Введите строку для кодирования\n"); readString(str); while(*str != '\0') { if (testString(str) == 0) { printf("Ошибка во входной строке\n"); } else { processString(str); printf("%s\n", str); } printf("Введите строку для кодирования\n"); readString(str); } printf("Работа закончена"); return 0; }