5
\$\begingroup\$

"The C Programming Language" (2nd Edition) by Kernighan and Richie has this exercise:

Write a program to print all input lines that are longer than 80 characters

I have written the following code for this exercise:

#include <stdio.h>

#define MAXLEN 1000
#define MINLEN 80

int main(void)
{
    int c;
    int index = 0;
    char line[MAXLEN];

    while ((c = getchar()) != EOF)
    {
        if (c != '\n')
        {
            line[index] = c;
            ++index;
        }

        else
        {
            line[index] = '\0';

            if (index >= MINLEN)
            {
                printf("%s\n", line);
            }
            index = 0;
        }
    }

    return 0;
}

This code is shorter than many other suggestions I found on the Internet. The code I wrote seems to be working. Am I missing something, or can I suppose that this code is fine for the exercise?

\$\endgroup\$
  • \$\begingroup\$ In the K&R book, the exercise required you to use function to achieve the result. You have not used functions in your code. \$\endgroup\$ – QuickMist Jul 10 '15 at 11:19
6
\$\begingroup\$

Just to elaborate on @ratchet freak's answer, what you need is a two-state program.

In state 1, when fewer than 80 characters have been input on a single line, store these characters in a buffer and increment a counter to reflect the number of characters that have been stored. If you receive a newline character in this state, reset the counter and start again.

As soon as this counter reaches 80, print out the contents of this buffer and switch to state 2, where characters are output as soon as they are received. There is no need to continue buffering in this state. If you receive a newline character, go back to state 1.

With this approach, there's no need to store more than 80 characters in memory (plus one byte for the terminating '\0'), and no possibility of a buffer overflow.

#include <stdio.h>
#define MIN_LENGTH 80

int main(void) {
  char buffer[MIN_LENGTH + 1];
  int c, n=0;

  while (1) {

    c = getchar();
    if (c == EOF) break;

    if (n < MIN_LENGTH) {

      /* State 1: Fewer than MIN_LENGTH characters in line */

      if (c == '\n') n = 0;
      else {
        buffer[n++] = c;
        if (n == MIN_LENGTH) {
          buffer[n] = '\0';
          printf("%s",buffer);
        }
      }
    }

    else {

      /* State 2: At least MIN_LENGTH characters in line */

      putchar(c);
      if (c == '\n') n = 0;
    }
  }

  return 0;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I just noticed that this code will print out lines of ≥80 characters, not >80 characters as per the original problem statement. But the basic principle is the same in either case. \$\endgroup\$ – r3mainer Jan 30 '15 at 10:52
  • \$\begingroup\$ Your comment and the code you provided are very inspiring for me. Thank you very much for taking the time to explain the missing points in my code. \$\endgroup\$ – c_enthusiast Jan 30 '15 at 11:15
5
\$\begingroup\$

You assume all lines are shorter than 1000 chars. This is a mistake and you never check for buffer overflows.

however you don't need to get the full line, just the 80 first characters and then if there is no newline then output the characters you have in the buffer and output all subsequent character you read until the next newline.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ If the input exceeds 1000 chars, it just stops collecting data. So I thought that would be reasonable, but I will definitely apply the check when I learn how to check for buffer overflows. (I am still studying the very first chapters of the book). Thank you very much for the suggestions. \$\endgroup\$ – c_enthusiast Jan 30 '15 at 10:20
  • \$\begingroup\$ @c_enthusiast no if input exceeds 1000 chars then you get undefined behavior because you are writing outside the allocated buffer, C does not check whether you are assigning out of bounds. This can cause all kind of weird things up to and including (according to the spec) demon coming out of your nose. \$\endgroup\$ – ratchet freak Jan 30 '15 at 10:30
  • \$\begingroup\$ This means that I should take the spec into account instead of what gcc outputs. Nobody wants to have a demon coming out of their nose, after all. Thank you very much for your suggestions. \$\endgroup\$ – c_enthusiast Jan 30 '15 at 11:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.