0

I compiled the below program:

#include <stdio.h>

#define MAXLINE 1000    /* maximum input line length */


int getline(char line[], int maxline);

void copy(char to[], char from[]);



/* print the longest input line */
main()

{

    int len;               /* current line length */

    int max;               /* maximum length seen so far */

    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) /* there was a line */
        printf("%s", longest);
    return 0;
}

/* getline: read a line into s, return length */
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;
}

/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
    int i;

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

I tried to run it in bash shell:

gcc -o longest-line longest-line.c
./longest-line

And basically it turns into a running process (shows in result of ps aux) and the cursor just blinks. In the code, when the program is run and the getline function is called, it does 1000 iterations and the getchar is called each time to get input from the terminal in order to increment the counter if it's not end of file or newline. However, immediately there is no input in the terminal and when I start adding input and press the enter key:

$ ./longest-line
Hello World
Hello Again

Nothing happens. It's supposed to print the longest line.

JohnMerlino
  • 3,900
  • 4
  • 57
  • 89
  • You should always use `{}` with lops, if statements etc. Avoids a lot of bugs, and makes it easier for others (or yourself after a few weeks) to u derstand the code without wondering if something is intentional or a bug. – hyde Nov 24 '13 at 18:10
  • @hyde This example is from Chapter 1 of the "C Programming Language (2nd Edition)" book. I copied it directly. But while it compiles fine, I don't know how to get it to return the longest line when I give input to it after compiling. – JohnMerlino Nov 24 '13 at 18:34
  • Also, make function implementation the declaration as well, i.e. move the two functions to the top of the file and remove the forward declaration. This stops you getting linker errors and reduces the maintenance required (i.e. changing the function signature only requires changing code in one place). – Skizz Nov 24 '13 at 18:47

2 Answers2

1

The problem is that if you press '\n' from keyboard getline will always return 1 because of this statement

if (c == '\n') {
    s[i] = c;
    ++i;
}

and the line while ((len = getline(line, MAXLINE)) > 0) will always be true.

But if you use a file as standard input it will work fine because of the EOF.

If you want it to work from keyboard input press Ctrl-D or Ctrl-Z to simulate an EOF.

  • And how come in the book "C Programming Language" they don't have square brackets? I copied this directly from book. – JohnMerlino Nov 24 '13 at 18:06
  • Yes but you are keeping the second if outside the loop –  Nov 24 '13 at 18:08
  • Square brackets means `[]`... `{}` are (curly) braces. – hyde Nov 24 '13 at 18:08
  • I think the second if is supposed to be outside the loop – JohnMerlino Nov 24 '13 at 18:11
  • But won't you run the loop forever? –  Nov 24 '13 at 18:13
  • I dont think it will run forever because if getchar returns EOF or if c is a newline during first iteration where i is set to 0, then getline returns 0, and 0 is not greater than 0, so while loop exits. – JohnMerlino Nov 24 '13 at 18:16
  • Yeah For sure including second if inside curly braces was not correct, because now all it does is echo what you type in terminal. It's supposed to echo the longest line after given input of several lines. – JohnMerlino Nov 24 '13 at 18:20
  • Try now, I modified the answer. When you are pressing enter you return 1 from `getline`, so the while is always executed because 1 > 0 –  Nov 24 '13 at 18:23
  • So how do I get this program to print the longest line. That was the whole objective of this exercise of chapter 1 "C Programming Language". Maybe it's supposed to run to EOF. Maybe when EOF occurs, then the loop exits. How can i trigger EOF from bash shell? I run this program from terminal on Ubuntu. – JohnMerlino Nov 24 '13 at 18:37
  • I read your updated answer. I think incrementing the \n is important here. That way I can write multiple lines without it processing longest line. I just need to find a way to trigger EOF from terminal so it processes the lines AFTER I have already entered multiple lines. – JohnMerlino Nov 24 '13 at 18:41
  • Try now this last version –  Nov 24 '13 at 18:41
0

So, on my compiler, I had to fix a few minor issues.

  • Generally, main should be written as int main() { ... } or int main(int argc, char **argv) { ... }.
  • getline() conflicts with a builtin function that gets pulled in from the #include <stdio.h>, so I simply renamed yours to getline_custom and also renamed all the usage points.

That being said, with these minor fixes, (which may not be required under your compiler), your program works correctly.

I believe your confusion is that the program won't print the longest line until after you've sent EOF. In bash, you can do this with CTRL+D.

Example:

[12:39pm][wlynch@watermelon /tmp] ./foo
test          // Then I hit enter
longest line  // Then I hit enter
short line    // Then I hit enter
one more      // Then I hit ctrl-D
longest line  // This is output from the program.

Another Example:

If we use redirection, we can more easily see the difference between the input and output.

[12:42pm][wlynch@watermelon /tmp] printf "longest line\nshort line" | ./foo
longest line

or, using an input file:

[12:53pm][wlynch@watermelon /tmp] cat input.txt 
longest line
short line
foo
blah
[12:53pm][wlynch@watermelon /tmp] cat input.txt | ./foo
longest line

On the other hand

If, on the other hand, you'd like the program to print the current longest line after each line of input, then we would need to change the code in this program.

Here's an example of that:

int main() {
    int len = 0;           /* current line length */
    int max = 0;           /* maximum length seen so far */
    char line[MAXLINE];    /* current input line */
    char longest[MAXLINE]; /* longest line saved here */

    while ((len = getline(line, MAXLINE)) > 0) {
        if (len > max) {
            max = len;
            copy(longest, line);
        }

        printf("Current longest line: %s", longest);
    }
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • By the way, I had to rename the getline function too but didn't have to put int in front of main. – JohnMerlino Nov 24 '13 at 19:01
  • @JohnMerlino: Here is a reasonable stackoverflow post about wanting the return type for main: http://stackoverflow.com/questions/2892787/why-would-you-precede-the-main-function-in-c-with-a-data-type Note that C89 means the C standard released in 1989, C99 means the C Standard released in 1999, and C11 is the C Standard released in 2011. – Bill Lynch Nov 24 '13 at 19:33