Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lec_cvv.docx
Скачиваний:
8
Добавлен:
01.06.2015
Размер:
110.86 Кб
Скачать

4.1.Указатели и аргументы функции

Переменные передаются функции по значению, поэтому нет прямого способа в вызванной функции изменить некоторую переменную в вызвавшей функции. Однако это легко сделать, если передавать функции не переменные, а их адреса. Программа Р20 иллюстрирует использование указателей в качестве аргументов функции izm(). Вначале в ней вводятся некоторые значения переменных а и b, затем они меняются местами. Заметим, что если в main() a и b – это переменные, то в izm() – это уже адреса, а значения переменных по этим адресам будут соответственно *а и *b. Пример программы Р20:

/*Программа Р20. Указатели и аргументы функций*/

#include<stdio.h>

main(){

int a, b;

puts(“введите значения а, b”);

scanf(“%d%d”, &a, &b);

printf(“a=%d, b=%d\n”, a, b);

izm(&a, &b); /*функция izm() меняет местами элементы а и b; ей передаются адреса этих элементов*/

printf(“измененные значения: a=%d; b=%d”, a, b);

}

#include “izm.c”

izm(a, b);

int *a, *b;

{

int c; /*a и b – указатели, *а и *b – значения, на которые они указывают*/

c=*a; *a=*b; *b=c;

}

Результат выполнения программы:

Введите значения a, b

87 999

a=87, b=999

измененные значения: a=999; b=87

4.2.Адресная арифметика

Если адреса указывают на элементы одного массива, то их можно сравнивать. Нельзя сравнивать либо использовать в арифметических операциях указатели на разные массивы. Любой адрес можно провеять на равенство или неравенство значению NULL, которое записывается вместо нуля (NULL можно присваивать указателю). Программа Р22 демонстрирует операции адресной арифметики.

/*Программа Р22. Адресная арифметика и операции с массивами*/

#include<stdio.h>

int a[]={10, 20, 30, 40 50, 60};

main(){

int i, *p;

for(i=0; i<6; i++) printf(“a[%d]=%d; %c”, i, a[i], (i==2)?’\n’:’ ‘);

printf(“\n\n”); /*вывод на экран массива а*/

for(p=&a[0]; p<=a[5]; p++) printf(“значение *p: %d; %c”, *p, (p==&a[2])?’\n’:’ ‘);

printf(“\n\n”); /*другой вариант вывода на экран массива а*/

for(p=&a[0], i=0; i<6; i++) printf(“p[$d]=%d; %c”, I, p[i], (i==2)?’\n’:’ ‘);

printf(“\n\n”); /*другой вариант вывода на экран массива а*/

for(p=a, i=0; p+i<=a+4; p++, i++) printf(“*(p+%d)=%d\t”, I, *(p+i));

printf(“\n\n”); /*вывод на экран 0-го, 2-го и 4-го элементов массива а*/

for(p=a+5; p>=a; p--) printf(“значение *p: %d; %c”, *p, (p==a+3)?’\n’:’ ‘);

printf(“\n\n”); /*Вывод на экран массива а в обратном порядке*/

for(p=a+5, i=0; i<=5; i++) printf(“p[-%d]= %d; %c”, i, p[-i], (i==2)?’\n’:’ ‘);

printf(“\n\n”); /*другой вариант вывода на экран массива а в обратном порядке*/

for(p=a+5; p>=a; p--) printf(“значение a[p-a]: %d; %c”, a[p-a], ((p==a+4)||(p==a+2))?’\n’:’ ‘);

printf(“\n\n”); /*Еще один вариант вывода на экран массива а в обратном порядке*/

}

Результаты работы программы Р22:

a[0]=10; a[1]=20; a[2]=30;

a[3]=40; a[4]=50; a[5]=60;

значение *р: 10; значение *р: 20; значение *р: 30;

значение *р: 40; значение *р: 50; значение *р: 60;

p[0]=10; p[1]=20; p[2]=30;

p[3]=40; p[4]=50; p[5]=60;

*(p+0)=10 *(p+1)=30 *(p+2)=50;

значение *р: 60; значение *р: 50; значение *р: 40;

значение *р: 30; значение *р: 20; значение *р: 10;

p[-0]=60; p[-1]=50; p[-2]=40;

p[-3]=30; p[-4]=20; p[-5]=10;

значение a[p-a]: 60; значение a[p-a]: 50;

значение a[p-a]: 40; значение a[p-a]: 30;

значение a[p-a]: 20; значение a[p-a]: 10;

4.3.Массивы указателей

В языке допускаются массивы указателей, которые объявляются следующим образом: char *m[5];. Здесь m[5] – массив, содержащий указатели на элементы типа char. Программа Р26 осуществляет упорядочивание строк заданного массива s в порядке убывания кодов первой буквы. Пусть в s 5 строк. Введем массив m указателей на строки массива s. Тогда для упорядочения s дочтаточно переставить надлежащим образом указатели в m.

/*Программа Р26. Массив указателей*/

#include<stdio.h>

main(){

int i, j, q, ind[5]={0, 0, 0, 0, 0}; /*ind – вспомогательный массив*/

char p, s[5][20], *m[5];

printf(“ввести 5 строк символов\n”);

for(i=0; i<5; i++) {scanf(“%s”, s[i]); m[i]=&s[i][0];} /*массив m будет содержать адреса строк массива s*/

for(i=0; i<5; i++) printf(“строка - %d; адрес строки - %p\n”, i, m[i]);

for(i=0; i<5; i++){p=’A’; q=0; /*переменной р присваивается символ А с заведомо малым кодом (А – русская буква)*/

for(j=0; j<5; j++) if(s[j][0]>=p && ind[j]==0){p=s[j][0]; q=j;}

ind[q]=1; /*после выполнения вложенного цикла for q равно номеру строки с наибольшим кодом первого символа; ind – вспомогательный массив, используемый для исключения повторного обращения к выбранной строке*/

m[i]=&s[q][0];}

puts(“\nупорядоченные строки”);

for(i=0; i<5; i++) printf(“строка %d\t\%s\n”, I, m[i]);

}

Результат работы программы:

Ввести 5 строк символов

Женя

Ваня

Петя

Миша

Гриша

Строка – 0; адрес строки – FF74

Строка – 1; адрес строки – FF88

Строка – 2; адрес строки – FF9C

Строка – 3; адрес строки – FFB0

Строка – 4; адрес строки – FFC4

Упорядоченные строки

Строка – 0; Петя

Строка – 1; Миша

Строка – 2; Женя

Строка – 3; Гриша

Строка – 4; Ваня

Следующая программа Р23 демонстрирует использование массива указателей на строки 2-мерного массива а.

/*Программа Р23. Указатели в многомерном массиве */

#include<stdio.h>

int a[3][3]={{10, 20, 30},

{40, 50, 60},

{70, 80, 90}};

int *pa[3]={a[0], a[1], a[2]}; /*объявление и инициализация указателя на строки массива а и присвоение начальных значений pa[0]=a[0]; pa[1]=a[1]; pa[2]=a[2]*/

int *p=a[0]; /*объявление указателя р на нулевой элемент первой строки массива а*/

main(){

int i, j;

puts(“исходная матрица”);

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

for(j=0; j<3; j++) printf(“%d”, a[i][j]);

printf(“\n”); }

printf(“\n”);

for(i=0; i<3; i++) printf(“a[%d][2-%d]=%d;\t*a[%d]=%d; \t*(*(a+%d)+%d)=%d\n”, i, i, a[i][2-i], i, *a[i], i, i, *(*(a+i)+i));

/*вывод на экран значений диагональных элементов от a[0][2] до a[2][0] массива а (a[i][2-i]); вывод на экран значений первых элементов каждой строки массива а (*a[i]); вывод на экран значений i-х элементов i-й строки массива а (*(*(a+i)+i))*/

for(i=0; i<3; i++) printf(“*pa[%d]=%d;\tp[%d]=%d\n”, i, *pa[i], i, p[i]); /*вывод на экран значений первых элементов каждой строки массива а (*pa[i]); вывод на экран значений элементов первой строки массива а (p[i])*/

}

Результат выполнения программы:

Исходная матрица

10 20 30

40 50 60

70 80 90

a[0][2-0]=30; *a[0]=10; *(*(a+0)+0)=10

a[1][2-1]=50; *a[1]=40; *(*(a+1)+1)=50

a[2][2-2]=70; *a[2]=70; *(*(a+2)+2)=90

*pa[0]=10; p[0]=10

*pa[1]=40; p[1]=20

*pa[2]=70; p[2]=30

Следующая программа Р24 сравнивает 2 строки str1 и str2.

/*Программа Р24. Ссылки на символьные массивы*/

#include<stdio.h>

main(){

int sravnenie();

char str1[30], str2[30];

printf(“ввести строки str1, str2\n”);

scanf(“%s%s”, str1, str2);

printf(“строка 1 - \t%s\n”, str1);

printf(“строка 2 - \t%s\n”, str2);

printf(“результат сравнения - \t%d”, sravnenie(str1, str2)); /*обращение к функции sravnenie() и вывод результата сравнения*/

}

sravnenie(s1, s2); /*функция возвращает отрицательное значение, если лексикографически s1<s2, положительное значение, если s1>s2, нулевое значение, если s1=s2*/

char *s1, s2;

{for(; *s1==*s2; s1++, s2++) if(*s1==’\0’) return(0);

return(*s1-*s2);

}

Результат работы программы:

Введите строки str1, str2

Петя

Иванов

Строка 1 – Петя

Строка 2 – Иванов

Результат сравнения – 7

Программа Р25 показывает использование многомерных массивов. В нее вводится матрица из нулей и единиц. Программа находит номер строки с наибольшим числом единиц.

/*Программа Р25. Многомерные массивы*/

#include<stdio.h>

main(){

int I, j, k, l, p, q=0, f=0, m[8][10];

puts(“введите число столбцов и строк матрицы m”);

scanf(“%d%d”, &i, &j);

puts(“ввести матрицу m по строкам”);

for(k=0; k<j; k++)

for(l=0; l<i; l++) scanf(“%d”, &m[k][l]);

puts(“введенная матрица m”);

for(k=0; k<j; k++)

for(l=0; l<i; l++) printf(“%d%c”, m[k][l], (l==i-1)?’\n’:’ ‘); /*используется тернарная операция “?:”*/

/*нахождение в матрице m строки с наибольшим числом единиц*/

for(k=0; k<j; k++){p=0;

for(l=0; l<i; l++) if(m[k][l]==1) p++

if(q<p){q=p; f=k;}} /*f – номер строки с наибольшим числом единиц, q – число единиц в f-й строке*/

printf(“номер строки с наибольшим числом единиц: %d;\nчисло единиц в строке:%d\n”, f+1, q);

}

Результат работы программы:

Введите число столбцов и строк матрицы m

4 3

Ввести матрицу m по строкам

1 0 0 1

1 0 1 1

0 1 0 1

Введенная матрица m

1 0 0 1

1 0 1 1

0 1 0 1

Номер строкис наибольшим числом единиц: 2;

Число единиц в строке: 3

Массив указателей можно инициализировать. Программа Р27 является соответствующим примером.

/*Программа 27. Инициализация массивов ссылок*/

#include<stdio.h>

main(){

int n;

char *name[]={“неверный номер месяца”, “январь”, “февраль”, “март”, “апрель”, “май”, “июнь”, “июль”, “август”, “сентябрь”, “октябрь”, “ноябрь”, “декабрь”};

puts(“введите номер месяца года”);

scanf(“%d”, &n);

printf(“название месяца – %s”, (n<1 || n>12)?name[0]: name[n]);

}

Результат работы программы:

Введите номер месяца года

10

Название месяца – октябрь

Указатели могут быть многоуровневыми, типа указатель на указатель, указатель на указатель на указатель и т.д.

4.6.Внешние аргументы

В программу на языке С можно передавать некоторые аргументы или параметры из командной строки. Когда, начиная вычисления, мы обращаемся к функции main(), ей передаются 2 параметра. Первый имеет имя argc и определяет число командных аргументов при обращении к программе. Второй, с именем argv, является указателем на массив символьных строк, содержащих эти аргументы (в одной строке – один аргумент). Предположим, что на диске В: есть некоторая программа P0.EXE. Обратимся к ней следующим образом:

B>P0 ВИТЯ ВОЛОДЯ БОРЯ

Тогда argv[0] – это указатель на Р0, argv[1] – на строку ВИТЯ и т.д. На первый фактический аргумент указывает argv[1], а на последний – argv[3]. Если argc=1, то после имени программы в командной строке параметров нет.

Следующие программы Р28 и Р29 показывают использование внешних аргументов. В первой из них командные параметры возвращаются на экран дисплея. Во второй, в зависимости от значения первого аргумента, последующие аргументы выводятся на экран в прямом или обратном порядке.

/*Программа 28. Использование внешних аргументов*/

#include<stdio.h>

main(argc, argv)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]