| Украина, Луганская обл., г. Рубежное |
Препроцессор, оформление программы и средства ввода/вывода
В этом случае, несмотря на то, что в Си нет динамических массивов и их размер должен указываться при инициализации, при передаче параметров допускается указывать "открытые" массивы. Но тогда разработчик должен самостоятельно позаботиться о том, чтобы сообщить функции размер конкретного массива, который передается в ходе работы программы. В приведенном примере передаваемая строка всегда заканчивается символом конца строки '\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;
}