'K&R Exercise 1-20 The Programming Language 2nd edition

What should i do in this program. I cant understand.
The question is as : Write a program detab that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assume a fixed set of tab stops, say every n columns. Should n be a variable or a symbolic parameter?
I started by replacing the tabs ('\t') with space (' '). But i guess this is the wrong approach. please suggest ?
and btw what should n be? variable or symbolic parameter?

code so far:

#include<stdio.h>
#define TAB 5
int main() {
    int i, c;
    while((c = getchar()) != EOF) {
        if(c == '\t') {
            for(i = 0; i < TAB; ++i)
                putchar(' ');
        } else
            putchar(c);
    }
    return 0;
}

In all the questions posted for this exercise i couldn't understand the meaning.


This is my final code, please tell me if it has any problems / bugs. I think it is working as it should..
thanks to @Nit, @Chrono Kitsune , @dasblinkenlight and all the others who helped.

#include<stdio.h>
#define TAB 8
int main() {
int c, count = 0, space = 0;
while((c = getchar()) != EOF) {

    if(c == '\t') {
        space = (TAB - (count % TAB));
        while(space > 0){
            putchar(' ');
            count++;
            space--;
        }
    }
    else{
        putchar(c);
        ++count;
    }

    if(c == '\n')
        count = 0;
}
return 0;
}


Solution 1:[1]

What you are doing is not what the exercise wants you to do: rather than inserting a fixed number of spaces for each tab, you should be inserting a different number of spaces depending on how much has been printed on the line so far.

It does not matter how you take the number of spaces per tab - the way you made it a preprocessor constant is perfectly fine. However, rather than producing TAB spaces regardless of where the '\t' has been found, you program needs to count how much "regular" characters have been printed, and count how many spaces are needed when it sees '\t'.

Make a variable count for characters printed so far. Initialize it to zero, and then reset it back to zero each time you see a '\n' character. When you call putchar, also make count++.

Now when you see a tab '\t' compute how far you are form the next tab stop. The expression for that is

TAB - (count % TAB)

That is how many spaces you need to print.

This should be enough information for you to go back and fix your program - I think you need to write only five additional lines of code (not counting lines for curly braces that you would need to insert) in order to finish this exercise.

Solution 2:[2]

The first step is to understand the problem. As I read it over and over for several times at first I couldn't understand what exactly it wants me to do. It's because some concepts weren't clear or familiar to me before I searched for more information about tab. First, what is a tab and what is a tab stop exactly? A tab is a character represented by the escape sequence \t in many contexts. Just like other characters such as letters or digits, it's a character, but with special usage, so it's not a wide space or 4 or 8 spaces as it appears to be. Being displayed like a wide space or 4 or 8 spaces is just what it's designed for, which aligns each tab-delimited group of texts on multiple lines to make the region look like a table, but underneath on the level the software sees it's just a character. Tab stops are positions on the line where the cursor goes when the Tab key is pressed. These positions are fixed on the line according to the width or number of characters (or columns, all referring to the same concept) with which the Tab character is displayed. For example, on Windows Notepad the default width for Tab is 8 characters, and when you type Tab key the cursor would move behind the 8th, 16th, 24th... character. You can type 0s on the first line to see the effect more clearly:

00000000000000000000000000000000
    Ivan    Hello   World
This    is  a   table
delimited   by  tab

Now reading the problem over again it's clear to me that it's about replacing the Tab characters with spaces while maintaining the original table look. Then you can start writing your code to calculate how many spaces are needed for each Tab. Here's my complete code for this exercise:

#include <stdio.h>

#define MAX_LENGTH 1000
#define LINE_NUM 100
#define TAB_WIDTH 8

int readLine(char line[], int maxLength);
void copy(char from[], char to[]);
void detab(char line[], char result[]);

main() {
    printf("Input: \n");
    char lines[LINE_NUM][MAX_LENGTH];
    char line[MAX_LENGTH];
    char result[MAX_LENGTH];
    int lineId = 0, length = 0;
    while ((length = readLine(line, MAX_LENGTH)) != 0) {
        detab(line, result);
        copy(result, lines[lineId]);
        lineId++;
    }
    
    printf("Output: \n");
    for (int i = 0; i <= lineId; i++) {
        printf("%s\n", lines[i]);
    }
}

int readLine(char line[], int maxLength) {
    char ch;
    int length = 0;
    while ((ch = getchar()) != EOF && ch != '\n' && length < maxLength) {
        line[length] = ch;
        length++;
    }
    if (ch == '\n') {
        line[length] = '\0';
    }
    return length;
}

void copy(char from[], char to[]) {
    int i = 0;
    while (from[i] != '\0') {
        to[i] = from[i];
        i++;
    }
    to[i] = '\0';
}

void detab(char line[], char result[]) {
    int i = 0;
    char ch;
    int column = 0;
    int spaces;
    int nextTabStop;
    while ((ch = line[i++]) != '\0') {
        if (ch == '\t') {
            spaces = TAB_WIDTH - column % TAB_WIDTH;
            nextTabStop = column + spaces;
            for (; column < nextTabStop; column++) {
                result[column] = ' ';
            }
        } else {
            result[column] = ch;
            column++;
        }
    }
    result[column] = '\0';
}

Solution 3:[3]

First, try to get familiar with '\t' (TAB character) and see what happens when you print

'\t' + ','
'.' + '\t' + ','
'..' + '\t' + ','

And so on. You will see that there is a fixed number of initial '.'s in which the ',' character after '\t' is on the same position, this means that the '\t' length is not fixed, so if you try to replace it with a fixed number of ' ' characters (white spaces), the output will be different from the input.

Understanding that, your task is to create a program that replaces all '\t' characters with white spaces, so you have to calculate the number of necessary white spaces to print for each '\t' char you read. This is what I've done so far.

#include <stdio.h>
#define WSPT 8 // white spaces per tab

main () {
    int c, counter;
    counter = 0; // distance from the previous tab stop
    while((c = getchar()) != EOF) {
        if(c == '\t') {
            for(int i = 0; i < WSPT - counter; ++i) 
                putchar(' '); // print white spaces until reach the next tab stop
            counter = 0; // you are again at the start of a tab stop
        } else {
            putchar(c); 
            if(c != '\n')
                counter = (counter + 1) % WSPT; // move 1 step
            else
                counter = 0; // you are again at the start of a tab stop
        }
    }
}

Solution 4:[4]

Okay, his is actually a very simple question and I'm not sure why everyone is making it more complicated than it is. We need to simply replace tab's with the necessary number of blanks so the resulting output looks no different than if there was a tab there.

No need for a million lines of code... a few will do...

#include <stdio.h>
/* A program *detab* that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assuming a fixed set of tabstops, say every n columns */
#define TAB_WIDTH 4         // tab width on particular machine

int main()
{
int c;
int i = 0;
while((c = getchar()) != EOF) {
  if(c != '\t')
    putchar(c);
  else
    while(i < TAB_WIDTH - 1){
      putchar(' ');
      i++;
    }
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sergey Kalinichenko
Solution 2 Ivan Huang
Solution 3 Toby Speight
Solution 4 user18794491