views:

53

answers:

2
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define TAB_STOP 8
/* replaces tabs from input with the proper amount of blank spots */
int Detab()
{
     int c, x;
     int column;
     x = column = 0;

     while((c=getchar())!=EOF)
     {
        if(c == '\n') /* reseting counter if newline */
        {
            putchar(c);
            return 1;
        }
        else if(c!='\t')  /* column counts places to tab spot */
        { 
             putchar(c);
             column++; 

             if(column == TAB_STOP) 
             column = 0;
        }
        else /* tab */
        {
           for(x=0; x<TAB_STOP - column; x++)
           putchar('_');

           column = 0;
        } 
     }
     return 0;
}

#define MAX_ARGUMENTS 100
int main(int argc, char *argv[])
{
     int i, val = 0;
     int nums[MAX_ARGUMENTS];
     int x = 0;

     for(i = 1; i < argc; i++) {

           while(isdigit(*argv[i])) {
             val = val * 10 + *argv[i] - '0';
             *++argv[i];
           }

           if(x > MAX_ARGUMENTS - 1) 
              return 0;

           nums[x++] = val;
           nums[x] = '\0';
           val = 0;
     }

     while(Detab(nums));

     printf("Press any key to continue.\n");
     getchar();
     return 0;
}

In main i put all the arguments(numbers) inside nums array and then pass it to detab. So now im interested what would be the smart way to edit detab so it works. I'm still trying to figure out for a working pseudocode but i dont really know.

The way i tought it should work is: if arguments are 5, 8, 10 then a tab inside first 4 characters leads to position 5, in 5 - 7th char leads to pos 8 etc. In case of a newline, the arguments start all over again from the begining.

A: 

The most common way is to have Detab accept a pointer (which points to an element in an array) and the length of that array:

int Detab(int* data, int len); // access data[0] through data[len - 1]

Call it like so:

void example() {
  int array[] = {5, 8, 10};
  Detab(array, 3);
  // or:
  Detab(array, sizeof array / sizeof *array); // second parameter evaluates to 3
                                              // without using a magic constant
}

Here's some pseudocode for expanding tabs:

def expandtabs_in_line(line, tabstops, default, space):
  result = ""
  for c in line:
    if c != "\t":
      result += c
    else:
      for stop in tabstops:
        if stop > len(result):
          result += space * (stop - len(result))
          break
      else:
        result += space * (default - (len(result) % default))
  return result

def expandtabs(lines, tabstops=[], default=8):
  for line in lines:
    yield expandtabs_in_line(line, tabstops, default, " ")

Try it out at codepad.

Roger Pate
Size, forgot about that... thanks!
Tool
Could you translate this into C? Ive never really worked in Python, i cant really translate that... That code also uses a getline function, right? Also, what is len(result)?
Tool
You asked for pseudocode, and "Python is executable pseudocode", so I used it. :) This code takes an array of lines and iterates over it (`for .. in ..`), transforming each line (in the separate function) and returning it (the yield is a special type of return). `len()` is the length function, and `len(result)` is the current length of result.
Roger Pate
Additionally, in the linked code I'm taking a multiline string literal and splitting it by newlines (which gives a list of strings, one per line), then I call expandtabs, and finally construct a string separated by newlines (`"\n".join`) of the results from expandtabs. I highly encourage you to play with that code on codepad, modifying it, etc.; it should be correct, I don't think I've missed any edge cases.
Roger Pate
A: 
char *spaces(int n)
{
     char *s = "";
     char *p = s;
     while(--n) {
       s = " ";
       s++;
     }

     return p;
}
char *expand_tabs_in_line(char *line, int *tabstops, int default_tab_stop)
{
    char *result = "";
    while(*line)
    {
        if(*line != '\t')
           result += *line;

        else {
             if(*tabstops) {
                 if(*tabstops > strlen(result)) 
                    result +=  *(spaces(*tabstops - strlen(result)));
                 else
                    result += *(spaces(default_tab_stop - (strlen(result) % default_tab_stop)));

                 if(!*tabstops)
                   tabstops++;
             }
        }
        line++;
    }
    return result;
}

Something like this?

Tool