Why does this program in Dennis Ritchie's "The C Programming Language" not work?

Viewed 193

I'm starting to learn C and came across the following program in Dennis Ritchie's The C Programming Language (2nd edition):

#include <stdio.h>
#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

int main()
{
    int len;
    int max;
    char line[MAXLINE];    /* current input line */
    char longest[MAXLINE]; /* longest line saved here */

    max = 0;

    while ((len = getline(line, MAXLINE)) > 0)
    {
        if (len > max)
        {
            max = len;
            copy(longest, line);
        }
    }
    if (max > 0)
        printf("%s", longest);
    return 0;
}

int getline(char s[], int lim)
{
    int c, i;

    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
        s[i] = c;
    if (c == '\n')
    {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

void copy(char to[], char from[])
{
    int i;

    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

When I run this program exactly as is, it does not compile because there are conflicting definitions of getline. It turns out there is a getline in stdio.h, and that's where the conflict comes from. I assume this is non-standard or was added to the library after the book was published. In any case, that error was easily fixed by simply changing the name of the function to getLine.

After making that change, the program compiles but never actually completes. What I did notice is that getLine adds both a newline character and a null terminator (\0) to the character array s, and the value it returns, while it is meant to be the length of the character array, is actually that length + 1. Modifying the function to return i - 1 instead of i fixes the issue.

My question is: why does it fix the issue? I doubt that it's a typo, but maybe that's possible? Or could it be a compiler issue? Do some compilers count a null terminator as a character (i.e. to be included in the length of the character array) while others don't?

I should also say that I'm using an M1 MacBook, so I guess it's possible that the code translates to different machine code which creates different results?

EDIT:

The following is the modified code that works for me:

#include <stdio.h>
#define MAXLINE 1000

int getLine(char line[], int maxline);
void copy(char to[], char from[]);

int main()
{
    int len;
    int max;
    char line[MAXLINE];    /* current input line */
    char longest[MAXLINE]; /* longest line saved here */

    max = 0;

    while ((len = getLine(line, MAXLINE)) > 0)
    {
        if (len > max)
        {
            max = len;
            copy(longest, line);
        }
    }
    if (max > 0)
        printf("%s", longest);
    return 0;
}

int getLine(char s[], int lim)
{
    int c, i;

    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
        s[i] = c;
    if (c == '\n')
    {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i - 1;
}

void copy(char to[], char from[])
{
    int i;

    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

Also, when I say that the original code never completes, I mean that I can type anything, press enter, type some more, press enter, etc. then finally just press enter without typing (the code is checking for an array of length zero, so this is where it should print out the line of max length and exit), and the program continues running.

1 Answers

When I run this program exactly as is, it does not compile because there are conflicting definitions of getline

There is a getline function offered as an extension in some implementations, and its prototype is conflicting with the example in the book. That's most likely what's happening with you. Awesome as K&R is, it's an old book at this point and out of date in many respects.

The easiest way to get around this is to rename your getline function to getLine or get_line or something else. Alternately you'll need to undefine _GNU_SOURCE or _POSIX_C_SOURCE before including stdio.h, either in your code or on the command line.

Related