собственно код программы:
Код:
/*
* 5.13.c
*
* Created on: 24.10.2009
* Author: egd
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXLINE 100
#define FREE_MEM \
{\
for (i = n - j; i > 0; --i)\
free(mass[i]);\
free(mass);\
exit(EXIT_FAILURE);\
}
int main(int argc, char *argv[]) {
int n, i, j = -1;
char **mass, *del, buff[MAXLINE + 1];
if (argc != 2)
n = 10;
else if (argv[1][0] == '-' && isdigit(argv[1][1]))
n = atoi(&argv[1][1]);
if ((mass = malloc(n * sizeof(char *))) == NULL) {
perror("malloc to mass");
exit(EXIT_FAILURE);
}
memset(mass, 0, sizeof(mass));
do {
if ((buff = fgets(buff, MAXLINE, stdin)) == NULL && ferror(stdin)) {
perror("fgets");
FREE_MEM
} else
++j;
if (j == n) {
free(mass[0]);
for (i = 0; i < n - 1; ++i)
mass[i] = mass[i + 1];
j = n - 1;
}
if ((mass[j] = malloc(strlen(buff) * sizeof(char))) == NULL) {
perror("calloc");
FREE_MEM
}
if (buff)
strcpy(mass[j], buff);
} while (!feof(stdin));
for (i = 0; i < n; ++i) {
printf("%s", mass[i]);
free(mass[i]);
}
free(mass);
exit(EXIT_SUCCESS);
}в кратце что она делает:
читает из stdin построчно и запносит в массив из argv[1] строк или 10 по умолчанию.
нужно вывести последние argv[1] строк (примерно тоже самое делает программа tail).
для экономии памяти, как и было написано в задании, я для каждой строки использовал минимум памяти.
если мы считали больше строк, чем может поместится в массиве - самую первую строку выталкиваем и сдвигаем все строки вверх, на освободившееся место помещаем новую.
и так далее пока не встретим EOF.
выводим что у нас получилось.
но при удалении первой строки получаем аварийное завершение с бектрейсом следующего содержания:
> ./5.13 -3 < ../5.13.c
*** glibc detected *** ./5.13: free(): invalid pointer: 0x0804b020 ***
======= Backtrace: =========
/lib/libc.so.6[0xb779e50b]
/lib/libc.so.6(cfree+0xd9)[0xb77a3049]
./5.13[0x804892c]
/lib/libc.so.6(__libc_start_main+0xfe)[0xb7747ace]
./5.13[0x8048681]
======= Memory map: ========
...
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Аварийный останов
а вот работающий код. отличие лишь в том, что для строк сразу задаем всю память, причем фиксированного размера MAXLINE
Код:
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 100
int main()
{
int n = 3;
// Выделяем память
char **buffers = malloc(sizeof(char*) * n);
int i=0;
for(i=0; i < n; ++i)
{
buffers[i] = malloc(sizeof(char)*MAXLINE);
}
// Читаем строки
for(i=0; i < n; ++i)
{
fgets(buffers[i], MAXLINE, stdin);
}
// Выводим строки
for(i=0; i < n; ++i)
{
printf("%s", buffers[i]);
}
// Освобождаем память обратно
for(i=0; i < n; ++i)
{
free(buffers[i]);
}
free(buffers);
}