char tmp;
if(n <= 1) /* нечего инвертировать */
return;
tmp = s[0]; /* спасти */
shiftLeft(s, n); /* сдвинуть */
s[n-1] = tmp; /* переместить */
reverse(s, n-1); /* инвертировать начало */
}
/* ВТОРАЯ ВЕРСИЯ нерекурсивна. Рекурсия заменена циклом.
Длина начала массива, которую надо инвертировать,
вынесена на переменную length.
*/
void reverse1(char s[], int n){
char tmp;
int length;
for(length=n; length > 1; --length){
tmp = s[0];
shiftLeft(s, length);
s[length-1] = tmp;
}
}
char testString[] = "abcdefghijklmnopqrstuvwxyz";
/* Если не задать размер массива, он будет вычислен компилятором автоматически.
Он будет равен числу букв внутри "..." ПЛЮС одна ячейка для невидимого
символа '\0' на конце.
В данном случае это 27.
*/
void main(){
int len;
len = strlen(testString);
/* вычислить длину строки: 26 ('\0' на конце не считается) */
printf("Строка для теста: \"%s\", ее длина %d\n",
testString, len);
/* Обратите внимание на два момента:
- строку (массив char) следует печатать по формату %s
- чтобы внутри "..." напечатать символ "
надо изобразить его как \"
А чтобы в putchar напечатать символ ' надо писать putchar('\'');
*/
/* Первая инверсия */
reverse(testString, len);
putstr("Инвертированная строка:");
putstr(testString);
/* Вторая инверсия - возвращает в исходное состояние */
reverse1(testString, len);
putstr("Инвертированная в исходное состояние строка:");
putstr(testString);
}
19_1.c
/* Еще более простой вариант решения:
просто обменивать элементы местами.
A B C D E F G H I J
J B C D E F G H I A
| | эти
J B C D E F G H I A
J I C D E F G H B A
| | потом эти
J I C D E F G H B A
J I H D E F G C B A
| | потом эти
----> <-----
J I H D E F G C B A
J I H G E F D C B A
| |
J I H G E F D C B A
| |
J I H G F E D C B A
стоп.
*/
#include
/* Обмен значений двух переменных типа char */
void swap(char *s1, char *s2){
char c;
c = *s1; *s1 = *s2; *s2 = c;
}
void reverse(char s[], int n){
int first, last;
first = 0; /* индекс первого элемента массива */
last = n-1; /* индекс последнего элемента массива */
while(first < last){ /* пока first левее last */
swap(&s[first], &s[last]);
first++; /* сдвинуть вправо */
last--; /* сдвинуть влево */
}
}
char testString[] = "abcdefghijklmnopqrstuvwxyz.";
void main(){
int len;
len = strlen(testString); /* Есть такая стандартная функция */
reverse(testString, len);
printf("Инвертированная строка: %s\n", testString);
}
19_2.c
/* Еще один вариант решения:
сформировать ответ в дополнительном массиве,
а потом скопировать его на прежнее место.
*/
#include
char testString[] = "abcdefghijklmnopqrstuvwxyz.";
/* Конструкция sizeof(массив)/sizeof(массив[0])
выдает размер массива, даже если он не был явно объявлен.
Эта конструкция применяется (чаще всего) для задания массива
с размером, равным размеру уже объявленного массива.
*/
char tempString[ sizeof(testString) / sizeof(testString[0]) ];
void reverse(char s[], int n){
int i;
/* вывернуть, результат в tempString[] */
for(i=0; i < n; i++)
tempString[n-1-i] = s[i];
tempString[n] = '\0'; /* признак конца строки */
/* скопировать на старое место */
for(i=0; i < n; i++)
s[i] = tempString[i];
s[n] = '\0'; /* признак конца строки */
}
void main(){
int len;
len = strlen(testString); /* Есть такая стандартная функция */
reverse(testString, len);
printf("Инвертированная строка: %s\n", testString);
}
19_3.c
/* Задача инвертирования массива целых чисел */
#include
int arr[] = {1, 5, 10, 15, 20, 25, 30};
int arrLen = sizeof(arr) / sizeof(arr[0]); /* размер массива */
/* Распечатка массива в строку */
void printit(int row[], int n){
int i;
for(i=0; i < n; i++){
printf("%d", row[i]);
if(i == n-1) putchar('\n');
else putchar(' ');
}
}
/* Печать отступа. Отладочная функция */
void printShift(int n){
n = arrLen - n;
while(n > 0){
printf(" ");
n--;
}
}
/* Сдвиг массива */
void shiftleft(int row[], int n){
int i;
for(i=1; i < n; i++)
row[i-1] = row[i];
}
/* Инвертирование */
void reverse(int row[], int n){
int pocket;
printShift(n); /* трассировка */
printf("CALLED reverse(row, %d)\n", n); /* трассировка */
if(n <= 1){
printShift(n); /* трассировка */
printf("return from reverse(row, %d);\n", n); /* трассировка */
return;
}
pocket = row[0];
shiftleft(row, n);
row[n-1] = pocket;
printShift(n); /* трассировка */
printit(arr, arrLen); /* трассировка */
reverse(row, n-1);
printShift(n); /* трассировка */
printf("all done; return from reverse(row, %d);\n", n); /* трассировка */
}
void main(){
reverse(arr, arrLen);
printit(arr, arrLen);
}
20.c
/* Задача: написать функцию для распечатки массива целых чисел
в виде таблицы в columns столбцов.
При этом порядок элементов должен быть таков:
0 4 8
1 5 9
2 6 10
3 7
*/
/* Пусть в массиве n элементов.
Если n < columns, то мы получаем такую ситуацию (n=2, columns=4)
0 1 пусто пусто
Поэтому
if(n < columns) columns = n;
Далее, прямоугольная таблица с columns столбцами и lines строками
может содержать максимум columns*lines элементов. Поэтому:
columns*lines >= n
Вычислим число строк.
Нам нужно минимальное целое число строк, такое что
lines >= n/columns
Такое число вычисляется по формуле
lines = (n + (columns - 1)) / columns;
где деление целочисленное.
Далее надо только вывести формулу для индекса элемента в массиве
в зависимости от номера строки (y) и столбца (x).
index(x, y) = (x * lines + y);
причем если index >= n, то ничего не выводить
*/
#include
int array[100];
void printArray(int a[], int n, int columns){
int lines; /* число строк */
int x, y; /* номер колонки, номер строки - с нуля */
int index; /* индекс элемента в массиве */
if(n < columns) columns = n;
lines = (n + (columns-1)) / columns;
/* Используем вложенные циклы: по строкам, а внутри - по столбцам */
for(y=0; y < lines; y++){
for(x=0; x < columns; x++){
index = x * lines + y;
if(index >= n) /* элемент за концом массива */
break; /* прервать строку */
/* break выводит только
из внутреннего цикла (по столбцам) */
/* сделать отступ в следующую колонку */
if(x != 0) putchar('\t');
printf("%02d|%d", index, a[index]);
/* Формат %02d заставляет печатать целое число
с использованием ДВУХ цифр, причем если
число состоит из одной цифры, то спереди
приписывается нуль.
*/
}
putchar('\n'); /* перейти к следующей строке */
}
}
void main(){
int i, cols;
/* Инициализация значений элементов массива */
for(i=0; i < 100; i++)
array[i] = i + 1;
for(cols=4; cols <= 13; cols++){
printf("\t\t* * * ТАБЛИЦА В %d СТОЛБЦОВ * * *\n", cols);
printArray(array, 77, cols);
putchar('\n');
}
}
20_1.c
#include
main(){
int x, y;
int COLUMNS = 11;
int LINES = 10;
int value;
/* цикл по строкам */
for(y=0; y < LINES; y++){
/* цикл по столбцам */
for(x=0; x < COLUMNS; x++){
/* что напечатать */
value = LINES * x + y;
/* если это не нулевой столбец, то перейти
в следующую колонку
*/
if(x > 0) putchar('\t');
/* ... и в ней напечатать значение */
printf("%d", value);
}
putchar('\n'); /* новая строка */
}
}
20_2.c
/*
elem(x, y) = LINES * x + y;
тогда
elem(0, y+1) - elem(COLUMNS-1, y) = 1 + LINES - COLUMNS*LINES;
elem(x+1, y) - elem(x, y) = LINES;
*/
#include
int A = 150; /* Количество элементов */
int COLUMNS = 7; /* Количество столбцов */
int LINES; /* Количество строк */
int value; /* Значение в текущей клетке */
int OFFSET_NEXT_COLUMN;
int OFFSET_NEXT_LINE;
/* Рисуем строку таблицы */
void line(){
int col; /* номер колонки */
for(col=0; col < COLUMNS; col++){
if(value >= A) /* отсутствующий элемент */
printf("* ");
else printf("%03d ", value);
/* Увеличение при переходе в соседнюю колонку */
value += OFFSET_NEXT_COLUMN; /* 1 */
}
/* Перейти к следующей строке */
putchar('\n');
/* Увеличение при переходе из конца одной строки к началу следующей.
Заметим, что к value уже прибавлено OFFSET_NEXT_COLUMN из точки 1,
поэтому при переходе в начало следующей строки в сумме прибавляется
OFFSET_NEXT_COLUMN + OFFSET_NEXT_LINE равное
1 - LINES*COLUMNS + LINES,
что соответствует формуле.
*/
value += OFFSET_NEXT_LINE; /* 2 */
}
int main(){
int nline; /* Номер строки */
LINES = (A + (COLUMNS - 1)) / COLUMNS;
OFFSET_NEXT_COLUMN = LINES;
OFFSET_NEXT_LINE = 1 - LINES*COLUMNS;
for(nline=0; nline < LINES; nline++)
line();
/* возврат 0 из main() означает "программа завершена успешно" */
return 0;
}
21.c
/* ДВУМЕРНЫЕ МАССИВЫ */
/*
Двумерный массив представляет собой двумерную
прямоугольную таблицу из нумерованных переменных.
Он объявляется так:
int array[LINES][COLUMNS];
А индексируется так:
array[y][x]
где 0 <= y <= LINES - 1
0 <= x <= COLUMNS - 1