Функции и структура программы 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Функции и структура программы



 

4.1. Перечислите все существенные изменения, внесенные стандартом ANSI в правила объявления и описания функций. Какова цель этих изменений?

 

4.2. Перечислить все случаи, когда в Си используется тип void. Дать определение этого типа.

 

4.3. Перечислить классы памяти, определенные в Си. Что определяет класс памяти? В каких случаях и каким образом класс памяти определяется по умолчанию? Привести примеры.

 

4.4. Определен ли в Си класс памяти для функций? Если определен, то каким образом; если нет, то почему.

 

4.5. Допустима ли в Си вложенность функций? Можно ли в Си каким-то образом управлять видимостью функций?

 

4.6. Объяснить, чем различаются описание (объявление, declaration) и определение (definition) – по терминологии Б. Кернигана и Д. Ритчи [1, см. стр.71]. Привести примеры.

 

4.7. Эквивалентны ли следующие объявления функций:

a) double f (); и double f (void);

b) char g (int i, char c); и char g (int, char);

c) h (double x); и int h (double x);

d) void h (int); и h (int);

e) extern int q (int); и int q (int);

f) static void s (char c); и void s (char c);

 

4.8. Определить, какие конструкции являются определениями, а какие описаниями; где они могут располагаться и что обозначают:

int i; char c = ‘a’; extern int f (int, char);

static int j; register int b; double g() { return 3.141592; };

extern long k; int h (int i); static char q(int, double);

auto short n; s(); static void p(int i) { };

 

4.9. Верны ли следующие утверждения:

a) «тип выражения в операторе return должен совпадать с типом результата функции»

b) «функция, которая не возвращает результата (тип результата void), может не содержать оператор return;»

c) «функция, которая возвращает результат, может не содержать оператор return E; но вызывает другую функцию, которая содержит такой оператор»

d) «функция, которая возвращает результат, может содержать несколько операторов return E;»

e) «в Си аргументы функции всегда передаются по значению»

f) «в теле одной функции могут находиться два разных оператора, помеченных одинаковыми метками, если эти операторы находятся в разных блоках»; например,

void f(void)

{ ... label: S1; ...

{ ... label: S2; ... goto label; ... }

... goto label; ...

}

g) «в Си нельзя использовать две (или более) взаимно рекурсивных функций»; например, если есть void f(void){ ... g(); ... } и void g(void){ ... f(); ... }, то программа, использующая такие функции, будет ошибочной.

h) «в Си можно войти в блок, минуя его заголовок; при этом память под локальные переменные, описанные в этом блоке, будет отведена, но инициализация (если она есть) выполняться не будет»

i) «любая функция, описанная в каком-либо файле, входящем в состав программы, может быть использована в этом и любом другом файле этой программы»

j) «в этом фрагменте программы нет ошибок»

#include <stdio.h>

int f(void) { return 100;}

void g(void) { printf("O.K.\n");}

main()

{ int i, j;

i = f();

j = g(), f();

g(); f();

printf("i=%d, j=%d f=%d\n", i, j, f());

}

 

4.10. В каких случаях в Си возможна инициализация переменных? Когда она происходит? Как определяется инициализация по умолчанию?

 

4.11. Допустимо ли в Си? Если "да" - опишите семантику этих действий; если "нет" - объясните почему.

a) #include <stdio.h> b) #include <stdio.h>

main() main()

{ int i; int sum = 0; { int i; int sum = 0;

for (i = 1; i <= 3; i++) for (i = 1; i <= 3; i++)

{ sum += i; { sum += i;

{ int i; { for (i = 1; i <= 5; i++)

for (i = 1; i <= 5; i++) sum *= i;

sum *= i; }

} }

} printf("sum=%d\n", sum);

printf("sum=%d\n", sum); }

}

c) #include <stdio.h> d) #include <stdio.h>

main() main()

{ double x; { double x;

scanf("%f", &x); scanf("%f", &x);

if (x >= 0) goto ok; if (x >= 0) goto ok;

{ double y = 5.0; { double y;

x = x? x: -x; x = x? x: -x;

ok: y+=sqrt(x); ok: y = sqrt(x);

printf("y = %f\n",y);} printf("y = %f\n",y);

} }

} }

4.12. Допустимо ли в Си? Если "да" - опишите семантику этих действий; если "нет" - объясните почему.

a) файл f1: b) файл f1:

#include<stdio.h> #include<stdio.h>

main() static int f(void)

{ extern int f(int); { int k;

int i; scanf("%d", &k); return k; }

i = f(g(5)); extern int g(int);

printf("i = %d\n", i); main()

} { int i;

int g(int k) i = f(); j = g(i);

{ k++; printf("i=%d,j=%d\n", i,j);

return f(k); }

} файл f2:

файл f2: extern int f(void);

int f(int i) { return i*i; } int g(int i)

{ return f()+i; }

 

c) файл f1: d) файл f1:

#include<stdio.h> #include<stdio.h>

extern int i; extern void f(void); extern int f(void);

main() int i;

{ f(); main()

printf("i = %d\n", i); { printf("res = %d\n", i+f()+f());

f(); }

printf("i = %d\n", i);

} файл f2:

int f(void)

файл f2: { static int i = 10;

int i = 1; return i--;

void f(void) { i++; } }

 

4.13. Что напечатает следующая программа?

 

a). #include <stdio.h> b). #include <stdio.h>

int i = 0; void f(void); int f(int); int b = 10;

main() main()

{ int i =1; { int c = 3;

printf("i1 = %d\n", i); b = f(c);

f(); printf("c=%d b=%d\n",c,b);

{ int i = 2; printf("i4 = %d\n", i); }

{ i +=1; printf("i5 = %d\n", i); } int f(int b)

printf("i6 = %d\n", i); { int c = 5;

} c--; b++;

printf("i7 = %d\n", i); printf("c=%d b=%d\n",c,b);

} return c+b;

void f(void) }

{ printf("i2 = %d\n", i);

i = i + 10; printf("i3 = %d\n", i); }

 

c). #include <stdio.h> d). #include <stdio.h>

char g (char c); int abc(int); int x;

int f (int i, char c) main()

{ int k = i+4; char b = g(c) + i; { int b;

printf("c1 = %c k0 = %d\n", c, k); b = abc(x);

{ int i = 3; k += i; printf("b1=%d x1=%d\n",b,x);

printf("i1 = %d k1 = %d\n", i, k); x = abc(b);

c = g(‘b’); printf("c2 = %c\n", c); printf("b2=%d x2=%d\n",b,x);

} }

i++; printf("i2 = %d k2 = %d\n", i, k); int abc(int b)

return i*(b-c); } { static int x = 5;

char g(char c) x += 7; b++;

{ c = c + 1; return c; } printf("b0=%d x0=%d\n",b,x);

main() return x+b;

{ int k =2; char c = ‘a’; k = f (k, c); }

printf("c3 = %c k3 = %d\n", c, k);

}

e). #include <stdio.h> f). #include <stdio.h>

int i = 1; int i = 1;

int reset (void); int reset (void);

int next (int); int next (void);

int last (int); int last (void);

int new (int); int new (int);

main() main()

{ int i, j; i = reset(); { int i, j; i = reset();

for (j = 1; j <= 3; j++) for (j = 1; j <= 3; j++)

{ printf("i=%d j=%d\n", i, j); { printf("i=%d j=%d\n", i, j);

printf("%d %d\n", next(i), last(i)); printf("%d\n", next(),);

printf("%d\n", new(i+j)); printf("%d\n", last());

} } printf("%d\n", new(i+j)); } }

int reset (void) { return i; } в файле f1:

int next (int j) { return j = i++; } static int i =10;

int last (int j) int next (void) { return i += 1; }

{ static int i = 10; return j = i--; } int last (void) { return i -= 1; }

int new (int i) int new (int i)

{ int j = 10; return i = j += i; } { static int j = 5; return i=j+=i; }

в файле f2:

extern int i;

int reset (void) { return i; }

 

4.14. Программа. Описать рекурсивную функцию вычисления n! - факториала числа n, основанную на соотношении n! = n*(n-1)!. С ее помощью найти факториалы натуральных чисел от1 до 10.

 

4.15. Программа. Описать рекурсивную функцию вычисления xn для вещественного x (x ¹ 0) и целого n:

ì 1 при n = 0

xn = í 1/x|n| при n < 0

î x* xn-1 при n > 0

Протестировать эту функцию на подходящих наборах входных данных.

 

4.16. Программа. Описать рекурсивную функцию вычисления НОД(n,m) - наибольшего общего делителя неотрицательных целых чисел n и m, основанную на соотношении НОД(n,m) = НОД(m,r), где r - остаток от деления n на m (см. задачу 3.43). С ее помощью найти наибольший общий делитель натуральных чисел a и b. Сравнить эффективность рекурсивной и нерекурсивной функций вычисления НОД.

 

4.17. Программа. Описать рекурсивную функцию вычисления
НОД (n1, n2, n3,..., nm), воспользовавшись для этого соотношением:
НОД (n1, n2, n3,..., nk) = НОД (НОД (n1, n2, n3,..., nk-1), nk), k = 3, 4,..., m. С ее помощью найти НОД (a1, a2, a3,..., a10).

 

4.18. Программа. Описать рекурсивную функцию вычисления n–ого числа Фибоначчи: f0 = 1; f1 = 1; fj+1 = fj-1+ fj; j = 1, 2, 3,.…С ее помощью вычислить 100-ое число Фибоначчи.

 

4.19. Программа. Описать рекурсивную функцию вычисления значения A(n,m) - функции Аккермана для неотрицательных целых чисел n и m:

ìm+1 если n = 0

A(n,m) = íA(n-1,1) если n ¹ 0, m = 0

îA(n-1, A(n, m-1)) если n>0, m>0

С помощью этой функции найти значение A(5,8).

 

 

УКАЗАТЕЛИ И МАССИВЫ

 

5.1. Допустимо ли в Си? Если "да" - опишите семантику каждого правильного действия (не принимая во внимание ошибочные); если "нет" - объясните почему.

a). ...

int i,* p, j, *q;

p = &i; q = &p;

j = *p = 1; q = p-1; *p += 1;

i = *++q + *p; q -= 1; i = *q ++ + *q;

printf("i=%d, j=%d, *p=%d, *q=%d \n", i, j, *p, *q);

b) ...

int x = 1, y; char c = ‘a’;

int *pi, *qi; char *pc;

pi = &x; *pi = 3; y = *pi; *pi = c; qi = pi;

pc = qi; *qi+=1; pi++; *(- - pi) = 5; y = *qi+1;

pc = &c; ++*pc; (*pc)++; *pc++; *pc+=1;

x = (int)pi; pi=(int*)pc; pi=(int*)x; x = 1+ *pi; pc=(char*)pi;

c = *pc; pc = &y; x = qi – pi; qi = 0; qi+=pi;

y = &pi; y = (int)&pi; pi = pi +5; *(pi+1)=0; pi=&(x+0);

 

5.2. К любому ли объекту в Си можно применять операцию взятия адреса &?

5. 3. Допустимо ли в Си? Если "да" - опишите семантику этих действий; если "нет" - объясните почему.

a) int i = 2; const int j = 5;

int *pi;

const int *pci;

int *const cpi;

const int * const cpci;

pi = &i; pci = &j; cpi = &i; cpci = &j; pci = &i;

pi = (int*)&j; i = *pci + *pi; *pci = 3;

*pi = 3; i=*pci++; *(cpi++)=5; *cpi++;

b) int f(const int i, int j) { j++; return i+j; }

main()

{ int a, b; const int c = 5;

scanf("%d", &a);

b = f(c,a); printf("a=%d, b=%d, c=%d \n", a, b, c);

b = f(c,c); printf("a=%d, b=%d, c=%d \n", a, b, c);

b = f(a,a); printf("a=%d, b=%d, c=%d \n", a, b, c);

b = f(a,c); printf("a=%d, b=%d, c=%d \n", a, b, c);

}

 

5.4. Пусть целочисленный массив a соддержит 100 элементов. Верно ли решена задача: "написать фрагмент программы, выполняющий суммирование всех элементов массива a".

a) int a[100], sum, i;

sum = 0;

for (i = 0; i < 100; ++i) sum += a[i];

b) int a[100], *p, sum;

sum = 0;

for (p = a; p < &a[100]; ++p) sum = sum + *p;

c) int a[100], *p, sum;

sum = 0;

for (p = &a[0]; p < &a[100]; p++) sum += *p;

d) int a[100], sum, i;

sum = 0;

for (i = 0; i < 100; ++i) sum += *(a+i);

e) int a[100], sum, i;

sum = 0;

for (i = 0; i < 100; ++a, ++i) sum += *a;

f) int a[100], *p, sum, i;

sum = 0;

for (i = 0, p = a; i < 100; ++i) sum += p[i];

g) int a[100], *p, sum, i;

sum = 0;

for (i = 0, p = a; i < 100; ++i) sum += *(p+i);

 

5.5. Допустимо ли в Си? Если "да" - опишите семантику каждого правильного действия (не принимая во внимание ошибочные); если "нет" - объясните почему.

a) ...

int a[5] = { 1, 2, 3, 4, 5 };

int *p, x, *q, i;

p = a + 2; * (p+2) = 7;

*a += 3; q=*&p-1;

x = ++ p - q ++; x += ++ *p; x=*p-- + *p++;

for (i = 0; i < 5; i++) printf("a [%d]=%d", i, a[ i ]); printf("\n");

printf("x=%d, *p=%d, *q=%d \n", x, *p, *q);

b) ...

char *str = "abcdef";

char *p, *q, *r; int k;

p = str; q = 0; p++;

k = p - str; r = p+k;

if (k && p || q) q = str + 6;

p = q? r: q; *(p-1) = ‘a’; *r = ‘x’;

printf("str: %s\n", str);

c) ...

char s[ ] = "0123456";

int *pi; char *pc1, *pc2;

pc2 = s;

pc1 = s + *(s+strlen(s) - 1) - ‘0’;

pi = (int*) pc2; *pc1-- = ‘8’;

if (pc1 - pc2 < 3) pc1 = pc2 = pi; else pc1 = (pc1+pc2)/2;

if (s == pc2) *pc1 = *pc2 + 1; else *pc1 = ‘9’;

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

d) ...

int i; char *c; int *pi;

i = ‘a’;

pi = &i; c = (char*)pi + 3; printf("c1=%c", *c);

i <<= 8; c--; printf("c2=%c\n", *c);

e) ...

char c1, c2; short i;

char *pc; short *ps;

c1 = ‘1’; c2 = ‘2’; ps =&i;

pc = (char*)ps; *pc = c1; pc++; *pc = c2;

printf("i = %hd\n", i);

 

5.6. Эквивалентны ли следующие фрагменты программы на Си?

a[ i ] /= k+m и a[ i ] = a[ i ]/k+m

a[ i ] /= k+m и a[ i ] = a[ i ]/(k+m)

a[ i++]+=3 и a[i++] = a[ i++]+3

a[ i++]+=3 и a[ i ] = a[ i++]+3

a[ i++]+=3 и a[ i++ ] = a[ i ]+3

a[ i++]+=3 и a[ i ] = a[ i ]+3; i++;

 

5.7. Что напечатает следующая программа?

#include <stdio.h>

char str[ ] = "SSSWILTECH1\1\11W\1WALLMP1";

main()

{ int i, c;

for (i = 2; (c = str [ i ])!= ‘\0’; i++) {

switch (c) {

case ‘a’: putchar(‘i’); continue;

case ‘1’: break;

case 1: while ((c = str [++ i ])!= ‘\1’ && c!= ‘\0’);

case 9: putchar(‘S’);

case ‘E’: case ‘L’: continue;

default: putchar(c); continue; }

putchar(‘ ’); }

putchar(‘\n’);

}

5.8. Что напечатает следующая программа?

#include <stdio.h>

int a[ ] = { 0, 1, 2, 3, 4 };

main()

{ int i, *p;

for (i = 0; i <= 4; i++) printf("a[ i ]=%d ", a[ i ]); printf("\n");

for (p = &a[0]; p <= &a[4]; p++) printf("*p=%d ", *p); printf("\n");

for (p = &a[0], i = 0; i <= 4; i++) printf("p[ i ]=%d ", p[ i ]); printf("\n");

for (p = a, i = 0; p+i <= a+4; i++) printf("* (p+i)=%d ", * (p+i));

printf("\n");

for (p = a+4; p >= a; p--) printf("*p=%d ", *p); printf("\n");

for (p = a+4, i=0; i <= 4; i++) printf("p[ -i ]=%d ", p[ -i ]);

printf("\n");

for (p = a+4; p >= a; p --) printf("a[ p - a ]=%d ", a[ p - a ]);

printf("\n");

}

 

5.9. Что напечатает следующая программа?

#include <stdio.h>

int a[ ] = { 8, 7, 6, 5, 4 };

int *p[ ] = { a, a+1, a+2, a+3, a+4 };

int **pp = p;

main()

{ printf("*a=%d **p=%d **pp=%d\n", *a, **p, **pp);

pp++;

printf("pp-p=%d *pp-a=%d **pp=%d\n", pp-p, *pp-a, **pp);

++*pp;

printf("pp-p=%d *pp-a=%d **pp=%d\n", pp-p, *pp-a, **pp);

pp = p;

++**pp;

printf("pp-p=%d *pp-a=%d **pp=%d\n", pp-p, *pp-a, **pp);

}

 

5.10. Что напечатает следующая программа?

#include <stdio.h>

int a[ 3 ][ 3 ] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

int *pa[ 3 ] = { a[ 0 ], a[ 1 ], a[ 2 ] };

int *p = a[ 0 ];

main()

{ int i;

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

printf(" a[ i ][ 2 – i ]=%d *a[ i ]=%d *(*(a+i)+i)=%d\n",

a[ i ][ 2 – i ], *a[ i ], *(*(a+i)+i));

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

printf("*pa[ i ]=%d p[ i ]=%d \n", *pa[ i ], p[ i ]);

}

 

5.11. Что напечатает следующая программа?

#include <stdio.h>

char *c[ ] = { "ENTER", "NEW", "POINT", "FIRST" };

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

char ***cpp=cp;

main()

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

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

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

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

}

 

5.12. Какие соглашения о конце строки существуют в Си и Паскале? Укажите все «за» и «против» явного указания концов строк с помощью null-литеры ‘\0’.

 

5.13. В чем заключается проблема «висящей» ссылки? Приведите примеры.

5.14. Нужна ли в Си «сборка мусора»? Почему возникает такая проблема и как она решается в Си?

 

5.15. Прочитайте следующие описания и определения:

int *ip, f(), *fip(), (*pfi)(); char *str[10]; char * (*cp)[5];

int (*r) (); double (*k)(double,int*);

float * (* (*x) [6])(); double (* (* (y())[ ])();

int * (*const *name[9])(void); char * const p;

 

5.16. Определите переменную x как массив указателей на функцию, имеющую два параметра типа int и возвращающую результат типа указатель на double.

5.17. Определите переменную y как указатель на массив указателей на функцию без параметров, возвращающую результат типа указатель на функцию с одним параметром типа int и результатом типа float.

 

5.18. Что будет напечатано? Объяснить, почему результат будет таким.

a) #include <stdio.h> b) #include <stdio.h>

int try_to_change_it(int); void compare (int, int *);

main() main()

{ int i = 4, j; { int i = 4, j = 5;

j = try_to_change_it(i); compare(i, &j);

printf("i=%d, j=%d\n", i, j); printf("i=%d, j=%d\n", i, j);

} }

int try_to_change_it(int k) void compare (int k, int *m)

{ printf("k1=%d\n", k); { printf("k1=%d,*m1=%d\n",k, *m);

k+=33; k++; (*m)++;

printf("k2=%d\n", k); printf("k2=%d,*m2=%d\n", k, *m);

return k; }

}

5.19. Верно ли решена задача: «Описать функцию, меняющую местами значения двух переменных символьного типа. Использовать эту функцию для изменения значений символьных переменных a и b.»

a) void swap (char x, char y) b) void swap (char *x, char *y)

{ char t; t = x; x = y; y = t;} { char *t; t = x; x = y; y = t;}

main() main()

{ char a,b; { char a,b;

scanf("%c%c", &a, &b); scanf("%c%c", &a, &b);

swap(a,b); swap(&a, &b);

printf("a=%c,b=%c\n",a,b); printf("a=%c,b=%c\n",a,b);

} }

c) void swap (char *x, char *y) d) void swap (char *x, char *y)

{ char t; t = *x; *x = *y; *y = t;} { char t; t = *x; *x = *y; *y = t;}

main() main()

{ char a,b; { char a,b;

scanf("%c%c", &a, &b); scanf("%c%c", &a, &b);

swap(a,b); swap(&a, &b);

printf("a=%c,b=%c\n",a,b); printf("a=%c,b=%c\n",a,b);

} }

e) void swap (char x, char y) f) void swap (char &x, char &y)

{ char *t; t = &x; &x = &y; &y = t;} { char t; t = x; x = y; y = t;}

main() main()

{ char a,b; { char a,b;

scanf("%c%c", &a, &b); scanf("%c%c", &a, &b);

swap(&a, &b); swap(a, b);

printf("a=%c,b=%c\n",a,b); printf("a=%c,b=%c\n",a,b);

} }

 

5.20. Допустимо ли в Си? Если "да" - опишите семантику этих действий; если "нет" - объясните почему.

int ques (char *s1, char *s2)

{ while (*s1 && *s2 && *s1++ == *s2++);

return *--s1 - *--s2;

}

 

5.21. Допустимо ли в Си? Если "да" - опишите семантику этих действий; если "нет" - объясните почему.

void ques (char *s1, char *s2, int n)

{ while (*s1 && *s2 && n-- && (*s1 ++ = *s2 ++)); }

 

5.22. Описать функцию, определяющую упорядочены ли строго по возрастанию элементы целочисленного массива из n элементов.

 

5.23. Описать функцию, определяющую индекс первого элемента целочисленного массива из n элементов, значение которого равно заданному числу x. Если такого элемента в массиве нет, то считать номер равным –1.

 

5.24. Описать функцию, вычисляющую значение x0 + x0*x1 + x0*x1*x2 + …+ x0*x1*x2 *… *xm, где xi - элементы вещественного массива x из n элементов, m - индекс первого отрицательного элемента этого массива либо число n-1, если такого элемента в массиве нет.

 

5.25. Описать функцию, вычисляющую значение max(x0 + xn-1, x1 + xn-2, x2 + xn-3,…, x(n-1)/2 + xn/2), где xi - элементы вещественного массива x из n элементов.

 

5.26. Описать функцию, вычисляющую значение min(x0 * x1, x1 * x2,
x2 * x3,…, xn-3 * xn-2, xn-2 * xn-1), где xi - элементы вещественного массива x из n элементов.

 

5.27. Описать функцию, вычисляющую значение x0*y0+x1*y1+ …+ xk*yk, где xi – отрицательные элементы вещественного массива a из n элементов, взятые в порядке их следования; yi – положительные элементы этого массива, взятые в обратном порядке; k = min(p,q), где p – количество положительных элементов массива a, q – количество отрицательных элементов этого массива.

 

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

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

b) сортировка обменом (метод пузырька): последовательно сравни-ваются пары соседних элементов xk и x k+1 (k = 0, 1, …,n-2) и, если xk > x k+1, то они переставляются; в результате наибольший элемент окажется на своем месте в конце массива; затем этот метод применяется ко всем элементам, кроме последнего, и т.д.

c) сортировка вставками: пусть первые k элементов массива (от 0 до
k-1) уже упорядочены по неубыванию; тогда берется xk и рaзмещается среди первых k элементов так, чтобы упорядоченными оказались уже k+1 первых элементов; этот метод повторяется при k от 1 до n-1.

 

5.29. Описать функцию, определяющую индекс первого элемента целочисленного массива из n элементов, значение которого равно заданному числу x. Если такого элемента в массиве нет, то считать номер равным –1. Элементы массива упорядочены по возрастанию; использовать метод двоичного (бинарного) поиска.

 

5.30. Программа. Описать функцию f(a, n, p), определяющую, чередуются ли положительные и отрицательные элементы в целочисленном массиве a из n элементов и вычисляющую целочисленное значение p. Если элементы чередуются, то p - это сумма положительных элементов, иначе p - это произведение отрицательных элементов. С помощью этой функции провести анализ целочисленного массива x [50].

 

5.31. Программа. Описать функцию f(a, n, p), определяющую, упорядочены ли строго по возрастанию элементы в целочисленном массиве a из n элементов, и вычисляющую целочисленное значение p. Если элементы упорядочены, то p - это произведение разностей рядом стоящих элементов, иначе p - это количество нарушений порядка в массиве a. С помощью этой функции провести анализ целочисленного массива b [60].

 

5.32. Программа. Описать функцию f (s, n, x), определяющую, какой символ чаще других встречается в строке s и сколько раз он в нее входит. Если таких символов несколько, то взять первый из них по алфавиту. С помощью этой функции провести анализ строки str.

 

5.33. Программа. Описать функцию f(s, n, x), определяющую, какой символ реже других (но не нуль раз) встречается в строке s и сколько раз он в нее входит. Если таких символов несколько, то взять первый из них по алфавиту. С помощью этой функции провести анализ строки str.

 

5.34. Программа. Для целочисленного массива а, содержащего n элементов, описать функцию f(a, n, last, k, nlast), определяющую last - значение последнего из элементов массива а, значение которого принадлежит диапазону
[-k, k], и nlast - индекс этого элемента. С помощью этой функции вычислить соответствующие значения last и nlast для целочисленных массивов x[20] и y[30].

 

5.35. Программа. Для вещественного массива а, содержащего n элементов, описать функцию G, определяющую значения максимального и минимального элементов этого массива. С помощью этой функции для вещественных массивов x[25] и y[40] вычислить соответствующие значения.

 

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

Например, abcdefgh => acegbdfh, vwxyz => vxzwy.

 

5.37. Описать функцию, которая в заданной строке меняет местами ее первую и вторую половины.

Например, abcdefgh => efghabcd, vwxyz => yzxvw.

 

5.38. Описать функцию, осуществляющую циклический сдвиг на n позиций вправо элементов целочисленного массива, содержащего m элементов (n<m).

5.39. Описать функцию, осуществляющую циклический сдвиг на n позиций влево элементов целочисленного массива, содержащего m элементов (n<m).

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

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

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

 

 

СТРУКТУРЫ, ОБЪЕДИНЕНИЯ

 

Основные сведения

 

6.1. Верны ли следующие утверждения:

a) описание структуры начинается с ключевого слова struct и содержит список объявлений членов структуры, заключенный в фигурные скобки;

b) за словом struct должен следовать идентификатор, называемый тегом структуры;

c) тег структуры используется в качестве имени типа при описании переменных;

d) имена членов структуры могут совпадать с именами переменных в той же области видимости;

e) имя тега структуры может совпадать с именами переменных в той же области видимости;

f) имя тега структуры может совпадать с именами членов этой структуры;

g) имена членов разных структур могут совпадать;

h) за описанием структуры (после правой закрывающей фигурной скобки) обязательно должен следовать список переменных;

i) переменные x, y, z разных типов

 

1) struct s { int a; float f; } x, y; 2) typedef struct { int a; float f;} s;

struct s z; s x, y;

struct { int a; float f; } z;

 

3) struct s { int a; float f; }; 4) struct s { int a; float f; };

typedef struct s new_s; typedef struct s s1;

struct s x; new_s y, z; typedef struct s s2;

s1 x, y; s2 z;

 

j) переменные x, y, z одного типа

 

1) struct { int a; float f; } x, y; 2) struct { int a; float f; } x, y;

struct { int a; float f; } z; struct { float f; int a; } z;

 

k) для доступа к членам структуры используется операция. (точка);

l) структуры не могут быть вложенными;

m) структурную переменную при ее описании можно инициализировать списком константных выражений, заключенным в фигурные скобки;

 

6.2. Каким образом в Си определяется эквивалентность типов? Какая эквивалентность типов рассматривается: структурная или именная? Чем они отличаются?

 

6.3. Описать в виде структуры следующие понятия:

a) дата (число, месяц, год);

b) адрес (страна, город, улица, дом, квартира);

c) треугольник (две стороны и угол между ними);

d) окружность (радиус и центр);

e) расписание занятий студента 209 группы факультета ВМК (день недели, предметы (с указанием – лекции или семинары), часы занятий, аудитория, фамилия преподавателя)

f) результаты проверки контрольной работы (номер группы, номер контрольной работы, тема, 25 строчек с полями: фамилия студента, вариант, информация о каждой из пяти задач (ее номер, оценка за ее решение, характеристика ошибок), итоговая оценка студента за эту контрольную работу.

 

6.4. Используя определенный в задаче 6.3 тип, описать переменную этого типа и присвоить ей значение:

a) дата – 16 ноября 1999 года;

b) адрес – Россия, Москва, Ильинка, дом 3, кв. 34;

c) треугольник – 5, 6.7, 35°;

d) окружность – радиус 4.567, центр (1.4, 5.6);

e) расписание занятий студента 209 группы факультета ВМК – понедельник, математический анализ (лекция) –1 пара, П-12, Ломов И.С., математический анализ (семинар) – 2 пара, 706, Григорьев Е.А., программирование (семинар) – 3 пара, 713, Пильщиков В.Н.

 

6.5. Что напечатает программа?

#include <stdio.h>

main()

{ struct data1 { char c[4]; char *s; } d1 = { "abc", "def" };

struct data2 { char * cp; struct data1 inf; } d2 = { "ghi", { "jkl", "mno"} };

printf("d1.c[0]=%c *d1.s=%c\n", d1.c[0], *d1.s);

printf("d1.c=%s d1.s=%s\n", d1.c, d1.s);

printf("d2.cp=%s d2.inf.s=%s\n", d2.cp, d2.inf.s);

printf("++d2.cp=%s ++d2.inf.s=%s\n", ++d2.cp, ++d2.inf.s);

}

 

6.6. Верны ли следующие утверждения:

a) описание объединения начинается с ключевого слова union и содержит список объявлений членов объединения, заключенный в фигурные скобки;

b) каждый член объединения располагается в памяти с одного и того же адреса; объем памяти для каждого члена выделяется в соответствии с его размером;

c) для каждого из членов объединения выделяется одна и та же область памяти;

d) все проблемы, связанные с выравниванием, решает компилятор;

e) в каждый момент времени объединение может содержать значение только одного из его членов;

f) все операции, применимые к структурам, применимы и к объединениям;

g) «рассогласованность» при работе с активным вариантом объединения контролируется компилятором.

 

6.7. Можно ли в Си создать аналог вариантных записей Паскаля?

 

6.8. Описать тип, с помощью которого можно организовать хранение данных о различных видах транспорта: грузовиках, автобусах, легковых автомобилях и мотоциклах. Для каждого вида транспорта имеются как общие характеристики (владелец, год производства и модель), так и индивидуальные (для грузовиков - число осей, грузоподъемность, для автобусов - число мест для пассажиров, для легковых автомобилей - число дверей (2 или 4), для мотоциклов - тип двигателя (двух- или четырехтактный)).

 



Поделиться:


Последнее изменение этой страницы: 2017-02-05; просмотров: 418; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.141.35.60 (0.34 с.)