Представление данных в языке С.
Лабораторная работа № 6
Сравнительный анализ языков программирования С и С++ в среде MS Visual Studio .
Ижевск 2015
СоставителИ:
в.п.Тарануха, канд.техн.наук, доцент
шАМСИАХМЕТОВ о.я.
Рецензенты - канд. физ.-мат. наук, доцент Клишин С.В.,
доктор техн. наук, профессор ушаков П.А.
МЕТОДИЧЕСКОЕ РУКОВОДСТВО к лабораторной работе №6
“Сравнительный анализ языков программирования С и С++ в среде MS Visual Studio 2008 ” пО курсу ” ИНФОРМАТИКА” профиля
”Проектирование и технология радиоэлектронных средств”
/ Тарануха В.П.,ШАМСИАХМЕТОВ О.Я.-: Ижевск: Издательство ИжГТУ, 2015.- 61 c.
Настоящие методические указания определяют последовательность выполнения лабораторной работы по дисциплине «ИНФОРМАТИКА» и включают в себя рекомендации ПО СОЗДАНИЮ ПРИКЛАДНЫх ПРОГРАММ на языке программирования с и с++ в среде MS VISUAL STUDIO 2008.
© Тарануха В.П.,шамсиахметов О.Я.
© ИжГТУ, 2015
Лабораторная работа №6
Сравнительный анализ языков программирования С и С++ в среде MS Visual Studio .
Краткая теория.
Представление данных в языке С.
Для того чтобы иметь возможность работать с тем или иным типом данных необходимо задать переменную соответствующего типа. Это осуществляется с использованием следующего синтаксиса:
<тип переменной> <имя_переменной>;
Например int arg; объявляет целочисленную переменную с именем arg.
В таблице 1 представлены основные типы данных:
Таблица 1. Основные базовые типы данных
|
При выборе имени переменной желательно использовать осмысленные имена. При определении имени можно использовать как верхний, так и нижний регистры букв латинского алфавита. Причем первым символом обязательно должна быть буква или символ подчеркивания ‘_’.
Язык С при объявлении переменных различает большой и малый регистры.
В отличие от многих языков программирования высокого уровня, в языке С переменные могут объявляться в любом месте текста программы.
В языке С просто реализуются элементарные математические операции: сложения, вычитания, умножения и деления:
int a, b;
a=4;// с начальными значениями
b=8;
int c;
c= a+b; //сложение двух переменных
с=a-b; //вычитание
c=a*b; //умножение
c=a/b; //деление
Представленные операции можно выполнять не только с переменными, но и с конкретными числами, например
c = 10 + 5;
c = 8*4;
float d;
d = 7/2;
Результатом первых двух арифметических операций будут числа 15 и 32 соответственно, но при выполнении операции деления в переменную d будет записано число 3, а не 3,5. Это связано с тем, что число 7 в языке С будет интерпретироваться как целочисленная величина, которая не может содержать дробной части. Поэтому полученная дробная часть 0,5 будет отброшена. Для реализации корректного деления одного числа на другое следует использовать такую запись: d = 7.0/2;
или
d = (float )7/2;
В первом случае вещественное число делится на два и результат (вещественный) присваивается вещественной переменной d. Во втором варианте выполняется приведение типов: целое число 7 приводится к
вещественному типу float, а затем делится на 2.
Второй вариант удобен, когда выполняется деление одной целочисленной переменной на другую:
int a, b;
a = 7;
b = 2;
d = a/b;
В результате значение d будет равно 3, но если записать
d = (float )a/b;
то получим значение 3,5.
Если переменная d является целочисленной, то результат деления всегда будет записан с отброшенной дробной частью.
Приоритет операций умножения и деления выше приоритета операций сложения и вычитания.
Для того чтобы изменить порядок вычисления (поменять приоритеты), используются круглые скобки :
double arg = (25.0 + 60.0)*n/SCALE;
Здесь сначала выполняется операция сложения и только затем операции умножения и деления.
Для простоты программирования в языке С реализованы компактные операторы инкремента и декремента, т.е. увеличения и уменьшения значения переменной на 1 соответственно. Данные операторы могут быть записаны в виде
i++; // операция инкремента
++i; // операция инкремента
Директивы препроцессора.
Почти все программы на языке С используют специальные команды для компилятора, которые называются директивами. В общем случае директива - это указание компилятору языка С выполнить то или иное действие в момент компиляции программы.
Существует строго определенный набор возможных директив, который включает в себя следующие определения:
#define, #elif, #else, #endif, #if, #ifdef, #ifndef, #include, #undef.
Директива #define используется для задания констант, ключевых слов, операторов и выражений, используемых в программе. Общий синтаксис данной директивы имеет следующий вид:
#define <идентификатор> <текст>
или
#define <идентификатор> (<список параметров>) <текст>
Пример использования директивы #define.
#include <stdio.h>
#define TWO 2
#define FOUR TWO*TWO
#define PX printf("X равно %d.\n", x)
#define FMT «X равно %d.\n»
#define SQUARE(X) X*X
Int main()
{ int x = TWO;
PX;
x = FOUR;
printf(FMT, x);
x = SQUARE(3);
PX;
return 0; }
После выполнения этой программы на экране монитора появится три строки:
X равно 2.
X равно 4.
X равно 9.
Директива #undef отменяет определение, введенное ранее директивой #define. Предположим, что на каком-либо участке программы нужно отменить определение константы FOUR. Это достигается следующей командой:
#undef FOUR
Интересной особенностью данной директивы является возможность переопределения значения ранее введенной константы.
Действительно, повторное использование директивы #define для ранее введенной константы FOUR невозможно, т.к. это приведет к сообщению об ошибке в момент компиляции программы. Но если отменить определение константы FOUR с помощью директивы #undef, то появляется возможность повторного использования директивы #define для константы FOUR.
Для того чтобы иметь возможность выполнять условную компиляцию, используется группа директив #if, #ifdef, #ifndef, #elif, #else и #endif.
Пример:программа выполняет подключение библиотек в зависимости от установленных констант.
#if defined(GRAPH)
#include <graphics.h> //подключение графической библиотеки
#elif defined(TEXT)
#include <conio.h> //подключение текстовой библиотеки
#else
#include <io.h> //подключение библиотеки ввода-вывода
#endif
Программа работает следующим образом: если ранее была задана константа с именем GRAPH через директиву #define, то будет подключена графическая библиотека с помощью директивы #include. Если идентификатор GRAPH не определен, но имеется определение TEXT, то будет использоваться библиотека текстового ввода/вывода. Иначе, при отсутствии каких-либо определений, подключается библиотека ввода/вывода. Вместо словосочетания #if defined часто используют сокращенные обозначения #ifdef и #ifndef и выше приведенную программу можно переписать в виде:
#ifdef GRAPH
#include <graphics.h> //подключение графической библиотеки
#ifdef TEXT
#include <conio.h> //подключение текстовой библиотеки
#else
#include <io.h> //подключение библиотеки ввода-вывода
#endif
Отличие директивы #if от директив #ifdef и #ifndef заключается в возможности проверки более разнообразных условий, а не только существует или нет какие-либо константы.
Например, с помощью директивы #if можно проводить такую проверку:
#if SIZE == 1
#include <math.h> // подключение математической библиотеки
#elif SIZE > 1
#include <array.h> // подключение библиотеки обработки
// массивов
#endif
В приведенном примере подключается либо математическая библиотека, либо библиотека обработки массивов, в зависимости от значения константы SIZE.
Используемая в приведенных примерах директива #include позволяет добавлять в программу ранее написанные программы и сохраненные в виде файлов. Например, строка
#include <stdio.h>
указывает препроцессору добавить содержимое файла stdio.h вместо приведенной строки. Это дает большую гибкость, легкость программирования и наглядность создаваемого текста программы.
Int main()
{ int age;
float weight;
printf("Введите информацию о Вашем возрасте: ");
scanf("%d", &age);
printf("Введите информацию о Вашем весе: ");
scanf("%f", &weigth);
printf("Ваш возраст = %d, Ваш вес = %f", age, weigth);
return 0; }
Основным отличием применения функции scanf() от функции printf() является знак & перед именем переменной, в которую записываются результаты ввода.
Функция scanf() может работать сразу с несколькими переменными. Предположим, что необходимо ввести два целых числа с клавиатуры. Формально для этого можно дважды вызвать функцию scanf(), однако лучше воспользоваться такой конструкцией:
scanf(" %d, %d ", &n, &m);
Функция scanf() интерпретирует это так, как будто ожидает, что пользователь введет число, затем - запятую, а затем - второе число.
Функция scanf() возвращает число успешно считанных элементов. Если операции считывания не происходило, что бывает в том случае, когда вместо ожидаемого цифрового значения вводится какая-либо буква, то возвращаемое значение равно 0.
If (выражение)
<оператор>
Если значение параметра «выражение» равно «истинно», выполняется оператор, иначе он пропускается программой. Следует отметить, что «выражение» является условным выражением, в котором выполняется проверка некоторого условия. В таблице 2 представлены варианты простых логических выражений оператора if:
Таблица 2. Простые логические выражения.
if(a < b) | Истинно, если переменная a меньше переменной b и ложно в противном случае. |
if(a > b) | Истинно, если переменная a больше переменной b и ложно в противном случае. |
if(a == b) | Истинно, если переменная a равна переменной b и ложно в противном случае. |
if(a <= b) | Истинно, если переменная a меньше либо равна переменной b и ложно в противном случае. |
if(a >= b) | Истинно, если переменная a больше либо равна переменной b и ложно в противном случае. |
if(a != b) | Истинно, если переменная а не равна переменной b и ложно в противном случае. |
if(a) | Истинно, если переменная а не равна нулю, и ложно в противном случае. |
Пример:
Программа определения знака введенного числа.
#include <stdio.h>
Int main()
{ float x;
printf("Введите число: ");
scanf("%f",&x);
if(x < 0)
printf("Введенное число %f является отрицательным.\n", x);
if(x >= 0)
printf("Введенное число %f является неотрицательным.\n", x);
return 0;
}
Анализ приведенного текста программы показывает, что два условных оператора можно заменить одним, используя конструкцию
If (выражение)
<оператор1>
Else
<оператор2>
которая интерпретируется таким образом. Если «выражение» истинно, то выполняется «оператор1», иначе выполняется «оператор2».
В случаях, когда при выполнении какого-либо условия необходимо записать более одного оператора, необходимо использовать фигурные скобки, т.е. использовать конструкцию вида
If (выражение)
{ <список операторов>}
Else
{ <список операторов>}
Следует отметить, что после ключевого слова else формально можно поставить еще один оператор условия if, в результате получим еще более гибкую конструкцию условных переходов:
if(выражение1) <оператор1>
else if(выражение2) <оператор2>
else <оператор3>
До сих пор рассматривались простые условия типа x<0. Вместе с тем оператор if позволяет реализовывать более сложные условные переходы.
В языке С имеются три логические операции:
&& - логическое И || - логическое ИЛИ ! - логическое НЕТ
На основе этих трех логических операций можно сформировать более сложные условия.
Например, если имеются три переменные exp1, exp2 и exp3, то они могут составлять логические конструкции, представленные в таблице 3:
Таблица 3 . Пример составных логических конструкций
if(exp1 > exp2 && exp2 < exp3 ) | Истинно, если значение переменной expl больше значения переменной exp2 и значение переменной exp2 меньше значения переменной exp3. |
if(exp1 <= exp2 || expl >= exp3 ) | Истинно, если значение переменной exp1 меньше либо равно значения переменной exp2 или значение переменной exp2 больше либо равно значения переменной exp3. |
if(exp1 && exp2 && !exp3) | Истинно, если истинное значение exp1 и истинно значение exp2 и ложно значение exp3. |
if(!exp1 || !exp2 && exp3) | Истинно, если ложно значение exp1 или ложно значение exp2 и истинно значение exp3. |
Подобно операциям умножения и сложения в математике, логические операции И ИЛИ НЕТ, также имеют свои приоритеты. Самый высокий приоритет имеет операция НЕТ, т.е. такая операция выполняется в первую очередь. Более низкий приоритет у операции И, и наконец самый малый приоритет у операции ИЛИ.
Условная операция if облегчает написание программ, в которых необходимо производить выбор между небольшим числом возможных вариантов. Однако иногда в программе необходимо осуществить выбор одного варианта из множества возможных. Формально для этого можно воспользоваться конструкцией if else if ... else.
Однако во многих случаях оказывается более удобным применять оператор switch языка С.
Синтаксис данного оператора следующий:
Switch(переменная)
{ case константа1:
<операторы>
case константа2:
<операторы>
default:
<операторы> }
Данный оператор последовательно проверяет на равенство переменной константам, стоящим после ключевого слова case. Если ни одна из констант не равна значению переменно, то выполняются операторы, находящиеся после слова default. Оператор switch имеет следующую особенность. Допустим, значение переменной равно значению константы 1 и выполняются операторы, стоящие после первого ключевого слова case. После этого выполнение программы продолжится проверкой переменной на равенство константы 2, что часто приводит к неоправданным затратам ресурсов. Во избежание такой ситуации следует использовать оператор break для перехода программы к следующему оператору после switch.
Пример:использования оператора switch.
#include <stdio.h>
Int main()
{ int x;
printf("Введите число: ");
scanf("%d",&x);
Switch(x)
{ case 1 : printf("Введено число 1\n"),break;
case 2 : printf("Введено число 2\n"); break;
default : printf("Введено другое число\п"); }
char ch;
printf("Введите символ: ");
scanf("%с",&сh; switch(ch)
{case 'a': printf("Введен символ а\n"); break;
case 'b': printf("Введен символ b\n"); break;
default : printf("Введен другой символ\n");
}
return 0;
}
Данный пример демонстрирует два разных варианта использования оператора switch. В первом случае выполняется анализ введенной цифры, во втором - анализ введенного символа. Следует отметить, что данный оператор может производить выбор только на основании равенства своего аргумента одному из перечисленных значений case, т.е. проверка выражений типа x<0 в данном случае невозможна.
Операторы циклов языка С.
Часто требуется много раз выполнить одну и ту же группу операторов. Например, для вычисления суммы ряда длиной N или перебора элементов массива с целью определения наибольшего или наименьшего значения и т.п. Во всех этих случаях необходим инструмент для реализации повторяющихся операций и таким инструментом являются операторы цикла.
С помощью оператора while реализуется цикл, который выполняется до тех пор, пока истинно условие цикла. Синтаксис данного оператора следующий:
while(<условие>)
{<тело цикла> }
Пример цикла, в котором выполняется суммирование элементов ряда S = ∑ i , пока S < N:
int N=20, i = 0;
long S = 0;
while(S < N)
{ S=S+i;
i + +; }
В данном примере реализуется цикл while с условием i < N. Так как начальное значение переменной i=0,аN=20, то условие истинно и выполняется тело цикла, в котором осуществляется суммирование переменной i и увеличение ее на 1. Очевидно, что на 20 итерации значение i=20, условие станет ложным и цикл будет завершен.
Продемонстрируем гибкость языка С, изменив данный пример следующим образом:
int N=20, i = 0;
long S = 0;
while((S=S+i++) < N);
В данном случае при проверке условия сначала выполняются операторы, стоящие в скобках, где и осуществляется суммирование элементов ряда и только, затем, проверяется условие. Результат выполнения обоих вариантов программ одинаковый и S=21.
Однако последняя конструкция бывает удобной при реализации опроса клавиатуры, например, с помощью функции scanf():
int num;
while(scanf("%d",&num) == 1)
{ printf("Bы ввели значение %d\n",num); }
Данный цикл будет работать, пока пользователь вводит целочисленные значения и останавливается, если введена буква или вещественное число.
Следует отметить, что цикл whileможно принудительно завершить даже при истинном условии цикла. Это достигается путем использования оператора break. Перепишем предыдущий пример так, чтобы цикл завершался, если пользователь введет число 0.
int num;
while(scanf("%d",&num) == 1)
{ if(num == 0) break;
printf("Вы ввели значение %d\n",num);}
Цикл завершается сразу после использования оператора break, т.е. в приведенном примере, при вводе с клавиатуры нуля функция printf() выполняться не будет и программа перейдет на следующий оператор после while.
Того же результата можно добиться, если использовать составное условие в цикле:
int num;
while(scanf("%d",&num) == 1 && num != 0)
{ printf("Bы ввели значение %d\n",num);}
Таким образом, в качестве условия возможны такие же конструкции, что и в операторе if.
Работа оператора цикла for подобна оператору while с той лишь разницей, что оператор for подразумевает изменение значения некоторой переменной и проверки ее на истинность. Работа данного оператора продолжается до тех пор, пока истинно условие цикла.
Синтаксис оператора for следующий:
for (<инициализация счетчика>;<условие>;<изменение значения счетчика>)
{ <тело цикла> }
Рассмотрим особенность реализации данного оператора на примере вывода таблицы кодов ASCII символов.
char ch;
for(ch = 'a'; ch <= 'z'; ch++)
printf("Значение ASCII для %c - %d.\n",ch,ch);
В данном примере в качестве счетчика цикла выступает переменная ch, которая инициализируется символом ‘a’. Это означает, что в переменную ch заносится число 97 - код символа ‘a’. Именно так символы представляются в памяти компьютера. Код символа ‘z’ - 122, и все малые буквы латинского алфавита имеют коды в диапазоне [97; 122]. Поэтому, увеличивая значение ch на единицу, получаем код следующей буквы, которая выводится с помощью функции printf(). Учитывая все вышесказанное, этот же пример можно записать следующим образом:
for(char ch = 97; ch <= 122; ch++)
printf("Значение ASCII для %c - %d.\n",ch,ch);
Здесь следует отметить, что переменная ch объявлена внутри оператора for. Это особенность языка С - возможность объявлять переменные в любом месте программы.
Существует много особенностей реализации данного оператора, отметим основные из них, которые могут заметно повысить скорость написания программ. Следующим примером продемонстрируем особенности изменения значения счетчика цикла.
int line_cnt = 1;
double debet;
for(debet = 100.0; debet<150.0; debet=debet*1.1, line_cnt++)
printf("%d. Ваш долг теперь равен %.2f.\n", line_cnt, debet);
Следующий фрагмент программы демонстрирует возможность программирования сложного условия внутри цикла.
int exit = 1;
for(int num = 0;num < 100 && !exit; num += 1)
{ scanf("%d",&mov);
if(mov == 0) exit = 0;
printf("Произведение num*mov = %d.\n",num*mov);
}
Оператор for с одним условием:
int i=0;
for( ; i < 100 ; )
i++;
и без условия
int i=0;
For( ; ; ; )
{i++;
if(i > 100) break;
}
В последнем примере оператор break служит для выхода из цикла for, т.к. он будет работать «вечно» не имея никаких условий.
Бывают ситуации, когда целесообразно выполнять проверку условия после того, как будут выполнены операторы, стоящие внутри цикла. Это достигается путем использования операторов do while, которые реализуют цикл с постусловием.
Пример:
const int secret_code = 13;
int code_ent;
do {
printf("Введите секретный код: ");
scanf("%d",&code_ent);
}
while (code_ent != secret_code);
Цикл с постусловием работает до тех пор, пока истинно условие, то есть пока значение введенного кода будет отличаться от значения секретного кода.
Следует обратить внимание на то, что после ключевого слова while должна стоять точка с запятой. При реализации данного цикла можно использовать составные условия, подобно циклу while, а также принудительно выходить из цикла с помощью оператора break.
Все рассмотренные выше операторы циклов допускают использование любых других операторов языка С внутри цикла, в том числе и операторов цикла. Это значит, что внутри одного цикла может находиться другой, что приводит к реализации вложенных циклов. Вложенные циклы необходимы для решения большого числа задач, например, вычисления двойных, тройных и т.д. сумм, просмотр элементов двумерного массива и многих других задач. В качестве примера вложенных циклов рассмотрим задачу вычисления суммы
двойного ряда S = ∑∑(i* j):
long S = 0;
int M = 10, N = 5;
for( int i = 0; i <= N; i++)
{ for( int j = 0; j <= M; j++)
S += i*j; }
Того же результата можно добиться и с помощью оператора цикла while.
Массивы.
Представление данных в виде отдельных переменных не всегда достаточно при программировании реальных задач. Например, для представления поведения сигнала во времени или хранения информации об изображении удобно использовать специальный тип данных - массивы. Одномерные массивы можно ассоциировать с компонентами вектора, а двумерные - с матрицами. В общем случае массив - это набор элементов данных одного типа, для объявления которого используется следующий синтаксис:
<тип данных> <имя массива>[число элементов];
Например:
int array_int[100]; //одномерный массив 100 целочисленных
// элементов
double array_d[25]; //одномерный массив 25 вещественных
// элементов
Объявление массивов отличается от объявления обычных переменных наличием квадратных скобок [ ].
Также имена массивов выбираются по тем же правилам, что и имена переменных. Обращение к отдельному элементу массива осуществляется по номеру его индекса.
Пример: запись в массив значений линейной функции
f (х) = kx + b и вывода значений на экран:
double k=0.5, b = 10.0;
double f[100];
for(int x=0; i < 100; i++)
{ f[i] = k*x+b;
printf("%.2f ",f[i]); }
В языке С предусмотрена возможность инициализации массива в момент его объявления, например, таким образом
int powers[4] = {1, 2, 4, 6};
В этом случае элементу powers[0] присваивается значение 1, powers[1] - 2, и т.д.
Особенностью инициализации массивов является то, что их размер можно задавать только константами, а не переменными.
Например, следующая программа приведет к ошибке при компиляции:
int N=100;
float array_f[N]; //ошибка, так нельзя.
Поэтому при объявлении массивов обычно используют такой подход:
#include <stdio.h>
#define N 100
Int main()
{ float array_f[N];
return 0; }
Следует отметить, что при инициализации массивов число их элементов должно совпадать с его размерностью.
Рассмотрим вариант, когда число элементов при инициализации будет меньше размерности массива.
#define SIZE 4
int data[SIZE]={512, 1024};
for(int i = 0; i < SIZE; i++)
printf("%d, \n",data[i]);
Результат работы программы будет следующим:
512, 1024, 0, 0
Из полученного результата видно, что неинициализированные элементы массива принимаются равными нулю. В случаях, когда число элементов при инициализации превышает размерность массива, то при компиляции произойдет ошибка. Поэтому, когда наперед неизвестно число элементов, целесообразно использовать такую конструкцию языка C++:
int data[] = {2, 16, 32, 64, 128, 256};
В результате инициализируется одномерный массив размерностью 6 элементов.
Если значение индекса при обращении к элементу массива превысит его размерность, то этом случае ни программа, ни компилятор не выдадут значение об ошибке, но в программе могут возникать непредвиденные ошибки.
Поэтому программисту следует обращать особое внимание на индексы, которые при обращении к элементам массива не выходили за его пределы.
Также следует отметить, что первый элемент массива всегда имеет индекс 0, второй - 1, и т.д.
Для хранения некоторых видов информации, например, изображений удобно пользоваться двумерными массивами. Объявление двумерных массивов осуществляется следующим образом:
int array2D[100][20]; //двумерный массив 100x20 элементов
Нумерация элементов также начинается с нуля, т.е. array2D[0][0] соответствует первому элементу, array2D[0][1] - элементу первой строки, второго столбца и т.д.
Для начальной инициализации двумерного массива может использоваться следующая конструкция:
long array2D[3][2] = {{1, 2},{3, 4},{5, 6}};
или
long array2D[][] = {{1, 2},{3, 4},{5, 6}};
В общем случае можно задать массив любой размерности и правила работы с ними аналогичны правилам работы с одномерными и двумерными массивами.
Работа со строками в языке С .
В языке С нет специального типа данных для строковых переменных. Для этих целей используются массивы символов (тип char).
Пример:
char str_1[100] = {'П,,,р,,,и,,,в,,,е,,,т,,,\0'};
char str_2[100] = "Привет";
char str_3[ ] = "Привет";
printf("%s\n%s\n%s\n",str_1,str_2,str_3);
В приведенном примере показаны три способа инициализации строковых переменных.
Первый способ является классическим объявлением массива,
второй и третий используются специально для строк. Причем в последнем случае, компилятор сам определяет нужную длину массива для записи строки.
Cпециальные управляющие коды, которые показывают, где заканчивается строка или где используется перенос внутри одной строки и т.п.
В частности символ ‘\0’ означает в языке С++ конец строки и все символы после него игнорируются как символы строки.
Пример :
char str1[10] = {'Л','е','к','ц','и','я','\0'};
char str2[10] = {'Л','е','к','ц', '\0','и','я'};
char str3[10] = {'Л','е', '\0','к','ц','и','я'};
printf("%s\n%s\n%s\n",str1,str2,str3);
Результатом работы данного кода будет вывод следующих трех строк:
Лекция
Лекц
Ле
Из этого примера видно как символ конца строки ‘\0’ влияет на длину строк. Таким образом, чтобы подсчитать длину строки (число символов) необходимо считать символы до тех пор, пока не встретится символ ‘\0’ или не будет достигнут конец массива. Функция вычисления размера строк уже реализована в стандартной библиотеке языка С string.h и имеет следующий синтаксис:
int strlen(char* str);
где char* str - указатель на строку.
Пример использования функции strlen():
#include <stdio.h>
#include <string.h>
int main(void)
{ char str[ ] = "Привет мир!";
int length = strlen(str);
printf("Длина строки = %d.\n",length);
return 0; }
Результатом работы программы будет вывод на экран числа 11. Учитывая, что первый символ имеет нулевой индекс, то можно заметить, что данная функция считает и символ ‘\0’.
Пусть объявлены две строки
char str1[ ] = "Это первая строка";
char str2[ ] = "Это вторая строка";
и необходимо выполнить оператор присваивания
str1 = str2;
При такой записи оператора присваивания компилятор выдаст сообщение об ошибке.
Для того чтобы выполнить копирование необходимо перебирать по порядку элементы одного массива и присваивать их другому массиву. Данная функция реализована в библиотеке языка С string.h и имеет следующее определение:
char* strcpy(char* dest, char* src);
Она выполняет копирование строки src в строку dest и возвращает строку dest.
Пример использования функции strcpy():
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[] = "Привет мир!";
char dest[100];
strcpy(dest,src);
printf("%s\n",dest);
return 0; }
Кроме операций вычисления длины строки и копирования строк важной является операция сравнения двух строк между собой.
В языке С две строки считаются одинаковыми, если равны их длины и элементы одной строки равны соответствующим элементам другой. Функция сравнения двух строк имеет вид:
int strcmp(char* str1, char* str2);
и реализована в библиотеке string.h. Данная функция возвращает нуль, если строки str1 и str2 равны и не нуль в противном случае.
Пример использования данной функции:
char str1[ ] = "Это первая строка";
char str2[ ] = "Это вторая строка";
if(strcmp(str1,str2) ==0)
printf("Строка %s равна строке %s\n",str1,str2);
else printf("Строка %s не равна строке %s\n",str1,str2);
В языке С имеется несколько функций, позволяющих вводить строки с клавиатуры. Самой распространенной из них является ранее рассмотренная функция scanf(), которой в качестве параметра передается ссылка на массив символов:
char str[100];
scanf("%s",str);
В результате выполнения этого кода, переменная str будет содержать введенную пользователем последовательность символов. Кроме функции scanf() также часто используют функцию gets() библиотеки stdio.h, которая в качестве аргумента принимает ссылку на массив символов:
gets(str);
Данная функция считывает символы до тех пор, пока пользователь не нажмет клавишу Enter, т.е. введет символ перевода строки ‘\n’.
Затем она записывает вместо символа ‘\n’ символ ‘\0’ и передает строку вызывающей программе.
Для вывода строк на экран помимо функции printf() можно использовать также функцию puts() библиотеки stdio.h, которая более проста в использовании. Пример:
#define DEF "Заданная строка"
char str[ ] = "Это первая строка";
puts(str);
puts (DEF);
puts(&str[4]);
Результат работы следующий:
Double square(double x)
{ x = x* x;
return x; }
Int main()
{double arg = 5;
double sq1=square(arg);
double sq2=square(3);
return 0;}
В данном примере задается функция с именем square, которая принимает один входной параметр типа double, возводит его в квадрат и возвращает вычисленное значение вызывающей программе с помощью оператора return. Следует отметить, что работа функции завершается при вызове оператораreturn. Даже если после этого оператора будут находиться другие операторы, то они выполняться не будут.
Например:
Int square(int x)
{x = x*x;
return x;
printf("%d",x);}
при вызове данной функции оператор printf() не будет выполнен никогда, т.к. оператор returnзавершит работу функции square.
Оператор return является обязательным, если функция возвращает какие-либо значения. Если же она имеет тип void, т.е. ничего не возвращает, то оператор return может не использоваться.
Можно создавать множество своих функций. При этом важно, чтобы объявление функции было раньше ее использования в программе подобно переменным. Именно поэтому во всех примерах объявление функций осуществляется до функции main(), в которой они вызываются.
Функция может принимать произвольное число аргументов, но возвращает только один или не одного (тип void). Для задания нескольких аргументов функции используется следующая конструкция:
void show(int x,int y,int z) { }
Здесь следует обратить внимание на то, что каждой переменной в списке аргументов функции предшествует ее тип, в отличие от объявления обычных переменных. Поэтому следующая программная строка приведет к сообщению об ошибке на этапе компиляции:
void show(int x, y, z) {} //неверное объявление
Если число пользовательских функций велико (50 и выше), то возникает неудобство в их визуальном представлении в общем тексте программы. Действительно, имея список из 100 разных функций с их реализациями, в них становится сложно ориентироваться и вносить необходимые изменения.
Для решения данной проблемы в языке С при создании своих функций можно пользоваться правило<