Практика программирования (Бейсик, Си, Паскаль)

       

Сформировать на экране таблицу ASCII


Задание 3.01. Формирование таблицы ASCII

Сформировать на экране таблицу ASCII таким образом, чтобы в ней были представлены все отображаемые символы 866-й кодовой страницы и их числовые коды. Один из возможных вариантов заполнения экрана такой таблицей представлен на рис. 3.1.

Совет 1 (общий)

Приведенная выше таблица содержит 21 кодовую строку, и смещение начальных кодов в смежных колонках равно 21. Поэтому внешний цикл повторяется 21 раз, начинаясь с первого отображаемого кода (32 — код пробела). Так как заголовок отделен от таблицы одной пустой строкой, вывод начинается с 3-й строки (3 = 32 - 29). А дальше остается только перебирать все коды отображаемого диапазона (от 32 до 255) и выводить пары "символ-код" по фиксированному формату — одна позиция под символ, разделяющий пробел, три позиции — под числовой код и пара пробелов между колонками.


Рис. 3.1. Таблица ASCII

Программа 3_01.bas

RЕМ Вывод таблицы ASCII

CLS : PRINT TAB(31); "Таблица ASCII"

FOR I=32 TO 52: LOCATE I-29,1

FOR J=I TO 255 STEP 21

PRINT USING "! ### ";CHR$(J);J;

NEXT J


NEXT I

Программа 3_01.с

/* Вывод таблицы ASCII */
#include <stdio.h>

main() {

int i,j;

clrscr ();

gotoxy(31,1);

printf("Таблица ASCII");

for (i=32; i<=52; i++) {

gotoxy(1,i —2 9) ;
for (j=i; j<=255; j+=21)
printf("%c %3d ",j,j);
} getch();

}

Программа 3_01.pas

program ASCII; {Вывод таблицы ASCII} uses Crt; var

i,j:word; begin clrscr;
gotoxy(31,1);
write('Таблица ASCII');
for i:=32 to 52 do
begin

gotoxy(l,i-29);

j:=i;

repeat

write(chr(j) :l,j:4, ' ');
j:=j+21;
until j>255;
end;
readln;
end.

Задание 3.02. Преобразование строк к верхнему регистру

Составить подпрограмму (функцию) up (s), которая заменяет в строке s коды малых букв кодами аналогичных больших букв с учетом их расположения в таблице ASCII.

Совет 1 (общий)



  • [97,122] — строчные латинские буквы от "а" до "z";

  • [160,175] — строчные русские буквы от "а" до "п";

  • [224,239] — строчные русские буквы от "р" до "я";

  • [241,241] — буква "ё".

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


    Совет 2 (QBasic)

    Для выделения и изменения j-гo символа строки s удобнее всего воспользоваться функцией (оператором) MID$(S,J, 1). Анализ на принадлежность одному из кодовых интервалов, подлежащему замене, целесообразно оформить в виде переключателя SELECT CASE — END SELECT. Наконец, функции ASC и CHR$ понадобятся, соответственно, для преобразования символа в код ASCII и модифицированного кода в символ эквивалентной большой буквы.

    В приводимых ниже двух вариантах программы преобразование к верхнему регистру выполнено в виде подпрограммы UP и функции UP$. Чтобы не портить аргумент функции и другие глобальные переменные головной программы, в теле функции объявлены свои локальные переменные в и j.

    Совет 3 (Си)

    Обратите внимание на то, что локальный массив ь, объявленный в теле функции up, имеет тип unsigned char, а не char. Объясняется это тем, что проверяемые коды (а они в теле функции выступают как числа) принадлежат диапазону [0,255].

    Совет 4 (Паскаль)

    Обратите внимание на то, что в теле функции не понадобился промежуточный массив b, т. к. параметр а передавался не по адресу (не var a:string), а по значению. Поэтому исходная строка оказалась в стеке, и ею можно было воспользоваться в теле функции, не опасаясь порчи параметра в вызывающей программе.

    Программа 3_02.bas

    REM Замена малых русских букв большими

    DECLARE SUB UP (A$)

    PRINT "Введите строку, содержащую малые и большие буквы"

    INPUT "",A$

    UP A$

    PRINT A$ END

    SUB UP(A$)

    FOR j=l TO LEN(A$)

    SELECT CASE MID$(A$,j,l)

    CASE "a" TO "z": MID$(A$,j,1)=CHR$(ASC(MID$(A$, j , 1) )-32)


    CASE "a" TO "n": MID$(A$,j,l)=CHR$(ASC(MID$(A$,j,l))-32)

    CASE "p" TO "я": MID$(A$,j,1)=CHR$(ASC(MID$(A$,j,1))-90)

    CASE "e": MID$(A$,j,l)="E"
    END SELECT
    NEXT j
    END SUB

    Программа 3_02a.bas

    RЕМ Замена малых русских букв большими

    DECLARE FUNCTION UP$(A$)

    PRINT "Введите строку, содержащую малые и большие буквы"

    INPUT "",A$

    B$=UP$(A$)

    PRINT A$

    PRINT B$

    END

    FUNCTION UP$(A$)

    'Чтобы не испортить аргумент А$, введена локальная переменная

    DIM В AS STRING

    В=А$

    FOR J=l TO LEN(A$)

    SELECT CASE MID$(В,J,1)

    CASE "a" TO "z": MID$ (B, J, 1) =CHR$ (ASC (MID$ (B, J, 1) )-32)
    CASE "a" TO "n": MID$ (B, J, 1)=CHR$ (ASC (MID$ (B, J, 1) ) -32)
    CASE "p" TO "я": MID$(B,J,1)=CHR$(ASC(MID$(B,J,1))-80)
    CASE "e": MID$(B,J,1)="E"
    END SELECT

    NEXT J

    UP$=B

    END FUNCTION

    Программа 3_02.с

    /* Замена малых русских букв большими */
    # include <stdio.h>

    #include <conio.h>
    #include <string.h>
    char *up(char *a);

    void main() {

    char a[80],*b;

    printf("\n Введите строку, содержащую малые и большие буквы\n");

    gets(a);

    b=up(а);

    printf("\na=%s",a);

    printf("\nb=%s",b);

    getch (); }

    char *up(char *a) {

    unsigned char b[80]; int j ;

    strcpy(b,a);

    for(j=0; j<strlen(a); j++) {

    if ( 97<=b[j] && b[j]<=122) b[j]-=32;
    if (160<=b[j] && b[j]<=175) b[j]-=32;
    if (224<=b[j] && b[j]<=239) b[j]-=80;
    if (241==b[j]) b[j]— ; }

    return b; }

    Программа 3_02.pas

    program UperCase;

    { Замена малых русских букв большими }

    var

    a,b>:string[80] ; function up(a:string):string; var

    j:integer;

    begin

    for j:=1 to length(a) do

    case a[j] of

    'a1..'z': a[j] :=chr (ord (a [ j ] )-32) ;

    'a'.,'n'; a[j]:=chr(ord(a[j])-32);
    'р'.'я': a[j]:=chr(ord(a[j])-80);
    'ё': a[j]:='Ё'; end;

    up:=a; end; begin

    writeln('Введите строку, содержащую малые и большие буквы ');


    readln(a);

    b:=uр(а);

    writeln(a);

    writeln(b);

    readln;
    end.

    Задание 3.03. Сортировка-фамилий

    Составить программу, которая запрашивает у пользователя 10 фамилий, сортирует их по алфавиту и выводит отсортированный список. Пока сортируемый массив мал, мы не будем обращать внимание на эффективность алгоритма сортировки. Один из следующих разделов специально будет посвящен этому достаточно сложному и важному вопросу.

    Так как программа должна сортировать фамилии, то следует установить правила их набора на клавиатуре, исключающие неоднозначность результатов сравнений:

  • вначале набирается фамилия, вслед за которой через пробел могут следовать однобуквенные инициалы, завершаемые точками;

  • первая буква фамилии и символы инициалов должны быть большими;

  • фамилии должны набираться либо только русскими, либо только латинскими буквами;

  • допускается набор составных фамилий с использованием разделяющего символа (например, Петров-водкин);

  • буквы Ё и ё в фамилиях заменяются буквами Е и е.

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

    Совет 1 (общий)

    Для повышения наглядности результатов работы программы можно вывести на экран два списка фамилий: слева — неупорядоченный, справа — упорядоченный.

    Совет 2 (QBasic)

    Для перевода курсора в позицию, соответствующую очередной строке списка, надо воспользоваться оператором LOCATE row, col (row — номер строки, col — номер столбца).

    Совет 3 (Си)

    В программе 3_03а.с демонстрируется одна из уловок, повышающая эффективность работы любой программы сортировки достаточно длинных документов. С подобного рода приемами вы неоднократно сталкивались, но, возможно, не обращали на них внимания. Например, на панелях Norton Commander'a можно выбрать один из нескольких способов упорядочения оглавления — по именам файлов, по их расширениям, по размерам, по датам создания, в порядке появления файлов на диске. Естественно, что такого рода сортировки не производят никаких перемещений файлов на диске. Вместо этого происходят перестановки каких-то указателей в оперативной памяти.


    В программе 3_03а. с для размещения фамилий использованы динамически запрашиваемые строки, на начало которых "смотрят" элементы массива указателей типа char (см. обращение к функции malloc). Вместо перестановки фамилий, расположенных не в алфавитном порядке, меняются местами соответствующие 4-байтовые указатели.

    Перевод курсора в начало очередной строки списка осуществляется функцией gotoxy (col, row), последовательность параметров которой прямо противоположна соответствующему оператору QBasic.

    Программа 3_03b!с построена менее замысловато. В ней использован двумерный массив для хранения фамилий, да и вывод результатов оформлен попроще.

    Программа 3_03.bas

    RЕМ Сортировка фамилий DIM NAMES(10)

    N=10

    CLS

    FOR J=l TO 10

    INPUT "Введи очередную фамилию - ", NAMES(J)

    NEXT J CLS

    PRINT "Фамилии до упорядочения : " FOR J=l TO N

    LOCATE J+2,1: PRINT NAMES(J)

    NEXT J

    FOR J=l TO N-l
    FOR K=J+1 TO N

    IF NAME$(J)>NAME$(K) THEN
    TMP$=NAME$(J)
    NAME$(J)=NAME$(K)
    NAMES(K)=TMP$
    END IF
    NEXT К
    NEXT J
    LOCATE 1,40

    PRINT "Фамилии после упорядочения :"
    FOR J=l TO N

    LOCATE J+2,40: PRINT NAME$(J)
    NEXT J
    END

    Программа 3_03а.с

    /* Сортировка фамилий */
    #include <stdio.h>
    #include <alloc.h>
    #include <conio.h>
    #include <string.h>

    main()

    {

    #define n_max 10

    #define len_max 20

    int j,k;

    char tmp[len_max], *names[n_max], *p;

    clrscr();

    for(j=0; j< n_max; j++) {

    printf("\n Введи очередную фамилию - ");
    scanf("%s",tmp);
    names[j]=(char *)malloc(len_max);

    strcpy(names[j],tmp); }

    clrscr () ;

    printf("Фамилии до упорядочения :");
    for(j=0; j<n_max; j++) {

    gotoxyd, j+2) ;
    printf("%s",names[j]); }

    for(j=0; j<n_max-l; j++)
    for(k=j+l; k<n_max; k++) {

    if (strcmp(names[j],names[k]) > 0} {

    p=names[j];
    names[j]=names[k] ;
    names[k]=p; } }

    gotoxy(40,1);

    printf("Фамилии после упорядочения :");
    for(j=0; j<n_max; j++) {


    gotoxy(40,j+2);
    printf("%s",names[j]) ; }

    getch(); }

    Программа 3_03b.c

    /* Сортировка фамилий */
    #include <stdio.h>

    #include <conio.h>
    #include <string.h>
    #define N 10

    main () {

    cnar a[N][20],tmp[20];
    int i,j; Clrscr () ;

    puts(" Введите 10 фамилий по одной в строке");
    for(i=0; i<N; i++)

    gets(&a[i][0]);
    for(1=0; i<N-l; 1++)
    for(j=i+l; j<N; j++)

    if(strcmp(&a[i] [0], &a[j] [0])>0) {

    strcpy(tmp,&a[i][0]);
    strcpy(&a[i][0],&a[j][0]);
    strcpy(&a[j][0],tmp); }

    puts("А теперь они же по алфавиту");
    for (1=0; i<N; i++)

    puts(&a[i][0]);
    getch(); }

    Программа 3_03.pas

    program sort;

    { Сортировка фамилий }

    uses crt;

    const

    n=10; var

    j,k:integer; tmp:string[20];

    name:array [l..n] of string[20];
    begin cirscr;

    for j:=1 to n do begin

    writeln('Введи очередную фамилию');
    readln(name[j]); end;

    clrscr;

    writeln('Фамилии до упорядочения :');
    for j :=1 to n do
    begin

    gotoxy(1,j+2);
    write(name[j]);
    end;
    for j:=1 to n-1 do

    {

    for k:=j+l to n do
    begin

    if name[j]>name[k] then
    begin

    tmp:=name [j];
    name[j]:=name[k];
    name[k]:=tmp;
    end
    end;

    gotoxy(40,l);

    writeln('Фамилии после упорядочения :');
    for j:=1 to n do
    begin

    gotoxy (40,j+2);
    write(name[j]);
    end;
    readln;
    end.

    Задание 3.04. Подсчет числа слов в строке

    Предполагая, что вводимая строка содержит не более 80-ти символов и состоит из "слов", разделенных одним или более пробелами, подсчитать количество слов в строке. Обратите внимание на критические ситуации — строка пуста, строка состоит из одних пробелов, строка содержит единственное слово, слова могут содержать единственный символ, отличный от пробела.

    Совет 1 (общий)

    В начале следует проверить длину введенной строки и, если она равна 0, сообщить, что число слов тоже равно 0. Затем имеет смысл проверить первый символ строки и, если он отличен от пробела, зафиксировать начало первого слова. Дальнейший анализ можно оформить в виде цикла, в котором проверяется очередной символ строки с учетом одной из двух возможных ситуаций - ему предшествовал пробел или символ, отличный от пробела. При переходе с пробела на непробел счетчик слов следует увеличить на 1. Переменная space хрэиит информацию о предшествующем символе — она равна 1 млм true, если предшествовавшим символом был пробел. Ее значение меняется на противоположное, если только один из двух смежных символов является пробелом.


    Программа 3_04.bas

    RЕМ Подсчет числа слов в строке

    CLS

    SPACE=1: WORDS=0

    PRINT "Введите строку"

    INPUT "",S$

    LENS=LEN(S$)

    IF LENS=0 THEN GOTO RET

    IF LEFT$(S$,1)<>" " THEN SPACE=0: WORDS=1

    FOR J=2 TO LENS

    IF SPACE=1 AND MID$(S$,J,1)<>" " THEN SPACE=0: WORDS=WORDS+1

    IF SPACE=0 AND MID$(S$,J,1)=" " THEN SPACE=1
    NEXT J
    RET:

    PRINT "Число слов в строке = "; WORDS
    END

    Программа 3_04.с

    /* Подсчет числа слов в строке */
    #include <stdio.h>
    #include <conio.h>
    #include <string.h>

    main() {

    char s[81], space=l, words=0, i,len;

    clrscr ();

    puts("Введите строку");

    gets (s) ;

    len=strlen(s);

    if (len=0) goto ret;

    if (s[0]!=' ') {

    space=0;

    words=l; }

    for(i=l; i<len; i++) (

    if (space==l &&, s[i]! = ' ') {

    space=0; words++; }

    if (space==0 && s[i]==' ')space=l; } ret:

    printf("\n Число слов в строке = %d",words);
    getch () ; }

    Программа 3_04.pas

    program num_words;

    { Подсчет числа слов в строке }

    label ret;

    var

    s:string[81];

    space:boolean;

    words:byte;

    i,len:byte; begin

    writeln('Введите строку');

    readln(s);

    len:=length(s);

    if len=0 then goto ret;

    space:=(s[1]=' ');

    if not space then words:=1;

    for i:=2 to len do

    begin

    if (not space)and(s[i]=' ') then space:=true;

    if (space)and(s[i]<>' ') then

    Degin

    space;=false; inc(words);
    end;
    end;
    ret:

    writeln('Число слов в строке = ',words);
    readln;
    end.

    Задание 3.05. Анализ нажатой клавиши

    Составить программу, которая анализирует код нажатой клавиши и выводит его на экран. Программа должна завершать свою работу после нажатия клавиши <Esc> (код клавиши равен 27).

    Совет 1 (общий)

    В программе необходимо организовать бесконечный цикл, прерываемый после приема кода клавиши <Esc>. К сожалению, обработку клавиши <Enter> не удается включить в цикл обработки обычных клавиш. В операторах вывода попытка отобразить символ с кодом 13 приводит либо к возврату курсора в начало строки и затиранию ранее напечатанного текста последующим сообщением (Си, Паскаль), либо к-переводу курсора в начало следующей строки (QBasic).


    Совет 2 (QBasic)

    Для ввода кода нажатой клавиши целесообразно использовать функцию (служебную переменную) INKEY$. Если нажата обычная клавиша, то INKEY$ выдает один символ, код которого можно определить по значению функции ASC. При нажатии функциональной клавиши в INKEY$ попадает два символа, первый из которых имеет нулевой код, поэтому выводить на экран надо код второго символа.

    Совет 3 (Си)

    Для ввода кода нажатой клавиши необходимо один (обычная клавиша) или два раза (функциональная клавиша) обратиться к функции getch.

    Совет 4 (Паскаль)

    Для ввода кода нажатой клавиши необходимо один (обычная клавиша) или два раза (функциональная клавиша) обратиться к функции readkey.

    Программа 3_05.bas

    RЕМ Анализ кода нажатой клавиши CLS

    GETKEY: A$=INKEY$: IF A$="" THEN GOTO GETKEY
    IF ASC(A$)=27 THEN STOP
    IF LEN(A$)=1 THEN

    IF ASC(A$)=13 THEN

    PRINT "Нажата клавиша Enter с кодом = 13": GOTO GETKEY

    END IF

    PRINT "Нажата обычная клавиша ' "; A$; " ' с кодом ="; ASC(A$)

    ELSE

    PRINT "Нажата управляющая клавиша с кодом ";ASC(RIGHT$(A$,1))
    END IF
    GOTO GETKEY

    Программа 3_05.с

    /* Анализ кода нажатой клавиши */ #include <stdio.h>

    main() { unsigned char ch;

    clrscr(); getkey:

    ch=getch();
    if(ch==27) exit(0);
    if(ch==13) {

    printf("\n Нажата клавиша Enter с кодом = 13");
    goto getkey; }

    if(ch==0) {

    ch=getch();

    printf("\n Нажата управляющая клавиша с кодом = %d",ch); }

    else printf("\n Нажата обычная клавиша %с с кодом=%d",ch,ch);
    goto getkey;
    }

    Программа 3_05.pas

    program keyboard;

    ( Анализ кода нажатой клавиши }

    uses Crt;

    label getkey;

    var

    ch:char;

    begin

    clrscr; getkey:

    ch:=readkey;

    if ord(ch)=27 then exit;
    if ord(ch)=13 then
    begin

    writeln('Нажата обычная клавиша Enter с кодом = 13');
    goto getkey;
    end;

    if ord(ch)=0 then
    begin

    ch:=readkey;

    writeln('Нажата управляющая клавиша с кодом = ',ord(ch));
    end else

    writeln('Нажата обычная клавиша "',ch,'" с кодом=',ord(ch));


    goto getkey; end.

    Программа 3_05a.pas

    program keyboard;

    { Анализ кода нажатой клавиши }

    uses Crt;

    var

    ch:char; begin clrscr; repeat

    ch:=readkey;

    if ord(ch)=13 then

    writeln('Нажата обычная клавиша Enter с кодом =13') else

    if ord(ch)=0 then

    begin

    ch:=readkey;
    writeln { 'Нажата управляющая клавиша с кодом = ' ,ord(ch) } ;

    end else

    writeln('Нажата обычная клавиша "',ch,'" с кодом = ',ord(ch});
    until ord(ch)=27;
    end.

    Задание 3.06. Три цвета радуги

    Мнемоническая фраза " Каждый охотник желает знать, где сидят фазаны" используется для запоминания последовательности цветовых оттенков радуги — красный, оранжевый, желтый, зеленый, голубой, синий, фиолетовый. Составить программу, которая вводит три слова, представляющие разные цвета радуги, и выводит их на экран в том порядке, в каком они должны быть расположены в описанной выше цветовой гамме. Например, введены слова желтый, красный и синий. На экран их следует вывести в "правильном" порядке — красный, желтый, синий.

    Совет 1 (общий)

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

    Программа 3_06.bas

    REM Упорядочение цветов радуги

    DATA "красный","оранжевый","желтый","зеленый"

    DATA "голубой","синий","фиолетовый"

    DIM А$ (7) , В$ (3)

    FOR I=0 ТО 6: READ A$(I): NEXT I

    PRINT "Введите по одному в строке 3 цвета радуги"

    FOR I=0 ТО 2: INPUT B$ (I): NEXT I

    PRINT "В радуге эти цвета следуют в таком порядке:"

    FOR J=0 TO 6: FOR I=0 TO 2

    IF A$(J)=B$(I) THEN PRINT A$(J)

    NEXT I: NEXT J

    END

    Программа 3_06.c

    /* Упорядочение цветов радуги */

    #include <stdio.h>

    #include <conio.h>

    #include <string.h> main()

    {

    char a[7][11]={"красный","оранжевый",

    "желтый","зеленый","голубой","синий","фиолетовый"};


    char b[3][11]; int i,j;

    printf("\n Введите по одному в строке 3 цвета радуги\n");
    for (i=0; КЗ; i++) gets (&b[i] [0] ) ;

    printf("\ nB радуге эти цвета следуют в таком порядке:\n");
    for(j=0; j<7; j++) for(i=0; i<3; i++)

    if(strcmp(&a[j][0],&b[i][0])==0)

    puts(&a[j][0]); getch(); }

    Программа 3_06.pas

    program raduga;

    { Упорядочение цветов радуги }

    const

    a:array [1..7] of string[10]=('красный','оранжевый',

    ' желтый', ' зеленый', ' голубой', ' синий', ' фиолетовый') ;
    var

    b:array [1..3] of string[10];

    i,j:byte; begin

    writeln('Введите по одному в строке 3 цвета радуги');

    for i:=l to 3 do readln(b[i]);

    writeln('В радуге эти цвета следуют в таком порядке:');

    for j:=1 to 7 do
    for i:=l to 3 do

    if a[j]=b[i] then writeln(a[j]);
    readln;
    end.

    Задание 3.07. Левый и правый прижим, центрирование текста при выводе

    Составить программу, которая запрашивает у пользователя текст, содержащий не более 20-ти символов, и выводит его в рамках колонки, расположенной с 10-й по 50-ю позиции с разными вариантами прижима. Для контроля правильности работы программы можно ограничиться вводом единственного символа и выдачей на экран строки, маркирующей номера колонок.

    Совет 1 (QBasic)

    Для смещения текста в нужную позицию строки можно воспользоваться либо функцией TAB, либо переводом курсора с помощью оператора LOCATE.

    Совет 2 (Си, Паскаль)

    Для перевода курсора в нужную позицию текущей строки можно воспользоваться процедурой gotoxy, у которой в качестве первого аргумента задан номер начальной колонки, а в качестве второго — значение функции wherey, соответствующее номеру текущей строки.

    Программа 3_07.bas

    CLS

    PRINT "Введите строку, содержащую не более 20 символов"

    FOR I = 1 ТО 8: PRINT "1234567890"; : NEXT I

    INPUT "", A$

    PRINT "Вывод, начиная с 10-й позиции :"

    FOR I = 1 ТО 8: PRINT "1234567890"; : NEXT I

    PRINT TAB(10); A$

    PRINT "Вывод по центру между 10-й и 50-й позициями :"


    FOR I = 1 ТО 8: PRINT "1234567890"; : NEXT I

    PRINT TAB(10 + (50 - 10) / 2 - LEN(A$) / 2); A$

    PRINT "Вывод с прижимом к 50-й позиции :"

    FOR I = 1 ТО 8: PRINT "1234567890"; : NEXT I

    PRINT TAB(51 - LEN(A$)); A$

    END

    Программа 3_07.с

    #include <stdio.h>
    #include <conio.h>

    #include <string. h>

    main()

    {

    char str[20], rule [] ="1234567890";
    int i;

    clrscr () ;

    puts(" Введите строку, содержащую не более 20 символов");
    for(i=0; i<8; i++)
    printf("%s",rule);
    gets (str) ;

    puts("Вывод, начиная с 10-й позиции :");
    for(i=0; i<8; i++) printf("%s",rule);
    gotoxy(10,wherey()); puts (str) ;

    puts("Вывод по центру между 10-й и 50-й позициями :");
    for(i=0; i<8; i++) printf("%s",rule);

    gotoxy(10+(50-10)/2-strlen(str)/2,wherey());
    puts(str);
    puts("Вывод с прижимом к 50-й позиции :");
    for (i=0; i<8; i++) printf("%s", rule);
    gotoxy(51-strlen(str),wherey());
    puts(str);

    getch(); }

    Программа 3_07.pas

    program text_justify;

    uses Crt;

    const

    rule:string='1234567890'; var

    s:string[20];

    i:integer; begin

    clrscr;

    writeln('Введите строку, содержащую не более 20 символов');

    for i:=0 to 7 do write(rule);

    readln(s);

    writeln('Вывод, начиная с 10-й позиции :');

    for i:=0 to 7 do write(rule);

    gotoxy(10,wherey); writeln(s);

    writeln('Вывод по центру между 10-й и 50-й позициями :');

    for i:=0 to 7 do write(rule);

    #include <string.h>

    main() {

    char str[20], rule[]="1234567890";

    int i ;

    clrscr();

    puts("Введите строку, содержащую не более 20 символов");
    for(i=0; i<8; i++)
    printf("%s",rule);
    gets (str) ;

    puts("Вывод, начиная с 10-й позиции :");
    for(i=0; i<8; i++) printf("%s",rule);
    gotoxy(10,wherey()); puts (str) ;

    puts("Вывод по центру между 10-й и 50-й позициями :");
    for (i=0; i<8; i++) printf("%s",rule);


    gotoxy(10+(50-10)/2-strlen(str)/2,wherey());
    puts(str); puts("Вывод с прижимом к 50-й позиции :");
    for (i=0; i<8; i++)
    printf("%s",rule);
    gotoxy(51-strlen(str),wherey());
    puts(str);

    getch(); }

    Программа 3_07.pas

    program text justify;

    uses Crt;

    const

    rule:string='1234567890'; var

    s:string[20];

    i:integer; begin

    clrscr;

    writeln(' Введите строку, содержащую не более 20 символов');

    for i:=0 to 7 do write(rule);

    readln(s);

    writeln('Вывод, начиная с 10-й позиции :');

    for i:=0 to 7 do write(rule);

    gotoxy(10,wherey); writeln(s);

    writeln('Вывод по центру между 10-й и 50-й позициями :');

    for i:=0 to 7 do write(rule);

    gotoxy(10+(50-10) div 2 - length(s) div 2,wherey);
    writeln(s); writeln{'Вывод с прижимом к 50-й позиции :');
    for i:=0 to 7 do write(rule);
    gotoxy(51-length(s),wherey);
    writeln(s);

    readln; end.

    Задание 3.08. Сравнение строк с игнорированием пробелов

    Написать подпрограмму-функцию compare, имеющую своими аргументами две строки, которая сравнивает их, игнорируя пробелы между словами и разницу между кодами больших и малых букв. Функция должна возвращать следующие значения: 1, если первая строка "больше" второй; -1, если первая строка "меньше" второй; о, если обе строки равны.

    Совет 1 (общий)

    Самым простым по реализации является алгоритм, в котором сначала коды всех малых букв заменяются кодами их больших эквивалентов, а затем из строк удаляются пробелы. Для выполнения первой процедуры можно воспользоваться функцией up (str) — см. программу 3_02.

    Программа 3_08.bas

    REM Сравнение строк с игнорированием пробелов

    DECLARE SUB UP(A$)

    DECLARE FUNCTION COMPARE(B$, C$)

    PRINT "Введите первую строку"

    INPUT "",A1$

    PRINT "Введите вторую строку"

    INPUT "", A2$

    K=COMPARE(A1$,A2$)

    IF K=l THEN PRINT "Первая строка 'больше'"

    IF K=-l THEN PRINT "Первая строка 'меньше'"

    IF K=G THEN PRINT "Обе строки равны"


    END

    FUNCTION COMPARE(B$,C$) DIM B1$,C1$

    UP B$: UP C$

    FOR J=l TO LEN(B$)

    IF MID$ (B$, J, 1)<>" " THEN B1$=B1$+MID$ (B$,J, 1 )

    NEXT J

    FOR J=l TO LEN(C$)

    IF MID$(C$,J,1)<>" " THEN C1$=C1$+MID$(C$,J,1) NEXT J

    IF B1$>C1$ THEN COMPARE=1 IF B1$=C1$ THEN COMPARE=0
    IF B1$<C1$ THEN COMPARE=-1 END FUNCTION

    SUB UP(A$)

    FOR J=l TO LEN(A$)

    SELECT CASE MID$(A$,J,1)

    CASE "a" TO "z": MID$ (A$, J, 1) =CHR$ (ASC (MID$ (A$, J, 1) )-32)
    CASE "a" TO "n": MID$(A$,J,1)=CHR$(ASC(MID$(A$,J,1))-32)
    CASE "p" TO "я": MID$(A$,J,1)=CHR$(ASC(MID$(A$,J,1))-80)
    CASE "ё": MID$(A$,J,1)="Ё" END SELECT

    NEXT J

    END SUB

    Программа 3_08.с

    /* Сравнение строк с игнорированием пробелов */

    #include <stdio.h>

    #include <conio.h>

    #include <string.h>

    char *up(char *a);

    int compare(char *s1, char *s2);

    void main() {

    char s1[80],s2[80];

    puts("Введите первую строку");

    gets (s1);

    puts("Введите вторую строку");

    gets(s2);

    switch(compare(s1,s2)) {

    case 1: puts("Первая строка 'больше'");break;

    case -1: puts("Первая строка 'меньше'");break;

    case 0: puts("Обе строки равны");

    }

    getch(); }

    char *up(char *a)

    {
    /* Замена кодов малых букв кодами больших */
    static unsigned char b[80]; int j ;

    strcpy (b, a) ;

    for(j=0; j<strlen(a); j++) {

    if(97<=b[j] && b[j]<=122) b[j]-=32;
    if(160<=b[j] && b[j]<=175) b[j]-=32;
    if (224<=b[j] && b[j]<=239) b[j]-=80;
    if (241==b[j]) b[j]—; }

    return b; }

    int compare(char *s1,char *s2) {

    char ssl[80],ss2[80]; char j,k;

    strcpy(s1,up(s1)};
    /* Замена малых букв большими */

    strcpy (s2*, up (s2) );
    /* с записью на то же место */
    for(j=0,k=0; j<strlen(sl); j++)

    if (sl[j] != ' ') ssl[k++]=sl[j];
    /* Извлекаем непробелы */
    ssl[k]=0x0; /* Добавили признак конца */

    for(j=0,k=0;
    j<strlen(s2); j++)


    if(s2[j]!=' ') ss2[k++]=s2[j];

    ss2[k]=0x0;

    k=atrcmp(ss1.ss2) /* Cравнили преобразованные строки */

    if(k>0)return 1;

    if(k<0)return 1;

    return 0;

    }

    Программа 3_08.pas

    program comp_string;

    { Сравнение строк с игнорированием пробелов }

    var

    s1,s2:string;

    function up (a:string):string; var

    j:integer; begin

    for j:=l to length(a) do
    case a[j] of

    'a'..'z': a[j] :=chr(ord(a[j])-32) ;
    'a'..'n': a[j]:= chr(ord(a[j])-32} ;
    'р'..'я': a[j]:= chr(ord(a[j])-80} ;
    'ё': a[j]:='E'; end; up:=a; end;

    function compare(s1,s2:string):integer;
    var

    ssl,ss2:string; j:byte;
    begin

    sl:=up(s1);

    s2:=up(s2);

    ssl:=' ';

    for j:=l to length(s1) do

    if sl[j]<>' ' then ssl:=ssl+sl[j];
    ss2:=' ';
    for j:=l to length(s2) do

    if s2[j]<>' ' then ss2:=ss2+s2[j];
    compare:=0;

    if ssl>ss2 then compare:=1;
    if ssl<ss2 then compare:=-!;
    end;
    begin

    writeln('Введите первую строку');
    readln(s1);

    writeln('Введите вторую строку');

    readln(s2);

    case compare(s1,s2) of

    1: writeln('Первая строка "больше"');
    -1: writeln('Первая строка "меньше"');

    0: writeln('06e строки равны');
    end;
    readln;
    end.

    Задание 3.09. Разноцветный текст

    Написать программу, которая выводит на экран текст, меняя цвет букв и цвет фона.

    Совет 1 (общий)

    В приведенных ниже текстах программ в пределах одного экрана демонстрируются две возможности. Во-первых, выводится строка, все символы которой окрашены в разные цвета. Для этого приходится каждый символ выдавать на экран отдельным оператором, предваряя вывод переустановкой цвета переднего плана. Выбранное для этой цели слово "ПРОГРАММИРОВАНИЕ" содержит ровно 16 букв, но каждый раз при очередной смене цвета фона одна из букв отображаемого слова имеет такой же цвет и не будет видна. Во-вторых, выводится строка, все символы которой имеют одинаковый цвет, не совпадающий с цветом фона. С помощью такой программы можно поэкспериментировать в подборе приятных цветовых сочетаний.


    Программа 3_09.bas


    RЕМ Разноцветный текст А$ = "ПРОГРАММИРОВАНИЕ"
    CLS

    ' Отображение разноцветных букв на допустимой фоновой гамме
    FOR CF=0 TO 7
    FOR CS=0 TO 15
    COLOR CS,CF LOCATE CF+1,2*CF+CS+1
    PRINT MID$(A$,CS+1,1)
    NEXT CS
    NEXT CF

    'Отображение мигающих разноцветных букв
    FOR CF=0 TO 7

    FOR CS=0 TO 15
    COLOR CS+16,CF
    LOCATE CF+1,2*CF+CS+41
    PRINT MID$(A$,CS+1,1)
    NEXT CS
    NEXT CF

    Программа 3_09.с

    /* Разноцветный текст */

    #include <conio.h>

    main() {

    int i ;

    textbackground(0);
    clrscr () ;

    for(i=0; i<24; i++) {

    gotoxy(2*i+l,i+l);
    textcolor(128+i);
    textbackground(i+2);

    cprintf("Цветовая гамма в текстовом режиме"); }

    getch(); }

    Программа 3_09а.с

    /* Разноцветный текст */
    #include <conio.h>

    main() {

    int i;

    textbackground(0) ;
    clrscr();

    for(i=0; i<24; i++) {

    gotoxy(2*i+l,i+1);

    textattr(128+i + ((i+1) « 4));

    cprintf("Цветовая гамма в текстовом режиме");

    }

    getch (); }

    Программа 3_09.pas

    program colorl;

    { Разноцветный текст }

    uses crt;

    var

    i:integer; begin

    textbackground(0); clrscr;

    for i:=0 to 23 do
    begin

    gotoxy(2*i+l,i+l);
    textcolor(128+i);
    textbackground(i+l);
    writeln('Тест цветовой гаммы ');
    end;
    readln;
    end.

    Задание 3.10. Преобразование обычной дроби в десятичную

    Составить функцию символьного (строкового) типа, преобразующую два своих целочисленных аргумента — числитель m и знаменатель п правильной дроби (m < n < 100) в строку, представляющую запись десятичной дроби. Для бесконечной дроби период следует заключить в круглые скобки. Например:

    m=3 n=5 значение функции - "0.6"

    m=1 n=6 значение функции - "0.1(6)"

    Совет 1 (общий)

    Очевидно, что количество цифр в десятичной дроби не превосходит 100, т. к. при последовательном делении на п мы можем получить не более чем п разных остатков (от 0 до п-1). Поэтому разумно завести массив для хранения остатков и при получении очередного остатка, отличного от 0, проверять, нет ли такого же среди ранее получавшихся. Как только новый остаток совпадет с одним из предыдущих, будет обнаружен период.


    Совет 2 (Си)

    К сожалению, среди строковых функций Си, включенных в заголовочный файл string.h, нет процедуры вставки символа в строку. Поэтому нам придется сдвигать вправо на одну позицию часть символов от начала периода и вставлять открывающуюся скобку. Не следует забывать и о вставке признака конца строки.

    Программа 3_10.bas

    RЕМ Преобразование обычной дроби в десятичную

    DECLARE FUNCTION FRAC2STR$(M%, N%)

    CLS : DEFINT A-Z

    INPUT "Введите числитель и знаменатель дроби : ",M,N

    PRINT M;"/";N;"= ";FRAC2STR$(M,N)

    END

    DEFSNG A-Z

    FUNCTION FRAC2STR$(M AS INTEGER,N AS INTEGER)

    DIM S AS STRING, REST(100) AS INTEGER

    DEFINT A-Z

    I=3: S="0."

    DO

    Q=M*10\N : P=M*10 MOD N: REST(I)=P
    IF P=0 THEN

    FRAC2STR=S+CHR$(Q+48) EXIT FUNCTION
    END IF
    FOR J=3 TO 1-1

    IF REST(J)=P THEN

    FRAC2STR=LEFT$(S, J-l}+"("+RIGHT$(S,LEN(S)-J+l)+")"

    EXIT FUNCTION
    END IF
    NEXT J

    S=S+CHR$(Q+48): I=1+1: M=P LOOP UNTIL P=0
    END FUNCTION

    Программа 3_10.с

    /* Преобразование обычной дроби в десятичную */
    #include <stdio.h>

    #include <conio.h>

    char *frac_to_str(char m,char n);

    main() {

    char m,n;

    printf("\n Введите числитель и знаменатель дроби : ");

    scanf("%d %d",sm,&n) ;

    printf("\n%d/%d=%s",m,n,frac_to_str(m,n));

    getch();

    }

    / *-----------------------------------------------* /

    char *frac_to_str(char m,char n) {

    int i=2,j,p,q;
    char rest[100];
    static char s [100]="0.";
    do {

    q=m*10/n; p=m*10%n; rest[i]=p;

    if(p==0) { s[i]=q+48;
    s[i+l]=0x0;
    return s; }
    for(j=2; j<i; j++)
    if(rest[j]==p) {

    for(p=i; p>=j; p--)

    s[p+l]=s[p];
    s[j]='(';
    s[i+l]=')';
    s [i+2]=0x0 ;
    return s ; }

    s[i]=q+48;
    i++;
    m=p; }

    while (p!=0); }

    Программа 3_10.pas

    program drobi;

    { Преобразование обычной дроби в десятичную }

    var

    m, n:byte;

    function frac_to_str(m,n:byte):string;
    var

    i,j,p,q:word;
    s:string;

    rest:array [1..100] of byte;


    begin

    s:='0.';

    i:=l;

    repeat

    q:=m*10 div n;
    p:=m*10 mod n;
    rest[i]:=p;
    if p=0 then begin

    frac_to_str:==s+chr (q+48) ;
    exit;
    end;
    for j:=l to i-1 do

    if p=rest[j] then
    begin insert(' (',s,j+2); frac_to_str:=s+')';
    exit;
    end;
    inc(i);

    s:=s+chr(q+48);
    m:=p;

    until p=0;
    end;
    begin

    writeln('Введите числитель и знаменатель дроби :');
    readln(m,n);

    writeln(m,'/',n, ' = ', frac_to_str(m,n));
    readln; end.

    Задание 3.11. Перевод чисел в римскую систему счисления

    Составить функцию символьного (строкового) типа, аргументом которой является натуральное число из интервала [1, 3999]. Функция должна возвращать строку с эквивалентным значением в формате римской системы счисления. Напомним, что в римской системе счисления используются большие латинские буквы — M(1000), O (500), C(100), L (50), X(10), V(5) и I(1). Если меньшая "цифра" находится левее "большей", то она вычитается (например: IV == V-I = 4, IX= X- I= 9, XL = L - X- 40). Если меньшая "цифра" расположена правее, то она прибавляется (например: VI = = V+ I= б, XI = X+ I= I I, LX = L + X = 60). Для некоторых "цифр" римская система допускает наличие до трех идущих подряд одинаковых

    цифр —
    I I= I + I = 2,
    I I I = I + I+ I= 3,
    XXX = X + X + X = 30,
    ССС == C+ C+ C= 300,
    MMM = M+ M+ M + 3000.

    Совет 1 (общий)

    Заведем два массива — символьный с наиболее характерными сочетаниями римских "цифр" и числовой с соответствующими значениями этих сочетаний. Оба массива разумно расположить в порядке убывания числовых значений (табл. 3.1).

    Таблица 3.1. Расположение массива в порядке убывания числовых названий



    Индекс элемента


    Символьный массив


    Числовой массив


    0


    M


    1000


    1


    CM


    900


    2


    D


    500


    3


    CD


    400


    4


    С


    100


    5


    ХС


    90


    6


    L


    50


    7


    XL


    40


    8


    X


    10


    9


    IX


    9


    10


    V


    5


    11


    IV


    4


    12


    I


    1


    Начинаем вычитать из переводимого числа первый элемент числового массива и вычитаем до тех пор, пока результат остается положительным. Каждый раз, когда вычитание возможно, к результирующей строке присоединяем соответствующее символьное значение. И так продолжаем экспериментировать с каждым элементом числового массива. Кстати, сумма всех элементов равна 3999, чем и объясняется ограничение на допустимый диапазон обрабатываемых чисел.


    Программа 3_11.bas

    RЕМ Перевод чисел в римскую систему

    DECLARE FUNCTION torome$ (M%)

    КЕМ Перевод арабских чисел в римскую систему счисления

    DEFINT A-Z

    COMMON SHARED ND()

    COMMON SHARED SD$()

    DATA 1,4,5,9,10,40,50., 90,100,400,500,900,1000

    DIM ND(13)

    FOR J=0 TO 12: READ ND(J): NEXT J

    DATA I, IV, V, IX, X, XL, L, XC, C, CD, D, CM, M

    DIM SD$(13)

    FOR J=0 TO 12: READ SD$(J): NEXT J

    INPUT "Введите целое число от 1 до 3999 : ", N

    IF N<1 OR N>3999 THEN PRINT "Число вне диапазона":
    END

    PRINT "В римской системе счисления "; N;" = ";torome$(N)

    END

    FUNCTION torome$ (M)

    SHARED ND(), SD$()

    S$=""

    FOR K=12 TO 0 STEP -1

    WHILE ND(K)<=M

    M=M-ND(K): S$=S$+SD$(K)
    IF M=0 THEN EXIT FOR

    WEND
    NEXT К
    torome$=S$
    END FUNCTION

    Программа 3_11.с

    /* Перевод чисел в римскую систему счисления */
    #include <stdio.h>.

    #include <conio.h>
    #include <string.h>
    char *to_rome(int n) ;

    main() {

    int N;

    printf("\n Введите целое число от 1 до 3999 : ");
    scanf("%d",&N); if (N<0 | | N>3999) {

    printf("\n Число вне диапазона");
    getch();
    exit(0); }

    printf("\n B римской системе счисления %d = %s",N,to_rome(N));
    getch();

    }

    /*-------------------------------*/

    char *to_rome(int n) {

    int k;

    static char s[20]="";

    int nd[13]={l,4,5,9,10,40,50,90,100,400,_500,900,1000};

    char *sd[13]={"I","IV","V","IX","X","XL",

    "L","XC","C","CD","D","CM","M"}; for(k=12; k>=0; k—) {

    while(nd[k]<=n) {

    n=n-nd[k]; strcat(s,sd[k]);
    if(n==0) break;
    } }

    return s; }

    Программа 3_11.pas

    program in_rome;

    {Перевод чисел в римскую систему счисления}

    var

    N:1..3999;

    function to_rome(n:integer): string;
    const

    nd:array [1..13] of integer=

    (1,4,5,9,10,40,50,90,100,400,500,900,1000) ;


    sd:array [1..13] of string=
    ( 'I', 'IV, 'V, 'IХ', 'X', 'XL',

    'L', 'XC', 'C','CD','D','CM', 'M');
    var

    k:integer;
    s:string;
    begin s : = " ;

    for k:=13 downto 1 do
    while nd[k]<=n do begin
    n:=n-nd[k];
    s:=s+sd[k];
    if n=0 then break;
    end;

    to_rome:=s;
    end; begin

    write ('Введите целое число от 1 до 3999 : ' ).; readln(N);

    writeln('B римской системе счисления ',N, ' = ', to_rome (N) ) ;
    readln;
    end.

    Задание 3.12. Перевод чисел из римской системы счисления

    Составить программу обратного преобразования из строки с записью числа в римской системе счисления в обычное число.

    Программа 3_12.bas

    REM Перевод чисел из римской системы счисления в арабскую

    DEFINT A-Z

    DATA 1,4,5,9,10,40,50,90,100,400,500,900,1000

    DIM ND(13)

    FOR J=0 TO 12: READ ND(J): NEXT J

    DATA I,IV,V,IX,X,XL,L,XC,C,CD,D,CM,M

    DIM SD$(13)

    FOR J=0 TO 12: READ SD$(J): NEXT J

    INPUT "Введите число в римской системе счисления : ", R$

    J=l: M=0

    100 :

    FOR К=12 ТО 0 STEP -1

    N=LEN(SD$(К))

    IF MID$(R$,J,N)=SD$(К) THEN M=M+ND(K): J=J+N: GOTO 100

    END IF

    IF J>LEN(R$) THEN EXIT FOR
    NEXT К

    PRINT "В арабской системе счисления ";R$;" = ";M
    END

    Программа 3_12a.bas

    REM Перевод чисел из римской системы счисления в арабскую
    DATA 1000,900,500,400,100,90,50,40,10,9,5,4,1
    DIM ND(13):
    FOR J=0 TO 12: READ ND(J): NEXT J
    DATA M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I
    DIM SD$(13): FOR J=0 TO 12: READ SD$(J): NEXT J
    INPUT "Введите число в римской системе счисления : ",R$
    FOR J=l TO LEN(R$)
    FOR K=0 TO 12

    N=LEN(SD$(K))

    IF MID$(R$,J,N)=SD$(К) THEN M=M+ND(K): J=J+1: K=K-1

    END IF NEXT К NEXT J

    PRINT "В арабской системе счисления ";R$;" = ";M
    END

    Программа 3_12.с

    /* Перевод чисел из римской системы счисления в арабскую */
    #include <stdio.h>

    #include <conio.h>
    #include <string.h>

    main() {

    int nd[13]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
    char *sd[13]={"M","CM","D","CD","C","XC","L","XL","X",


    "IX","V","IV","I"}; char r[20],s[3]; int j,k,n,m=0;

    printf("ХпВведите число в римской системе счисления : ");
    scanf("%s", r);
    for(j=0; j<strlen(r); j++)
    for(k=0; k<13; k++) {

    n=strlen(sd[k]);
    strncpyfs, &r.[j] ,n) ;
    s[n]=0;
    if(strcmp(s,sd[k])==0)

    { m += nd[k]; j++; k—; } }

    printf("\nB арабской системе счисления %s = %d",r,m);
    getch(); }

    Программа 3_12.pas

    { Перевод чисел из римской системы счисления в арабскую }

    program from rome;

    const

    nd:array [1..13] of integer=(1000,900,500,400,100,

    90,50,40,10,9,5,4,1);

    sd:array [1..13] of string=('M','CM','D','CD','C',

    'XC' , 'L', 'XL', 'X', 'IX1, 'V, 'IV, 'I' ) ; var

    r,s:string;

    j,k,n,m: integer; begin

    m:=0;

    write('Введите число в римской системе счисления : ');

    readln(r);

    J:=l;

    while j<=length(r) do begin k:=l;

    while k<=13 do begin

    n:=length(sd[k]);

    s:=copy(r,j,n);

    if s=sd[k] then begin

    inc(m,nd[k]); inc(j);
    dec(k);
    end;
    inc(k);
    end;
    inc(j);
    end;

    writeln('B арабской системе счисления ',r,' = ',m);
    readln;
    end.

    Задание 3.13. Вхождение строки с разрядкой

    Строка S2 может входить в более длинную строку S1 в общепринятом смысле, когда непрерывная подпоследовательность символов строки S1совпадает с цепочкой символов S2. Однако возможна и другая ситуация, когда строка S2 входит в строку S1 с разрядкой. При этом символы S2 с равномерным шагом через 1, 2, 3 или более символов встречаются в строке S1.

    Например, для строк S1="ABCBEEC" и S2="ABC" имеют место обычное (с нулевым шагом разрядки) вхождение (символы 1, 2 и 3 в строке si) и вхождение с разрядкой в 2 символа (символы 1, 4 и 7 в строке S1).

    Составить программу, которая:

  • запрашивает и вводит анализируемые строки S1 и S2;

  • определяет, входит ли строка S2 в S1, выдает шаг разрядки и номера соответствующих позиций в строке si.

    Задача программы — определить все возможные варианты вхождения S2 в S1.


    Совет 1 (общий)

    Идея поиска довольно проста. Обозначим через h шаг по индексу в строке S1, с которым выбираются символы, сравниваемые с символами S2. Для нулевой разрядки h=l, для выборки через символ h=2 и т. д. Очевидно, что начинать

    сравнение надо с символа S1[I], совпадающего с первым символом S2. Однако реализация этой идеи может быть разной. Например, из строки si можно извлечь с заданной разрядкой нужное число символов и результат сравнить с S2. Более эффективно совместить эти две операции и сравнивать извлекаемый из S1 символ с очередным символом S2, прекращая выборку при первом несовпадении. Указанный подход был реализован победителем областной студенческой олимпиады В. Мартьяновым (апрель 2000 г.), на базе программы которого и построены приведенные ниже примеры. Наиболее оригинальной, на наш взгляд, является проверка условия (h=l) или (L2>1). Здесь L2—длина второй строки.


    Программа 3_13.bas

    RЕМ Поиск вхождения S2 в S1 с разрядкой

    CLS

    INPUT "Введите S1: ", Sl$: L1=LEN(S1$)

    INPUT "Введите S2: ", 32$: L2=LEN(S2$)

    FOR H=l TO L1

    IF (H=l) OR (L2>1) THEN
    FOR I=1 TO Ll-(L2-l)*H

    IF MID$(S1$,I,1)=MID$(S2$,l,l) THEN
    FOR J=2 TO L2,

    IF MID$(S1$,I+(J-1)*H,1)<>MID$(32$,J,1) THEN GOTO ml
    NEXT J

    PRINT "Шаг: ";Н-1,"Позиции: ";I;

    FOR К = 1 TO L2 - 1: PRINT "-"; I + К * H; : NEXT K: PRINT
    К = 1 ml:
    END IF

    NEXT I
    END IF
    NEXT H

    IF К = 0 THEN PRINT "Строка S2 не входит в S1"
    END

    Программа 3_13.с

    /* Поиск вхождения S2 в S1 с разрядкой */

    #include <stdio.h>

    #include <conio.h>

    #include <string.h> main{)

    {

    char s1 [80],s2[80];
    int i,j,k=0,h,Ll,L2;
    clrscr();

    printf("Введите S1: ");
    scanf("%s",s1);
    Ll=strlen(s1);
    printf("Введите S2: ");
    scanf("%s",s2);
    L2=strlen(s2);
    for(h=l; h<=Ll; h++)
    {
    if(h==l || L2>1
    }

    {
    for(i=0; i<Ll-(L2-l)*h; i++)
    {
    if (sl[i]=s2[0])

    {
    for(j=l; j<L2; j++)


    if(si[i+j*h]!=s2[j]) goto ml;
    printf("\n Шаг: %2d Позиции: %d",h-l,i+1);
    for(k=l; k<L2; k++)
    printf("-%d",i+i+k*h);
    ml:;
    }

    } } }

    if(k==0) printf(" Строка S2 не входит в S1");
    getch () ; }

    Программа 3_13.pas

    program red_str;

    (Поиск вхождения S2 в S1 с разрядкой}

    uses crt;

    var

    s1,s2:string;

    i,j,k,h,L1,L2:integer;
    label 1;
    begin

    clrscr;

    write('Введите S1: ');
    readln (si);
    Ll:=length(sl);

    write('Введите S2: ');
    readln (s2);
    L2:=length(s2);

    k:=0;

    for h:=l to L1 do

    if (h=l)or(L2>1) then

    for i:=l to L1-(L2-1)*h do
    if s1[i]=s2[l] then begin

    for j:=2 to L2 do

    if s1[i+(j-l)*h]os2[j] then goto 1;
    write ('Шаг: ',h-l:2,' Позиции: ',i);
    for k:=l to L2-1 do
    write('-',i+k*h);
    writeln;
    k:=l;
    1:
    end;

    if k=0 then writeln('Строка 32 не входит в S1');
    readln;
    end.

    Заглянув в таблицу ASCII, нетрудно убедиться в том, что замене подлежат коды символов, попадающие в следующие интервалы:

    Содержание раздела