Строковые литералы, массивы и указатели

Строковые литералы —последовательность символов, заключенная в двойные кавычки. В строковом литерале на один символ больше, чем используется при записи. Он всегда заканчивается нулевым символом '\0’.

Пример:

sizeof(“Бор”); // значение 4

Строковый литерал можно присвоить переменной типа char*

Но, изменение литерала через такой указатель является ошибкой.

Пример:

#include<stdio.h>

int main()

{

char cStr[]="Mars";

cStr[2]='p'; // ошибки нет

printf("cStr=%s\n",cStr);

char* pStr="Mars"; //

pStr[2]='p';// ошибка при выполнении программы

printf("pStr=%s\n",pStr);

return 0;

}

Объявление объектов и типов.

Все переменные в Си должны быть объявлены. Объявление происходит с помощью ключевого слова – спецификатора типа, идентификатора и модификаторов.

Модификатор Определяемый тип
* указатель
[] массив
() функция

Можно использовать одновременно более одного модификатора, что позволяет создавать множество сложных описателей типов.

Замечание: Некоторые комбинации недопустимы, например:

1. элементами массива не могут быть функции:

2. функции не могут возвращать функции.

При интерпретации сложных описателей квадратные и круглые скобки (справа от идентификатора) имеют приоритет перед звездочкой (слева от идентификатора).

Квадратные или круглые скобки имеют один и тот же приоритет и связываются слева направо.

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

Для интерпретации можно использовать простое правило: «изнутри наружу», состоящее из 4-х шагов.

1. Начать интерпретацию с идентификатора и посмотреть вправо, есть ли квадратные или круглые скобки.

2. Если они есть, то проинтерпретировать эту часть описателя и затем посмотреть налево в поисках звездочки.

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

4. Интерпретировать спецификатор типа.

Пример:

int *(*comp[10])()

6 5 3 1 2 4

В примере объявляется переменная comp (1) как массив (2) из 10 указателей (3) на функции (4), возвращающие указатели (5) на целые значения(6).

/* Что напечатает программа? */

#include <stdio.h>

int main()

{

char note[]="You are welcome!";

char *ptr;

ptr=note;

puts(ptr); // You are welcome!

puts(++ptr; // ou are welcome!

note[7]='\0';

puts(note); // You are

puts(++ptr); // u are

return 0;

}

// Примеры объявления с использованием модификаторов

int board [8][8]; // массив массивов типа int

int **ptr; // указатель на указатель на тип int

int *risk[10]; // 10-элементный массив указателей на тип int

int (*wis)[10]; // указатель на 10-элементный массив типа int

int (*oop)[3][4]; // указатель на массив 3x4 типа int

char *fun(); // функция, возвращающая указатель на тип char

char (*fun)(); // указатель на функцию, возвращающую тип char

char (*fun())[3]; // функция, возвращающая указатель на 3-эл. массив har*/

Пример: /* Многоуровневые ссылки */

#include <stdio.h>

char *m[]={"January","February","March","April","May","June","July",

"August","September","October","November","December"};

char **mp[]={m+11,m+10,m+9,m+8,m+7,m+6,m+5,m+4,m+3,m+2,m+1,m};

char ***mpp[]={mp,mp+9,mp+6,mp+3};

char ****mppp=mpp;

int main()

{

int i;

printf("%s\n",***++mppp);

printf("%s\n",***--mppp);

for(i=0;i<12;i++)

printf("%s%c",mppp[0][0][i-11],(i==6)?'\n':' ');

printf("\n");

for(i=0;i<12;i++)

printf("%s%c",mppp[1][2][11-i],(i==5)?'\n':' ');

printf("\n");

printf("%s\n",*mppp[3][1]);

printf("%s\n",**mppp[1]+3);

printf("%s\n",mppp[2][-1][3]+2);

for(i=0;i<8;i++)

printf("%s\n",mppp[3][-2][-9]+i);

return 0;

}

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

March

December

January February March April May June July

August September October November December

December November October September August July

June May April March February January

August

ch

tober

February

ebruary

bruary

ruary

uary

ary

ry

y

Пример:

#include <stdio.h>

char *c[]={"TEST1 ","NOP ","FILE ","FIRST "};

char **cp[]={c+3,c+2,c+1,c};

char ***cpp=cp;

int main()

{

printf("%s ",**++cpp);

printf("%s ",*--*++cpp+3);

printf("%s",*cpp[-2]+3);

printf("%s\n",cpp[-1][-1]+1);

return 0;

}

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

FILE T1 STOP

Пример:/* нахождение определителя матрицы */

#include<stdio.h>

#include<windows.h>

#define n 4

void main()

{

float a[n][n],koef,det=1;

int i,j,k;

char cStr[]="Введите матрицу n на n";

CharToOem(cStr,cStr);

printf("%s\n",cStr);

for(i=0;i<n;i++)

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

scanf("%f",&a[i][j]);

// Прямой ход

for(i=0;i<n-1;i++){ // идем по строкам

for(j=i+1;j<n;j++){ //по соотв. столбцу

koef=a[j][i]/a[i][i];

for(k=i;k<n;k++) //по столбцам

a[j][k]-=a[i][k]*koef;}}

// Вывод результатов

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

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

printf("a[%d][%d]=%5.2f\t",i,j,a[i][j]);

printf("\n");}

for(i=0;i<n;i++)

det*=a[i][i];

printf("det=%5.2f\n",det);

}

Пример: /* решение СЛАУ методом Гаусса */

#include<stdio.h>

#include<windows.h>

#define n 4

void main()

{

float a[n][n+1],x[n],koef,det=1,y=0;

int i,j,k;

char cStr[]="Введите матрицу n на n+1";

CharToOem(cStr,cStr);

printf("%s\n",cStr);

for(i=0;i<n;i++)

for(j=0;j<n+1;j++)

scanf("%f",&a[i][j]);

// Прямой ход метода Гаусса

for(i=0;i<n;i++){ // идем по строкам

for(j=i+1;j<n;j++){ // по соотв. столбцу

koef=a[j][i]/a[i][i];

for(k=i;k<n+1;k++) // по столбцам

a[j][k]-=a[i][k]*koef;}}

// Вывод результатов

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

for(j=0;j<n+1;j++)

printf("a[%d][%d]=%5.2f\t",i,j,a[i][j]);

printf("\n");}

for(i=0;i<n;i++)

det*=a[i][i];

printf("det=%f\n",det);

// Обратный ход.

x[n-1]=a[n-1][n]/a[n-1][n-1];

for(i=n-2;i>=0;i--){

y=0;

for(j=n-1;j>i;j--)

y+=a[i][j]*x[j];

x[i]=(a[i][n]-y)/a[i][i];}

for(i=0;i<n;i++)

printf("x[%d]=%5.2f\n",i+1,x[i]);

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: