Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Бичков - Основи сучасного програмування.doc
Скачиваний:
69
Добавлен:
07.03.2016
Размер:
2.67 Mб
Скачать

Int f(char * s)

{int i;

for (i=0;*s='\0';i++;s++);

return i;}

/*функція обраховує кількість елементів рядка*/

char s[10];

Можемо викликати функцію

f(&s[i]); або f(s+i).

Допускається існування масиву покажчикiв:

int * a[20];

Покажчики на масив і багатовимірні масиви. Визначення int(*a)[20]задає покажчик на масив. У цьому випадку ім'я а також задає адресу першого елемента масиву, але додавання до такого покажчика, наприклад, одиниці приведе до збільшення адреси на всю довжину масиву – у даному випадку – 20 елементів типу int.

Для розуміння механізму інтерпретації багатовимірних масивів можемо навести такі міркування. Одновимірний масив int a[10] може бути розглянутий через покажчик (а містить адресу першого елемента):

int * pa;

pa=a;

pa++==a[1];

Двовимірний масив int a[5][10] інтерпретується як покажчик на масив із 10 елементів:

int (*pa)[10];

pa=a;

Тоді

*(pa++)==a[1][0];

*(*(pa)+1)==a[1][1];

Аналогічно, якщо розглянути, наприклад, тривимірний масив

int b[10][20][30];

то він інтерпретується як покажчик на двовимірний масив розмірністю 20  30:

int (*pb)[20][30];

pb=b;

Тоді ***(pb++)==b[1][0][0], *(**(pb++)+1)==b[1][0][1].

Ім'я b міститиме адресу тривимірного масиву (першого його елемента). Тоді b[0],b[1],…,b[9] – адреси відповідних двовимірних масивів, b[i][j] – одновимірних. Наприклад:

int d[1][3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

int d1[1][3][4]={111,2,3,4,5,6,7,8,9,10,11,12};

main()

{

printf("%d',***(d+1));

}

Буде надруковане значення 111 – першого елемента масиву d1.

У загальному випадку доступ до елемента n-вимірного масиву a[N][N]…[N] здійснюється за таким правилом:

a[m1][m2]…[mn]=*(a[0][0]…[0]+m1*Nn-1 +m2*Nn-2+…+mn)

n-1 нульових індексів

При роботі з динамічними масивами необхідно звернути особливу увагу на виділення пам'яті за допомогою функцій malloc чи calloc.

Наведемо деякі приклади розв'язання задач.

1. Розглянемо алгоритм сортування методом "бульбашки". Розсортируємо літери в рядку у порядку зростання їх кодів. Причому розглянемо два варіанти програми: із застосуванням операції індексації до елементів рядка та без нього, лише через покажчики. Ідея сортування методом "бульбашки" досить проста. Розглядаючи масив зліва направо, перевіряємо, чи менший перший елемент за наступний. Якщо ця умова виконується, то розглядається другий елемент масиву і т. д. Якщо ж виявиться, що поточний елемент більший за наступний, то ці елементи міняються місцями, і перегляд масиву починається спочатку.

Перший варіант програми:

#define YES 1

#define NO 0

bsort(char *s)

{

register int i; /*індекс літери, що порівнюється*/

register int need=YES; /*чи потрібно продовжувати сортування*/

while(need){

need=NO; /*не потрібно*/

for(i=0; s[i+1]; i++)

/*умова циклу: ми порівнюємо i-ту та i+1-шу літери,

*тому перевіряємо наявність i+1-ї літери*/

if(s[i]>s[i+1]){/*у неправильному порядку*/

swap(&s[i], &s[i+1]); /*переставити*/

need=YES; /*щось змінилось: потрібно

*повторити перегляд масиву літер*/

}

}

}

Другий варіант програми:

bpsort(char *s)

{

register char *p; register need=YES;

while(need){

need=NO;

for(p=s; p[1] !='\0'; p++)

if(*p>*(p+1)){

swap(p, p+1); need=YES;

}

}

}

/*обмін двох літер, що знаходяться за адресами s1 і s2*/

swap(s1, s2) register char *s1, *s2;

{

char tmp; /*temporary*/

tmp=*s1; *s1=*s2; *s2=tmp;

}

char sample1[]="Homo homini lupus est – ergo bibamus!";

char sample2[sizeof(sample1)]; /*масив такого самого обсягу*/

main(){

strcpy(sample2, sample1); /*скопіювати*/

bsort (sample1); printf("%s\n", sample1);

bpsort(sample2); printf("%s\n", sample2);

}

Специфікацію пам'яті register у даному прикладі використано з метою збільшення швидкодії програми, що не принципово. Слід звернути увагу на використання функції swap ().

2. Переформатуємо матрицю так, щоб її стовпчики розміщувались за спаданням їх поелементних сум.

Матрицю запишемо в динамічному масиві. При цьому слід звернути увагу на специфіку виділення пам'яті за допомогою функції malloc:

sum=(int *)malloc(m*sizeof(int));arr=(int *)malloc(n*m*sizeof(int));

При такому виділенні пам'ять має бути коректно звільнена за допомогою функції free():

free(sum);free(arr);

Текст програми:

#include <stdio.h> #include <conio.h> #include <stdlib.h> void main() {int i,j,k,n,m,t,*sum,*arr; clrscr(); puts("Введи n");

scanf("%d%d",&n,&m); sum=(int *)malloc(m*sizeof(int)); arr=(int *)malloc(n*m*sizeof(int)); for(i=0;i<n;i++) for(printf("\n"),j=0;j<m;j++) {*(arr+i*m+j)=rand()%21;printf("%4d",*(arr+i*m+j));} printf("\n\n"); for(j=0;j<m;j++) {for(i=0,sum[j]=0;i<n;i++) sum[j]+=*(arr+i*m+j); printf("%4d",sum[j]); } for(i=1;i<m;i++) for(j=0;j<m-i;j++) {if(sum[j]>=sum[j+1]) continue; t=sum[j];sum[j]=sum[j+1];sum[j+1]=t; for(k=0;k<n;k++) {t=*(arr+k*m+j);*(arr+k*m+j)=*(arr+k*m+j+1);*(arr+k*m+j+1)=t;} } printf("\n\n"); for(i=0;i<n;i++) for(printf("\n"),j=0;j<m;j++) printf("%4d",*(arr+i*m+j)); printf("\n\n"); for(j=0;j<m;j++) printf("%4d",sum[j]);

free(sum);free(arr); getch(); }

3. Нехай у масиві записано деякий текст. Обчислимо середню кількість слів у реченні та середню довжину речення:

#include <stdio.h> #include <conio.h> #include <string.h> void main() { char text[128], //вихідний текст copy[128], //копія вихідного тексту *p, //початок чергового речення *s, //початок чергового слова raz1[]="!?.", //роздільники речень raz2[]=".?!,;: ";//роздільники слів intl, //довжина тексту 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(NULL,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() { 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]; } } 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++) { /*заповнення масиву випадковими числами з діапазону [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;