S
slashdotcommacolon
Hello, I'm working on the exercises from k&r, exercise 5-13 is to
implement a simple replacement for the unix tail command. The brief
says it should be able to cope no matter how unreasonable the input and
should make best use of availbale storage (I suppose it means dont just
declare a big char array).
I have made a solution that seems to be basically working (tail -1
doesnt work, I'll try to fix that later), but I'm having trouble
free'ing allocated memory, if i add the call to free() where i thought
it should go my c library kills it (gnu c library) as it detects an
error.
If I just dont free the memory, it works, but I suppose that is bad
form.
I have added a comment where I thought I should be using free(), please
help me understand why this happens, as I am having trouble visualising
why it doesnt work.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHUNK_SIZE 256
char *getline(void);
void writeline(const char *line);
int main(int argc, char **argv)
{
int nlines = 10, end = 0, start = 1;
int i, cnt = 0;
char **linev, *line;
/* find number of lines required */
if (argc > 1 && *argv[1] == '-')
nlines = strtol(argv[1]+1, NULL, 10);
/* allocate space for nlines pointers */
if ((linev = malloc(sizeof (char *) * nlines)) == NULL)
return 1;
/* put each line into the last element of linev */
while ((line = getline()) != NULL) {
linev[end = (end + 1 == nlines) ? 0 : (end + 1)] = line;
if (++cnt >= nlines) {
/* this is where i would like to free(linev[start]); */
start = (start + 1 == nlines) ? 0 : (start + 1);
}
}
/* EOF received, print lines */
/* for nlines, or number of lines received if < nlines */
for (i = (cnt < nlines) ? cnt : nlines; i; i--) {
writeline(linev[start]);
free(linev[start]);
start = (start + 1 == nlines) ? 0 : (start + 1);
}
free (linev);
return 0;
}
char *getline(void)
{
char *line;
int c, n = 0;
if ((line = (char *) malloc(CHUNK_SIZE)) == NULL)
return line;
while ((c = getchar()) != EOF) {
if ((line[n++] = c) == '\n')
break;
if (CHUNK_SIZE - (n % CHUNK_SIZE) <= 2)
if ((line = (char *) realloc(line, ((n / CHUNK_SIZE + 1) *
CHUNK_SIZE) * sizeof (char))) == NULL)
return line;
}
line[n+1] = '\0';
if (n == 0)
free(line);
return (n) ? line : NULL;
}
void writeline(const char *line)
{
int i = 0;
for (i = strlen(line); i > 0; i--)
putchar (*(line++));
}
implement a simple replacement for the unix tail command. The brief
says it should be able to cope no matter how unreasonable the input and
should make best use of availbale storage (I suppose it means dont just
declare a big char array).
I have made a solution that seems to be basically working (tail -1
doesnt work, I'll try to fix that later), but I'm having trouble
free'ing allocated memory, if i add the call to free() where i thought
it should go my c library kills it (gnu c library) as it detects an
error.
If I just dont free the memory, it works, but I suppose that is bad
form.
I have added a comment where I thought I should be using free(), please
help me understand why this happens, as I am having trouble visualising
why it doesnt work.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHUNK_SIZE 256
char *getline(void);
void writeline(const char *line);
int main(int argc, char **argv)
{
int nlines = 10, end = 0, start = 1;
int i, cnt = 0;
char **linev, *line;
/* find number of lines required */
if (argc > 1 && *argv[1] == '-')
nlines = strtol(argv[1]+1, NULL, 10);
/* allocate space for nlines pointers */
if ((linev = malloc(sizeof (char *) * nlines)) == NULL)
return 1;
/* put each line into the last element of linev */
while ((line = getline()) != NULL) {
linev[end = (end + 1 == nlines) ? 0 : (end + 1)] = line;
if (++cnt >= nlines) {
/* this is where i would like to free(linev[start]); */
start = (start + 1 == nlines) ? 0 : (start + 1);
}
}
/* EOF received, print lines */
/* for nlines, or number of lines received if < nlines */
for (i = (cnt < nlines) ? cnt : nlines; i; i--) {
writeline(linev[start]);
free(linev[start]);
start = (start + 1 == nlines) ? 0 : (start + 1);
}
free (linev);
return 0;
}
char *getline(void)
{
char *line;
int c, n = 0;
if ((line = (char *) malloc(CHUNK_SIZE)) == NULL)
return line;
while ((c = getchar()) != EOF) {
if ((line[n++] = c) == '\n')
break;
if (CHUNK_SIZE - (n % CHUNK_SIZE) <= 2)
if ((line = (char *) realloc(line, ((n / CHUNK_SIZE + 1) *
CHUNK_SIZE) * sizeof (char))) == NULL)
return line;
}
line[n+1] = '\0';
if (n == 0)
free(line);
return (n) ? line : NULL;
}
void writeline(const char *line)
{
int i = 0;
for (i = strlen(line); i > 0; i--)
putchar (*(line++));
}