1

I'm trying to read input from stdin into an array of pointers, by parsing it into lines(each pointer represents a line). When I try to print them, however, it only prints the first one. I cannot see what the problem is with the rest of them. (This is part of an exercise from K&R). Also, I am aware of the memory leak, but it does not pose a concern for me now.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXLINES 5000
char *lineptr[MAXLINES];

int readlines(char *[], int);
void writelines(char *[], int);

main(int argc, char *argv[])
{
    int i, nlines;
    
    for (i = 0; i < MAXLINES; ++i)
    {
        lineptr[i] = malloc(MAXLINES * sizeof(**lineptr));
    }
    
    nlines = readlines(lineptr, MAXLINES);
    
    writelines(lineptr, nlines);
    
    return 0;
}

int readlines(char *lineptr[], int nlines)
{
    int num;
    char *c_ptr = *lineptr;
    
    for (num = 0; (*c_ptr = getchar()) != EOF; ++c_ptr)
    {
        if (*c_ptr == '\n')
        {
            *c_ptr = '\0';
            
            c_ptr = *++lineptr;
            
            if (++num >= nlines)
            {
                return num;
            }
        }
    }
    
    *c_ptr = '\0';
    
    return num;
}

void writelines(char *lineptr[], int nlines)
{
    while (nlines--)
    {
        printf("%s\n", *lineptr++);
    }
}
2
  • Does this mean that you get only one line of output or you get many lines but they are all the same? Commented Sep 9, 2021 at 23:09
  • @CraigEstey I only get one line of output. The others start with '\0', I think. Commented Sep 9, 2021 at 23:30

1 Answer 1

1

When this line runs:

c_ptr = *++lineptr;

c_ptr is pointing to the first character of the next line. Then it goes back to the top of the loop where c_ptr is incremented. This means that the first character of the second and subsequent lines are never written to. When you then attempt to print those lines, you read whatever garbage value happens to be there. And if that value happens to be 0, you print a blank line.

Instead of a for loop, use a while loop and only increment c_ptr when you don't go to a new line. Also, move the reassignment of c_ptr to the next line after you check the line counter, otherwise you read past the end of the lineptr array.

num = 0;
while ((*c_ptr = getchar()) != EOF)
{
    if (*c_ptr == '\n')
    {
        *c_ptr = '\0';
        
        if (++num >= nlines)
        {
            return num;
        }
        c_ptr = *++lineptr;
    } else {
        ++c_ptr;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Oh, god. I just now realized this. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.