Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

ПРИМЕЧАНИЕ. Функция strlen() считает только символы



Функция strlen() считает только символы. Она не включает в результат null - символ \0

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

В языках С и C++ можно создавать не только простые массивы и указатели. Их можно объединить в очень полезную конструкцию — массив указателей. Массив указателей — это такой массив, элементы которого являются указателями на другие объекты. Эти объекты, в свою очередь, могут быть указателями. Это означает, что можно иметь массив указателей, которые ссылаются на другие указатели.

// 10ARGCGV.CPP

// Программа на C++, использующая массив указателей для обработки

// аргументов командной строки argc and argv

#include "stdafx.h"

#include "E:\LECTURE\AlgorithmProgramming 02\Universal_HederFile.h"

#define IFIND_SMALLEST 0

#define IFIND_LARGEST 1

void StopWait(void);

int main(int argc, char *argv[])

{

char *psz;

int ihow_many;

int iwhich_extreme=0;

int irange_boundary=32767;

if(argc < 2)

{

// Вам нужно ввести -S,-s,-L,-l и хотя бы одно число

cout << "\nYou need to enter an -S, -s, -L, -l"

<< " and at least one integer value" << endl;

exit(1);

}

while(--argc > 0 && (*++argv)[0] == '-')

{

for(psz=argv[0]+1; *psz!= '\0'; psz++)

{

switch(*psz)

{

case 's':

case 'S':

iwhich_extreme=IFIND_SMALLEST;

irange_boundary=32767;

break;

case 'l':

case 'L':

iwhich_extreme=IFIND_LARGEST;

irange_boundary=0;

break;

default:

// Неизвестный аргумент

cout << "\n\nUnknow argument! " << *psz << endl;

exit(1);

}

}

}

if(argc == 0)

{

// Введите хотя бы одно число

cout << "Pliase enter at least one number\n";

exit(1);

}

ihow_many=argc;

while(argc--)

{

int present_value;

present_value=atoi(*(argv++));

if(iwhich_extreme == IFIND_LARGEST && present_value > irange_boundary)

irange_boundary=present_value;

if(iwhich_extreme == IFIND_SMALLEST && present_value < irange_boundary)

irange_boundary=present_value;

}

// Самое большее / меньшее из... введенных значений

cout << "The ";

cout << ((iwhich_extreme)? "largest": "smallest");

cout << " of the " << ihow_many << " value(s) input is " << irange_boundary

<< endl;

StopWait(); /* Wait a little */

return(0);

}

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

10argcgv

10argcgv 98

10argcgv 98 21

10argcgv -s 98

10argcgv -S 98 21

10argcgv -I 14

10argcgv -L 14 67

Взглянув на функцию main(), вы заметите формальные параметры argc и argv, с которыми познакомились ранее. Напомним, что argc — это целое число, равное количеству отдельных элементов или аргументов, появляющихся в командной строке. Переменная argv ссылается на массив указателей на символьные строки.

7.23.5. Дополнительная информация об указателях на указатели.

В следующей программе демонстрируются переменные-указатели, ссылающиеся на другие указатели. Этот пример рассматривается здесь потому, что в нем используется динамическое распределение памяти.

/*10DBLPTR.C

Программа на С, использующая указатели с двумя уровнями косвенности*/

------------

#include "stdafx.h"

#include "E:\LECTURE\AlgorithmProgramming 02\Universal_HederFile.h"

#define IMAXELEMENTS 3

void voutput(int **ppiresult_a, int **ppiresult_b, int **ppiresult_c);

void vassign(int *pivirtual_array[], int *pinewblock);

void StopWait(void);

main()

{

int **ppiresult_a, **ppiresult_b, **ppiresult_c;

int *pivirtual_array[IMAXELEMENTS];

int *pinewblock, *pioldblock;

ppiresult_a=&pivirtual_array[0];

ppiresult_b=&pivirtual_array[1];

ppiresult_c=&pivirtual_array[2];

pinewblock=(int *)malloc(IMAXELEMENTS*sizeof(int));

pioldblock=pinewblock;

vassign(pivirtual_array, pinewblock);

**ppiresult_a=7;

**ppiresult_b=10;

**ppiresult_c=15;

voutput(ppiresult_a, ppiresult_b, ppiresult_c);

pinewblock=(int *)malloc(IMAXELEMENTS*sizeof(int));

*pinewblock=**ppiresult_a;

*(pinewblock+1)=**ppiresult_b;

*(pinewblock+2)=**ppiresult_c;

free(pioldblock);

vassign(pivirtual_array, pinewblock);

voutput(ppiresult_a, ppiresult_b, ppiresult_c);

StopWait(); /* Wait a little */

return(0);

}

void vassign(int *pivirtual_array[], int *pinewblock)

{

pivirtual_array[0]=pinewblock;

pivirtual_array[1]=pinewblock+1;

pivirtual_array[2]=pinewblock+2;

}

void voutput(int **ppiresult_a, int **ppiresult_b, int **ppiresult_c)

{

printf("%d\n",**ppiresult_a);

printf("%d\n",**ppiresult_b);

printf("%d\n",**ppiresult_c);

}

Эта программа иллюстрирует концепцию переменной-указателя (ppiresult_a, ppiresult_b, ppiresult_c), ссылающихся на постоянный адрес (&pivirtual_array[0], &pivirtual_array[1], &pivirtual_array[2]), содержащий ссылочный адрес на ячейку, содержимое которой может динамически изменяться.

7.23.6. Массивы указателей на строки.

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

/*10AOFPTR.C

Программа на С, демонстрирующая описание и использование массивов

указателей*/

#include "stdafx.h"

#include "E:\LECTURE\AlgorithmProgramming 02\Universal_HederFile.h"

#define INUMBER_OF_ERRORS 3

char *pszarray[INUMBER_OF_ERRORS]=

{

"\nFile not available.\n", /* Файл отсутствует */

"\nNot an alpha chaacter.\n", /* He буква */

"\nValue not between 1 and 10.\n" /*He значение от 1 до 10 */

};

FILE *fopen_a_file(char *psz);

char cget_a_char(void);

int iget_an_integer(void);

FILE *pfa_file;

void StopWait(void);

void main()

{

char cvalue;

int ivalue;

fopen_a_file("input.dat");

cvalue=cget_a_char();

ivalue=iget_an_integer();

StopWait(); /* Wait a little */

}

FILE *fopen_a_file(char *psz)

{

const ifopen_a_file_error=0;

pfa_file=fopen(psz,"r");

if(!pfa_file)

printf("%s",pszarray[ifopen_a_file_error]);

return(pfa_file);

}

char cget_a_char(void)

{

char cvalue;

const icget_a_char_error=1;

printf("\nEnter a character: "); /* Введите символ */

scanf("%c", &cvalue);

if(!isalpha(cvalue))

printf("%s",pszarray[icget_a_char_error]);

return(cvalue);

}

int iget_an_integer(void)

{

int ivalue;

const iiget_an_integer=2;

printf("\nEnter an integer between 1 and 10: "); /*Введите целое */

scanf("%d", &ivalue);

if((ivalue < 1) || (ivalue > 10))

printf("%s", pszarray[iiget_an_integer]);

return(ivalue);

}

7.24. Ссылочный тип в C++ (reference type).

В языке C++ имеется способ вызова по ссылке, который использовать еще проще, чем указатели. Для начала рассмотрим использование ссылочных переменных в C++. Так же, как и в С, в языке C++ можно объявить обычные переменные или переменные-указатели. В первом случае для данных действительно выделяется память; во втором случае память резервируется для адреса объекта, который будет создан в другое время. В C++ имеется третий тип объявлений — ссылки. Так же, как указатель, ссылочная переменная указывает на положение другой переменной, однако, так же как и в случае обычной переменной, для ссылки не требуется специальной операции разыменования. Синтаксис ссылочной переменной понятен:

int iresult_a=5;

int& riresult_a=iresult_a; // правильно

int& riresult b; // неправильно: нет начального значения

В этом примере определяется ссылочная переменная riresult_a и присваивается существующей переменной iresult_a. После этого адресуемое значение имеет два имени — iresult_a и riresul_a. Поскольку обе переменные указывают на одну и ту же ячейку памяти, они представляют собой, по сути, одну переменную. Любое присваивание, сделанное по отношению к riresult_a, отражается на iresult_a; справедливо и обратное утверждение. Следовательно, при помощи ссылки можно создать нечто подобное псевдониму (alias) переменной.

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

7.24.1. Адрес в качестве возвращаемого значения функции.

Когда функция возвращает адрес либо в виде переменной-указателя, либо в виде ссылки, пользователь получает некоторый адрес в памяти. Он может считать значение, находящееся по этому адресу, и, если тип указателя не объявлен как const, всегда может что-нибудь туда записать. Если функция возвращает адрес, то пользователь получает возможность читать и — в случае указателей, имеющих тип, отличный от const — обновлять локальные данные. Это важно для проектирования приложений.

7.24.2. Использование встроенного отладчика.

Чтобы увидеть работу этой программы на C++ в реальных условиях, можно воспользоваться встроенным отладчиком. Проследим при помощи окна Trace изменения переменной pi.

Что происходит? При вызове функции ifirst_function() для переменной ilocal_to_first в стеке выделяется локальная область памяти, в которую записывается число 11. После этого функция ifirst_function() возвращает адрес этой локальной переменной (очень плохая новость!). Во второй строке функции mata() вызывается функция isecond_function(), которая в свою очередь выделяет локальную область памяти для переменной ilocal_to_second и записывает туда число 44. Почему же оператор printf печатает значение 44, хотя ему при вызове функции inrst_fiinction() был передан адрес переменной ilocaljojirsf?

Фактически происходит следующее. Когда при вызове функции ifirst_function() адрес временной локальной переменной ilocal_to_first был присвоен переменной pi, то этот адрес был сохранен, несмотря на завершение области действия ilocal_to_first. При вызове функции isecond_function(), ей также понадобилась локальная память. Поскольку переменной ilocal_to_first не стало, переменная ilocal_to_second получила ту же локальную.область, что и ее предшественница. Так как pi указывает на ту же занятую ячейку памяти, то становится понятным, почему при печати адресуемой ячейки появляется число 44. Следует быть чрезвычайно внимательным и стараться не возвращать адреса локальных переменных.

7.24.3. Использование ссылочного типа.

Подводя черту, можно выделить четыре основных причины использования ссылок C++:

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

· Ссылки передают ответственность за передачу аргумента тому программисту, который пишет функцию, а не тому, который ею пользуется.

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

· Ссылки используются при передаче функциям классов, при этом конструкторы и деструкторы не вызываются.

14. Использование функций.

14.1. Создание и использование простой функции.

14.2. Прототипы функций.

14.3. Вызов по значению и вызов по ссылке.

14.4. Указатели.

14.5. Операция косвенной адресации: *.

14.6. Описание указателей.





Дата публикования: 2015-01-13; Прочитано: 393 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.015 с)...