Skip to content

Bug of Exercise 1-21 #84

@ChenZhongPu

Description

@ChenZhongPu

entab.c is buggy.

For example, given the input is FOUR blanks, [entab.c] fails because the expected output is FOUR blanks but the actual is nothing. Another example, suppose the input is TWO blanks and then followed one tab, the expected output is ONE tab, but the actual is not.

The correct version:

#include <stdio.h>

// Define how many columns a tab character represents.
// The standard is often 8, but 4 is also common.
#define TAB_WIDTH 8

int main() {
  int c;
  int column = 0;      // Tracks the current cursor position (column number)
  int space_count = 0; // Counts total consecutive whitespace (spaces and tabs)

  while ((c = getchar()) != EOF) {
    if (c == ' ') {
      // If it's a space, just count it for now.
      space_count++;
    } else if (c == '\t') {
      // If it's a tab, calculate how many spaces it represents
      // at the current position and add that to our count.
      space_count += TAB_WIDTH - ((column + space_count) % TAB_WIDTH);
    } else {
      // If it's a non-whitespace character, it's time to print
      // the buffered whitespace in the most efficient way.

      // This loop flushes the space buffer.
      while (space_count > 0) {
        // Calculate how many character positions are left until the next tab
        // stop.
        int distance_to_next_stop = TAB_WIDTH - (column % TAB_WIDTH);

        // If the number of buffered spaces is enough to reach or cross
        // the next tab stop, we can print a tab.
        if (space_count >= distance_to_next_stop) {
          putchar('\t');
          // Advance the column to the next tab stop.
          column += distance_to_next_stop;
          // Decrement our space counter by the number of spaces this tab
          // replaced.
          space_count -= distance_to_next_stop;
        } else {
          // If we don't have enough spaces to justify a tab,
          // we must print the remaining ones as individual spaces.
          putchar(' ');
          column++;
          space_count--;
        }
      }

      // After flushing the spaces, print the actual character that we read.
      if (c == '\n') {
        putchar(c);
        column = 0; // Reset column to 0 for the new line.
      } else {
        // For any other character, just print it and advance the column by one.
        putchar(c);
        column++;
      }
    }
  }

  // Important: Don't forget to flush any trailing spaces at the end of the
  // file. This part is identical to the flushing logic above.
  while (space_count > 0) {
    int distance_to_next_stop = TAB_WIDTH - (column % TAB_WIDTH);
    if (space_count >= distance_to_next_stop) {
      putchar('\t');
      column += distance_to_next_stop;
      space_count -= distance_to_next_stop;
    } else {
      putchar(' ');
      column++;
      space_count--;
    }
  }

  return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions