osn_progr_final
.pdfvoid main()
{
char text[128], //вихідний текст copy[128], //копія вихідного тексту *p, //початок чергового речення
*s, //початок чергового слова raz1[]="!?.", //розділювачі речень raz2[]=".?!,;: ";//розділювачі слів int l, //довжина текста
k, //кількість речень u;
do
{
clrscr();
puts("Введіть вхідний текст"); gets(text);
l=strlen(text);
strcpy(copy,text);
for(p=strtok(text,raz1),k=0;p!=NULL;p=sttok(NULL
,raz1))
k++;
for(s=strtok(copy,raz2),u=0;s!=NULL;s=strtok(NUL
L,raz2))
u++;
puts("Середня довжина речень:"); printf("%5d",l/k);
puts("\nСередня кількість слів у реченні"); printf("%5d",u/k);
puts("\nДля продовження натисніть ENTER, для ви-
ходуESC"); }while(getch()!=27);
}
Приклад 4 Нехай задано цілочисельний арифметичний вираз, записаний як
рядок в десятковій системі числення. Перевіримо правильність запису і обчислимо значення цього виразу. Вираз записаний без дужок, операції виконуються у порядку їх слідування.
#include <stdio.h> #include <string.h> #include <conio.h> #include <stdlib.h>
void main()
{
101
char a_v[80], a_v1[80], *p, c[40]; char *oper="+-*/%", *cifr="0123456789", *c_o="0123456789+-*/%";
int a[40], l_a_v, l, i, j, jk, ac; textmode(1); textcolor(YELLOW);
textbackground(BLUE);
m1:clrscr();
puts("Введіть арифметичний выраз: "); gets(a_v);
strcpy(a_v1, a_v); l_a_v=strlen(a_v); l=strspn(a_v,c_o);
if(l!=l_a_v) { puts("\n Помилка у виразі");
goto end; } p=strtok(a_v, oper); i=0;
do
{
a[i++]=atoi(p);
}
while(p=strtok(NULL, oper)); strcpy(a_v, a_v1); p=strtok(a_v, cifr);
j=0; do
{
c[j++]=*p;
}
while(p=strtok(NULL, cifr));
if(i!=j+1) { puts("\n Помилка у виразі"); goto end; }
jk=j;
ac=a[0];
i=j=0;
while(j<jk)
{
switch(c[j++])
{
case '+' : ac+=a[++i]; break; case '-' : ac-=a[++i]; break; case '*' : ac*=a[++i]; break; case '/' : ac/=a[++i]; break; case '%' : ac%=a[++i];
}
}
102
strcpy(a_v, a_v1); printf("\n%s = %d", a_v, ac); end:
printf("\n\n Для продовження - натисніть 7 : "); scanf("%d", &l); getchar();
if(l==7) goto m1;}
Приклад 5
Зашифруємо текст методом Гронсфельда. Ключом в цьому методі є скінченна послідовність цифр, яку записують підряд над символами текста, що шифрується. Тоді зашифрований текст утворюється таким чином: замість кожної літери у вихідному тексті друкується символ , що віддалений від цієї літери (у вибраній системі кодування, наприклад ascii) на величину відповідного елемента ключа(що стоїть над цією літерою).
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h> void main()
{
int n,*arr,i; char str[301],ch;
srand(time(NULL));
m1:
clrscr();
printf("Введіть текст(не більше 300 символов), що закінчується <Enter>:\n");
gets(str);
n=strlen(str);
arr = NULL;
arr = (int*) calloc(n,sizeof(int));//виділення пам”яті
clrscr();
puts("Введений текст:"); printf("\"%s\"",str);
putchar('\n'); puts("\nСформований ключ:"); for(i=0;i<n;i++)
{
103
/*заповнення масиву випадковими числами з діапазона[0..99] та друк*/
arr[i]=rand()%100;
printf("%4d",arr[i]);
}
for(i=0;i<n;i++) str[i]-=arr[i]; printf("\n\nЗашифрований текст:\n"); putchar('"');
for(i=0;i<n;i++) printf("%c",str[i]); putchar('"');
puts("\n\nРозшифровка:"); putchar('"');
for(i=0;i<n;i++) printf("%c",str[i]+arr[i]); putchar('"');
free(arr); //очистка пам”яті printf("\n\nПродовжуємо? (7-так):"); if(getch()=='7') goto m1;
}
Приклад 6 Відцентруємо рядки тексту.
Вхідні рядки не повинні містити табуляцій
#include <stdio.h> |
|
extern char *gets(); |
|
#define WIDTH 60 |
/* ширина листа */ |
main(){ |
|
char rd[81]; register char *s; |
|
char *head, |
/* початок тексту */ |
*tail; |
/* кінець тексту */ |
register int len, i; |
|
int shift; |
/* відступ */ |
/* Читати з стандартного вводу в rd по одному рядку, * доки файл не закінчиться. */
while( gets( rd ) != NULL ){ if( !*rd ){
/* Рядок порожній */ putchar( '\n' ); continue;
}
/* пропуск пропусків на початку рядка */ for( s = rd; *s == ' ' ; s++ );
if( ! *s ){
104
/* Рядок складається лише з пропусків */ putchar( '\n' ); continue;
}
head = s;
/* стати на кінець рядка */ while( *s ) s++;
/* шукати останній непропуск */ s--;
while( *s == ' ' && s != rd ) s--; tail = s;
/* Довжина тексту */ len = (tail-head) + 1;
/* різниця вказівників – ціле число */ shift = (WIDTH - len)/2;
if(shift < 0 ){
fprintf(stderr, "Рядок довший ніж %d\n", WIDTH
);
shift = 0;
}
/* Друк результату */
for( i=0; i < shift; i++ ) putchar( ' ' );
while( head <= tail ) putchar( *head++ ); putchar( '\n' );
}
}
Приклад 7 Задача про розмін монети
Знайдемо всі можливі коефіцієнти a0 .. an розкладу числа S у
вигляді S = a0 * c0 + a1 * c1 + ... + an * cn, де c0 .. cn задані та впорядковані, ai >= 0, ci >= 0.
#include <stdio.h>
/* Тут задаємо вартості розмінних монет */ int cost[] = {
1, 2, 3, 5, 10, 15, 20, 50, 100, 300, 500 /* копі-
йок */
};
#define N |
(sizeof cost / sizeof(int)) |
int count[ N ]; |
/* кількість монет даного типу |
(коефіцієнти ai) */ |
|
long nvar; |
/* число вариантов */ |
105
main( ac, av ) char *av[];
{
int coin;
if( ac == 1 ){
fprintf( stderr, "Вкажіть, яку монету размінювати: %s число\n",
av[0] ); exit(1);
}
coin = atoi( av[1] );
printf( " Таблиця розмінів монеты %d
коп.\n", coin );
printf( " Кожний стовпчик містить кількість монет вказаної вартості.\n" );
printf( "------------------------------------------------
-------------------\n" );
printf( "| 5р. | 3р. | 1р. | 50к.| 20к.| 15к.| 10к.| 5к.| 3к.| 2к.| 1к.|\n" );
printf( "------------------------------------------------
-------------------\n" );
change( N-1, coin );
printf( "------------------------------------------------
-------------------\n" );
printf( "Всього %ld варіантів\n", nvar );
}
/* рекурсивный размін */ change( maxcoin, sum )
int |
sum; |
/* |
монета, яку міняємо */ |
int |
maxcoin; |
/* |
індекс по масиву cost[] монети |
максимальної вартості, допустимої при даному разміні.
*/
{
register i;
if( sum == 0 ){ /* вся сума розміняна */ /* роздрукувати черговий варіант */ putchar( '|' );
for( i = N-1 ; i >= 0 ; i-- ) if( count[i] )
printf(" %3d |", count[ i ] );
106
else
printf(" |" ); putchar( '\n' );
nvar++;
return;
}
if( sum >= cost [ maxcoin ] ){
/* якщо можна видати монету вартістю
cost[maxcoin] , то відати її: |
*/ |
count[ maxcoin ] ++; |
/* порахували видану мо- |
нету */ |
|
/* розмінюємо залишок суми :
Перший аргумент - можливо можна дати ще одну таку монету ?
Другий аргумент - загальна сума зменшилась на одну монету cost[maxcoin].
*/
change( maxcoin, sum - cost[maxcoin] );
count[ maxcoin ] --; /* ... Тепер спробуємо інший варіант ... */
}
/* спробувати розмін більш мілкими монетами */ if( maxcoin )
change( maxcoin-1, sum );
}
Приклад 8. Програма, що друкує сама себе Напишемо програму, яка друкує “сама себе”. Такі програми є
дуже популярні серед студентів, що починають вивчати різні мови програмування. При цьому зразу ж необхідно уточнити, що текст програми повинен зберігатись в самій програмі. Викоритстання будь-яких зовнішніх джерел заборонене. Будемо використовувати масив вказівників на рядки:
#include <stdio.h> |
/* 1 |
*/ |
char *s[] = |
/* 2 |
*/ |
{ |
/* 3 |
*/ |
“#include <stdio.h>” |
|
|
"char *s[] =", |
|
|
"{", |
|
|
"рядок 4", |
|
|
..., |
|
|
107
"рядок N" |
|
|
|
}; |
/* 4 |
*/ |
|
рядок програми 5 |
/* 5 |
*/ |
|
... |
/* |
6 |
*/ |
рядок програми N |
/* |
7 |
*/ |
Роздрукувати програму можна, використовуючи цикл for.Загальна технологія наступна. Спочатку друкуємо перші три рядки програми як s[0],s[1],s[2]:
for(i=0; i<2; i++) {fputs(s[i], stdout); putc(NEW_LINE,stdout);}
Отримаємо:
#include <stdio.h> |
/* 1 |
*/ |
|
char *s[] = |
/* |
2 |
*/ |
{ |
/* |
3 |
*/ |
Потім–всі елементи , що ініціалізують масив вказівників s. При цьому необхідно друкувати відкриваючі лапки, s[i], закриваючі лапки, кому (крім останнього рядка ) і новий рядок. У рядкових константах не можемо використовувати лапки та символ нового рядка, тому доведеться використовувати їх коди відповідно 34 та 10 (для ASCII).
for(j = 0; j<21; j++) {putc(QUOTE,stdout); fputs(s[j], stdout); putc(QUOTE,stdout); putc(',',stdout); putc('\n',stdout);getch();}
Отримаємо всі рядки, що ініціалізують масив s:
“#include <stdio.h>” "char *line[] =", "{",
"рядок 4",
...,
"рядок N"
Потім друкуємо елементи масиву s, починаючи з четвертого (у схемі
"рядок 4"):
for(; i<21; i++) {fputs(s[i],stdout); putc(NEW_LINE,stdout);}
Отримаємо:
}; /* 4 */
108
рядок 4 |
/* 5 |
*/ |
|
... |
/* |
6 |
*/ |
рядок N |
/* |
7 |
*/ |
В наведеній схемі не використовуються пропуски, що не є принциповим.
Рядок N повинен містити закриваючу фігурну дужку. Набір рядків, очевидно, повинен містити фінкцію main() та відкриваючу фігурну дужку. Все інше в цьому переліку рядків може бути довільним. Ось текст програми:
#include <stdio.h> char *s[]=
{
"#include <stdio.h>", "char *s[] ={",
"};",
"#define QUOTE 34 ", "#define NEW_LINE 10 ", "int main()",
"{",
"int i,j;",
"for(i = 0; i < 2; i++)", "{fputs(s[i], stdout);", "putc(NEW_LINE,stdout);}", "for(j = 0; j<21; j++)", "{putc(QUOTE);", "fputs(s[j], stdout);", "putc(QUOTE,stdout);", "putc(',',stdout);", "putc(NEW_LINE,stdout);}", "for(; i<21; i++)", "puts(line[i], stdout);", "return 0;",
"}",
};
#define QUOTE 34 #define NEW_LINE 10 int main()
{
int i,j;
for(i=0; i<2; i++) {fputs(s[i], stdout); putc(NEW_LINE,stdout);} for(j = 0; j<21; j++)
109
{putc(QUOTE,stdout); fputs(s[j], stdout); putc(QUOTE,stdout); putc(',',stdout); putc('\n',stdout);getch();} for(; i<21; i++) {fputs(s[i],stdout); putc(NEW_LINE,stdout);} return 0;
}
5.10.5 Структури та об’єднання .
5.10.5.1 Структури
Синтаксично структури задаються наступним чином: struct [<тег>] {<список оголошення елементів >} <описувач> Наступна форма
struct <тег> <описувач> […<описувач>]-
використовується у випадку, коли тег-відповідної структури визначений вище, тобто знаходиться в межах області видимості.
Приклад:
struct point { int x,
int y;} A,B; struct { int x; float y;} Z,S;
Доступ до елемента структури здійснюється двома способами. Якщо визначений екземпляр структури, то доступ здійснюється конструкцією виду <описувач> . <ім’я поля>. У випадку, коли оголошений вказівник на екземпляр структури, доступ здійснюється з використанням операції ->: <вказівник> -> <ім’я поля>. Наприклад:
struct point *pa;
…
pa->x=4;
Структури можуть бути вкладеними, тобто полем структури також може бути структура:
struct line {int d; struct point a; struct point b;} L1,L2;
Доступ здійснюється таким чином:
L1.a.x=2;
L2.b.y=3;
Використовуємо стільки операцій доступу , скільки є рівнів вкладеної структури. Якщо оголосити вказівник на структуру line
110