3

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;
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Abhishek
  • 79
  • 1
  • 7
  • +1 for learning by K&R. – Etheryte Nov 01 '14 at 19:56
  • But what's the problem? What is wrong about the approach? – ChiefTwoPencils Nov 01 '14 at 19:58
  • 1
    Hint: count the number of characters. – Weather Vane Nov 01 '14 at 19:59
  • 5
    BTW, I find it hilarious that with all the down voting that goes on this site,that all you have to do is use K&R, not do any research, not explain the issue, or give sample io, and get upvotes. What a joke. – ChiefTwoPencils Nov 01 '14 at 19:59
  • 1
    Your error is assuming you only get a tab-character `\t` when you at a tab-stop. Tab does not mean exactly x spaces, but 1 to x spaces, so we are at the next tab-stop, which are at positions n*x from the start of each line. – Deduplicator Nov 01 '14 at 20:01
  • If you google "symbolic parameter C" you'll find earlier SO questions. – Weather Vane Nov 01 '14 at 20:03
  • 1
    @ChiefTwoPencils The problem in this question isn't that much about a programming issue but understanding the posed question to begin with. – Etheryte Nov 01 '14 at 20:10
  • @Nit: but this is no different than posting a homework assignment. Because OP teaches themselves with K&R does not imply research, usefulness, or clarity. I'm simply saying there's an obvious lack of consistency when the post is missing basically everything that is typically desired. – ChiefTwoPencils Nov 01 '14 at 20:14
  • tab usually means 4 spaces? right – Abhishek Nov 01 '14 at 20:14
  • 4? For all the cool kids, a tab is 2 characters. I still like 4. :) – Don Branson Nov 01 '14 at 20:15
  • 4
    Think of the terminal/console as lines and columns. Suppose you have 80 columns (0-79) with special positions called "tab stops" every 8 columns (0,8,16,24,32,40,48,56,64,72). If you encounter a `\t`, it should move to the next tab stop. You're basically trying to duplicate the same effect by outputting the number of spaces necessary to move to the next tab stop. –  Nov 02 '14 at 00:22
  • 2
    `hi \tcrazy\t world` should print `hi `, putting you in column 3. Then print 5 spaces for the tab (`TAB - column % TAB`) to move to column 8, which is the next tab stop. Then print `crazy`, putting you in column 13. Another tab moves you to column 16, so `8 - 13 % 8 = 8 - 5 = 3 spaces`. Finally you print ` world`. If you're on Linux or OS X, you can get an idea for it using the `printf` utility at the command line: `printf 'hi \tcrazy\t world\nhi crazy world\n` (my spaces count might have been incorrect a little bit there, but you can play with it yourself like I said). –  Nov 02 '14 at 00:26
  • 1
    Counting the number of characters you output will tell you which column you're in. Don't forget to count characters when you output spaces, or your column position will be incorrect, and reset the column position to 0 after each `\n` and `\r`. –  Nov 02 '14 at 00:29

5 Answers5

11

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • what is a tab stop exactly? – Abhishek Nov 01 '14 at 20:09
  • 1
    Once again, a few seconds googling would tell you what a tab stop is. – Weather Vane Nov 01 '14 at 20:11
  • 5
    @Abhishek This is related to the way the TAB key used to work on early computers and on typewriters. When you pressed TAB, the typing position or the cursor moved to the next so-called tab stop position, which could be set at equal intervals as in this exercise, or at specific spots. Let's say tab stops are set at equal intervals of 5 spaces. When you press TAB, the cursor should go to the next position divisible by 5. If you are in position 0, you go to position 5. If you are in position 7, you go to position 10, and so on. – Sergey Kalinichenko Nov 01 '14 at 20:13
  • what i have to do is like replace the space and tab with a fixed space of 5 character? eg. _______________ to ______________ ,where _ is character – Abhishek Nov 01 '14 at 20:26
  • 1
    @Abhishek No, replacing with a fixed space of 5 characters is what your program does now. Instead, it should compute how many spaces it is missing to the next position divisible by five (look at the formula in the answer) and print that many spaces. – Sergey Kalinichenko Nov 01 '14 at 20:28
  • 2
    I think the tab key *still* works that way. For example with the MS Word version I use, 14.0, 21 years after Word's inception, hitting the tab key brings the writing mark to the nearest of a sequence of evenly spaced positions. The tabulator was (and probably still is) used for tabular data or tables, hence the name, with typewriters. Many people like to indent their source code with it because it saves a few keystrokes compared to using spaces. With smarter editors which indent for you the choice has become almost irrelevant these days. Oh, and the "true" tab size is 8. – Peter - Reinstate Monica Nov 01 '14 at 20:39
4

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';
}
Joseph Tesfaye
  • 814
  • 14
  • 26
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
        }
    }
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
-1

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++;
    }
  }
}
  • 2
    This works if the tabs are in the beginning of the line. But if they follow some ordinary characters then you need to consider also the characters printed after the previous tab stop. (Simple example: In a line like "ab" the tab should be replaced by TAB_WIDTH-2 spaces, not TAB_WIDTH.) – tzp Apr 13 '22 at 14:57
-1

why so complicated stuffs..just do this

#include <stdio.h>

int main()
{
        int c, tab=6, count=0;
        while((c=getchar())!=EOF)
        {
                count++;
                if (c=='\t')
                {
                        for (int i=count; i%(tab+1)!=0; i++) putchar(' ');
                }
                else putchar(c);
                if(c=='\n') count=0;
        }
}
lynx
  • 1