Работа с указателями: операции взятия адреса и разыменования адреса — КиберПедия 

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Работа с указателями: операции взятия адреса и разыменования адреса

2022-10-28 37
Работа с указателями: операции взятия адреса и разыменования адреса 0.00 из 5.00 0 оценок
Заказать работу

 

В Си указатели объявляются так:

ТИП * ИМЯ_УКАЗАТЕЛЯ;

То есть, если c и d - указатели на целое, то в Паскале их объявят так:

a:^Integer; {Указатель на целое число}

b:^Integer; {Указатель на целое число}

а в Си так:

int *a; //Указатель на целое число

int *b; //Указатель на целое число

 

Рассмотрим следующий фрагмент программы:

1> var

2> x1, x2, y1, y2: integer;

3> begin

4> x1:= 13;

5> x2:= 3;

6> divide(x1, x2, @y1, @y2);

В строке 6 к переменным y1 и y2 применяются операции взятия адреса @, которые возвращают указатели на эти переменные (адреса переменных).

В Си операция взятия адреса обозначается знаком &. Аналогичный фрагмент программы на Си будет выглядеть так:

int x1 = 13;

int x2 = 3;

int y1, y2;

divide(x1, x2, &y1, &y2);

 

Рассмотрим реализацию на Паскале функции divide с использованием указателей:

1> procedure divide(a, b: integer; c, d: PInteger);

2> begin

3> c^:= a div b;

4> d^:= a mod b;

5> end;

В строках 3 и 4 к параметрам c и d, которые имеют тип указатель на целое, применяются операции разыменования адреса ^. Операция разыменования адреса может быть применена только к указателю. В результате выполнения этой операции получается переменная, адрес которой хранит этот указатель.

В результате выполнения строк 3 и 4 в переменные y1 и y2 будут занесены значения частного и остатка от деления соответственно.

В Си операция разыменования адреса обозначается знаком *. Процедура divide на Си будет выглядеть так:

void divide(int a, int b, int * c, int * d)

{

*c = a / b;

*d = a % b;

}

 

Полный текст примера на Си будет выглядеть так:

#include <stdio.h>

 

/*Процедура делит a на b.

 В c заносится частное, в d – остаток от деления.*/

void divide(int a, int b, int * c, int * d)

{

*c = a / b;

*d = a % b;

}

 

int main()

{

int x1 = 13;

int x2 = 3;

 

int y1, y2;

 

divide(x1, x2, &y1, &y2);

printf("\n\n%d / %d = %d\n", x1, x2, y1);

printf("%d %% %d = %d\n", x1, x2, y2);

return 0;

}

ВВОД В ЯЗЫКЕ СИ

 

Функция GETCH – ввод символа

 

Функция getch возвращает код нажатой клавиши. Эта функция не входит в стандарт Си, но во многих реализациях Си она есть. Есть она и в Borland C++ 3.

Функция getch имеет прототип (общий вид):

int getch();

Действие функции полностью эквивалентно действию функции readkey в Turbo Pascal’e.

 

 

Функция SCANF - форматированный ввод

Функция SCANF аналогична по выполняемым действиям процедуре READ в Паскале.

В использовании функция SCANF аналогична функции PRINTF. Так же, как и в PRINTF, первым параметром SCANF является форматная строка, в которой при помощи спецификаторов преобразования указываются типы вводимых параметров (%d – десятичное int, %Lf – long double). Принципиальное отличие SCANF от PRINTF в использовании – то, что в PRINTF нужно передавать выводимые значения, а в SCANF - указатели на вводимые переменные.

Пример. Нужно для двух введенных целых чисел вывести на экран их среднее арифметическое.

#include <stdio.h>

 

int main()

{

int a, b;

float sr;

printf(“\n\nВведите a =”);

scanf(“%d”, &a); // %d - вводится параметр целого типа.

      // В функции scanf параметр a должен измениться

      // (его значение вводится с клавиатуры).

      // Для того, чтобы обеспечить изменение a,

      // в scanf передается указатель на a.

printf(“Введите b =”);

scanf(“%d”, &b);

sr = (a + b) / 2.0;

printf(“Среднее арифметическое = %f\n”, sr);

return 0;

}

 

РАЗВИЛКИ

 

Пример задачи: размер файла в байтах

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

Пример:

1. Файл имеет размер 10240 байт (б). Это то же самое, что 10 килобайт (Кб) или 0.0098 мегабайта (Мб). Ясно, что в данном случае удобнее всего размер выдавать в килобайтах.

2. Файл имеет размер 1500000 байт (б). Это то же самое, что 1464,84 килобайта (Кб) или 1.043 мегабайта (Мб). Ясно, что в данном случае удобнее всего размер выдавать в мегабайтах.

 

Пересчет из байт в другие единицы измерения производится по формулам:

1 Кб = 1024 б

1 Мб = 1024 Кб = 1024*1024 б = 1 048 576 б

1 Гб = 1024 Мб = 1024*1024*1024 б = 1 073 741 824 б

 

Уточним задачу.

Дано число X. 0 <= X <= 2 000 000 000.

Нужно вывести X, если X < 1024.

Если 1024 <= X < 1024*1024, нужно вывести X / 1024.

Если 1024*1024 <= X < 1024*1024*1024, нужно вывести                              X / (1024*1024).

Если X >= 1024*1024*1024, нужно вывести X / (1024*1024*1024).

 

Усеченные развилки

 

Решение задачи на Паскале:

var

x: longint;

Begin

Write(‘Введите размер файла:’);

read(x);

 

if x < 0 then

begin

writeln(‘Вы ввели неправильный размер файла!’);

exit;

end;

 

if x < 1024 then

writeln(‘size = ‘, x, ‘ б’);

 

if (x >= 1024) and (x < 1024*1024) then

writeln(‘size = ‘, (x / (1024)):0:2, ‘ Кб’);

 

if (x >= 1024*1024) and (x < 1024*1024*1024) then

writeln(‘size = ‘, (x / (1024*1024)):0:2, ‘ Мб’);

 

if x >= 1024*1024*1024 then

writeln(‘size = ‘, (x / (1024*1024*1024)):0:2, ‘ Гб’);

End. 

 

В Паскале существует две операции деления. Обычная операция деления обозначается знаком / - в результате выполнения такой операции получается результат - вещественное число. Операция целочисленного деления обозначается DIV. Оба операнда операции DIV должны иметь целый тип.

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

В примере обратите внимание на формат вывода:0:2. Такая запись означает нулевую минимальную ширину поля и две цифры после запятой. Нулевая минимальная ширина поля означает, что число при выводе будет занимать столько позиций, сколько нужно.

 

Реализация на Си:

#include <stdio.h>

 

int  main()

{

long x;

 

printf(“Введите размер файла:”);

scanf(“%ld”, &x);

 

if (x < 0)

{

pritnf(“Вы ввели неправильный размер файла!”);

return 1; //Возвращаем из main не 0 – сигнал об ошибке

         //во время исполнения программы

}

 

if (x < 1024)

printf(“size = %d б“, (int) x); // x имеет тип long,

         // а в форматной строке указан %d – int,

         // поэтому необходимо приведение типа (int) x

 

if (x >= 1024 && x < 1024.0*1024)

printf(“size = %0.2f Кб”, x / 1024.0);

 

if (x >= 1024.0*1024 && x < 1024.0*1024*1024)

printf(“size = %0.2f Мб“, x / (1024.0*1024));

 

if (x >= 1024.0*1024*1024)

printf(“size = %0.2f Гб“, x / (1024.0*1024*1024));

 

return 0;

}

 

В отличие от Паскаля, в Си операция деления одна, и обозначается она /. Но (!) если хотя бы один операнд имеет вещественный тип, то результат вычисляется по правилам деления вещественных чисел (то есть как при использовании операции / в Паскале). Если оба операнда имеют целый тип, то результат получается по правилам деления целых чисел (как при использовании DIV в Паскале). Это означает, что если разделить целое число 2000 на 1024, то получится 2000 / 1024 = 1, а не 1.95. В нашем примере нам нужно, чтобы деление не было целочисленным. Поэтому при делении 2000 / 1024 выполняем 2000 / 1024.0. Поскольку один из операндов вещественный, то и результат будет вещественный 2000 / 1024.0 = 1.95.

 

Сравним усеченную развилку в Паскале и в Си:

Паскаль Си
if x < 1024 then writeln(x); if (x < 1024) printf(“%d “, (int)x);

 

Отличие усеченной развилки в Паскале и Си видно из примера и из формального описания синтаксиса:

 

Паскаль:

If УСЛОВИЕ Then ОПЕРАТОР

 

Си:

if ( УСЛОВИЕ ) ОПЕРАТОР

 

Полные развилки

 

Решение задачи на Паскале:

var

x: longint;

Begin

Write(‘Введите размер файла:’);

read(x);

 

if x < 0 then

writeln(‘Вы ввели неправильный размер файла!’)

else

begin

if x < 1024 then

writeln(‘size = ‘, x, ‘ б’)

 

else if x < 1024*1024 then

writeln(‘size = ‘, (x / (1024)):0:2, ‘ Кб’)

 

else if x < 1024*1024*1024 then

writeln(‘size = ‘, (x / (1024*1024)):0:2, ‘ Мб’)

 

else

writeln(‘size = ‘, (x / (1024*1024*1024)):0:2,

         ‘ Гб’);

end;

End. 

 

Реализация на Си:

#include <stdio.h>

 

int main()

{

long x;

 

printf(“Введите размер файла:”);

scanf(“%ld”, &x);

 

if (x < 0)

pritnf(“Вы ввели неправильный размер файла!”);

else

{

if (x < 1024)

printf(“size = %d б“, (int)x);

 

else if (x < 1024.0*1024)

printf(“size = %0.2f Кб”, x / 1024.0);

 

else if (x < 1024.0*1024*1024)

printf(“size = %0.2f Мб“, x / (1024.0*1024));

 

else

printf(“size = %0.2f Гб“, x / (1024.0*1024*1024));

}

 

return 0;

}

 

Сравним полную развилку в Паскале и в Си:

Паскаль Си
if x < 0 then writeln(‘Ошибка ввода!’) else begin … end;   if (x < 0) pritnf(“Ошибка ввода!”); else { … }  

 

Отличие усеченной развилки в Паскале и Си видно из примера и из формального описания синтаксиса:

 

Паскаль:

If УСЛОВИЕ Then ОПЕРАТОР Else ОПЕРАТОР

 

Си:

if ( УСЛОВИЕ ) ОПЕРАТОР else ОПЕРАТОР

 

задание для Лабораторной работуы по теме «Вычисление математических функций»

 

Цель работы

 

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

Общее задание

 

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

В программе обязательно использовать функции. Использование глобальных переменных запрещено.

 

Простые задания

 

В варианте задается «кусочная функция» y = f(x). В программе необходимо обеспечить ввод с клавиатуры границ диапазона [a..b] и шага изменений h для аргумента x. Нужно вывести на экран таблицу значений функции y = f(x) для , шаг изменения x равен h.

 

Пример выполнения лабораторной работы по простым заданиям

 

Функция y=f(x) имеет вид:

Если x < 3, то

Если , то

Если x > 6, то

 

Реализация на Си:

#include <stdio.h>

#include <math.h>

 

/*

Вычисление функции, заданной в варианте

*/

double f(double x)

{

if (x < 3) return sin(3 * x) + 6;

if (x <= 6) return (x * x) / (1 + x * x);

return 1 + sqrt(x + 10);

}

 

int main()

{

double a, b, h;

double x, y;

 

// Ввод значений границ диапазона и шага изменения X

while (1) // бесконечный цикл ввода

{

printf("Введите значения A, B, H:");

scanf("%lf%lf%lf", &a, &b, &h);

if (a > b)

{

printf("Вы ввели неверные значения: a > b!!\n");

continue; // продолжаем выполнение цикла ввода

}

if (h <= 0)

{

printf("Вы ввели неверные значения: h <= 0!!\n");

continue; // продолжаем выполнение цикла ввода

}

// Ввод корректен - выходим из цикла

break;

}

 

// Формируем шапку таблицы

printf("+------------+---------------+\n");

printf("+ X +  Y  +\n");

printf("+------------+---------------+\n");

// формируем таблицу

for (x = a; x <= b; x += h)

{

y = f(x);

printf("| %10lf | %12lf |\n", x, y);

}

// Завершаем формирование таблицы

printf("+------------+---------------+\n");

return 0;

}


 

Варианты для простых заданий и для заданий средней сложности

 


Вариант A1:

Функция y=f(x) имеет вид:

Если x < 2, то

Если , то

Если x > 5, то

 

Вариант A2:

Функция y=f(x) имеет вид:

Если x <= 0, то

Если 0 < x < 3, то

Если x >= 3, то

 

Вариант A3:

Функция y=f(x) имеет вид:

Если x <= -3, то

Если -3 < x <= 0, то

Если x > 0, то

 

Вариант A4:

Функция y=f(x) имеет вид:

Если x < 0, то

Если 0 <= x <= 2, то

Если x > 2, то

 

Вариант A5:

Функция y=f(x) имеет вид:

Если x < 3, то

Если 3 <= x <= 6, то

Если x > 6, то

 

 


Вариант A6:

Функция y=f(x) имеет вид:

Если x < 3, то

Если 3 <= x <= 6, то

Если x > 6, то

 

Вариант A7:

Функция y=f(x) имеет вид:

Если x < 2, то

Если 2 <= x <= 5, то

Если x > 5, то

 

Вариант A8:

Функция y=f(x) имеет вид:

Если x <= 0, то

Если 0 < x < 3, то

Если x >= 3, то

 

Вариант A9:

Функция y=f(x) имеет вид:

Если x <= -3, то

Если -3 < x <= 0, то

Если x > 0, то

 

Вариант A10:

Функция y=f(x) имеет вид:

Если x <= 0, то

Если 0 < x < 6, то

Если x >= 6, то

 


Вариант A11:

Функция y=f(x) имеет вид:

Если x < 0, то

Если 0 <= x <= 2, то

Если x > 2, то

 

Вариант A12:

Функция y=f(x) имеет вид:

Если x < 3, то

Если 3 <= x <= 6, то

Если x > 6, то

 

Вариант A13:

Функция y=f(x) имеет вид:

Если x < 3, то

Если 3 <= x <= 6, то

Если x > 6, то

 


Вариант A14:

Функция y=f(x) имеет вид:

Если x < 2, то

Если 2 <= x <= 5, то

Если x > 5, то

 

Вариант A15:

Функция y=f(x) имеет вид:

Если x <= 0, то

Если 0 < x < 3, то

Если x >= 3, то

 


Задания среднего уровня сложности

 

В варианте задается «кусочная функция» y = f(x). В программе необходимо обеспечить ввод с клавиатуры границ диапазона [a..b] и шага изменений h для аргумента x. Нужно вывести на экран таблицу значений функции y = f(x), вычисленную с использованием функций стандартной библиотеки Си, и значения y1 = f1(x), вычисленные с помощью пользовательской реализации этих же функций. В пользовательской реализации необходимо использовать итерационный алгоритм вычисления.

Варианты заданий средней сложности те же, что и для простых заданий (смотри выше).

 


Поделиться с друзьями:

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

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.138 с.