Thread: Detab - K&R Exercise

  1. #1
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294

    Detab - K&R Exercise

    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?

    That is the exercise. Here is my attempt. I'm having some issues not printing the correct number of spaces. Can some take a look and see if they spot the issue? Thank you guys!

    Code:
    #include <stdio.h>
    
    int stringtointeger(char **str);  /* converts the argument to integer if capable */
    
    int main(int argc,char *argv[]){
        if(argc != 2)
            printf("Usage: %s n [tabstop every n columns]\n",argv[0]);
        else{
            int tabstop,k,c;
            if((tabstop = stringtointeger(argv))){
                if(tabstop > 10)
                    printf("Tab stop must be less than 10\n");
                else{
                    k = ++tabstop;
                    while((c = getchar()) != EOF){
                        if(c == '\t'){
                            for(k;k > 0;--k)
                                printf(" ");
                        }
                        else
                            printf("%c",c);
                        if(k > 0)
                            --k;
                        else
                            k = tabstop;
                    }
                }
            }
            else
                printf("Input Error. Make sure you are using an integer for argument\n");
        }
        return 0;
    }
    int stringtointeger(char **str){    /* returns int if argument is int, else returns 0 */
        int i= 0,c,t = 0;
        
        if((c = str[1][i]) < '0' || c > '9')
            return 0;
        else{
            for(i = 0;((c = str[1][i]) != '\0' && c >= '0' && c <= '9');++i)
                t = (t * 10) + (c - '0');
            if(c != '\0')
                return 0;
            return t;
        }
    }

  2. #2
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    What happens when a newline is encountered? Shouldn't you reset 'k' to 'tabstop' at that time?

    Edit: Oh, and there's a function called atoi that will convert a string to an integer for you, so you don't have to write your own. There's also strtol, which is more flexible than atoi, but unless you need that flexibility, stick with atoi.
    Last edited by christop; 05-18-2012 at 12:10 PM.

  3. #3
    Broken Box of Syntax
    Join Date
    May 2012
    Location
    Florida
    Posts
    19
    I do not know about the rest of it but I did notice this:

    After else there is not a opening braket.

    Code:
        else
                printf("Input Error. Make sure you are using an integer for argument\n");
        }
        return 0;
    But even that is just knit picking.

    Can you print out the error if any? Or atleast the output of the program?

    Another thing I noticed is:
    Code:
    else{
    int tabstop,k,c;}
    This seems to be the only time the variable tabstop is declared. I would be wrong but I believe once that "else" statement ends that variable disappears.
    Last edited by Layvian; 05-18-2012 at 12:37 PM.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    @jwroblewski44:
    Code:
    k = ++tabstop;
    You realize this code changes the value of tabstop, which is not good. Also, you simply print that many spaces for each tab, instead of "moving to the next tabstop". You need to count how many characters you have printed on that line so far, in a different variable (initialize it to 0 every time you start a new line). If you encounter a tab, you need to keep printing space character until you reach the next multiple of your tabstop variable. That's how tabstops work, they align you at columns that are a multiple of that value.

    Quote Originally Posted by christop View Post
    There's also strtol, which is more flexible than atoi, but unless you need that flexibility, stick with atoi.
    I usually prefer strol since it provides error checking. This is especially important since the input is from a user and not a "trusted source", so you must properly validate it.

    Quote Originally Posted by Layvian View Post
    After else there is not a opening braket.

    Code:
        else
                printf("Input Error. Make sure you are using an integer for argument\n");
        }
        return 0;
    That is fine, brackets are not necessary since there is only one statment in that if. The closing bracket you quoted belongs to the else that starts on line 8.
    Quote Originally Posted by Layvian View Post
    Another thing I noticed is:
    Code:
    else{
    int tabstop,k,c;}
    This seems to be the only time the variable tabstop is declared. I would be wrong but I believe once that "else" statement ends that variable disappears.
    You're right, it disappears that the end of that else statement (the one that starts on line 8), but it's not a problem since the OP doesn't try to use the variable after that point.
    Last edited by anduril462; 05-18-2012 at 12:49 PM.

  5. #5
    Broken Box of Syntax
    Join Date
    May 2012
    Location
    Florida
    Posts
    19
    That is fine, brackets are not necessary since there is only one statment in that if. The closing bracket you quoted belongs to the else that starts on line 8.

    You're right, it disappears that the end of that else statement (the one that starts on line 8), but it's not a problem since the OP doesn't try to use the variable after that point.
    That would make sense, I had copied it to a online compiler to test it out. But now that you mentioned that it makes sense.

  6. #6
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181
    I ran this programme, still not sure what the problem is... It replaces tabs with spaces whith equivalent number of spaces specified by command line argument. is what I see... Is it not supposed to do this?

    Detab - K&amp;R Exercise-capture1-jpg
    Last edited by Vespasian; 05-18-2012 at 01:07 PM.

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Vespasian View Post
    I ran this programme, still not sure what the problem is... It replaces tabs with spaces whith equivalent number of spaces specified by command line argument. is what I see... Is it not supposed to do this?
    Code:
    $ ./tab 3
                    line 1 (2 tabs)
            line 1 (2 tabs)
                    line 2 (also 2 tabs)
           line 2 (also 2 tabs)
                    line 3 (also 2 tabs)
           line 3 (also 2 tabs)
    $ ./tab 3
    a       line 1 (tab in the middle)
    a   line 1 (tab in the middle)
    a       line 2 (also 1 tab in the middle)
    a line 2 (also 1 tab in the middle)
    a       line 3 (also 1 tab in the middle)
    a    line 3 (also 1 tab in the middle)


    It does not line them up consistently (note line 1 is over-indented by 1 space in the first example). This is due to the increment issue i mentioned, and the subsequent manipulation of k, which is a bit awkward. Also, it's just way out of wack when you have tabs in the middle of a line, which is valid input, but processed incorrectly. It's not a straight "each tab char is n spaces", tab takes you to the next column that is a multiple of n.

  8. #8
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    thanks for the help guys. heres my new code.
    Code:
    /* detab */
    /* john wroblewski */
    /* jwroblewski44[at]yahoo[dot]com */
        /*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? */
    #include <stdio.h>
    
    int stringtointeger(char **str);  /* converts the argument to integer if capable */
    
    int main(int argc,char *argv[]){
        if(argc != 2)
            printf("Usage: %s n [tabstop every n columns]\n",argv[0]);  //if only one argument
        else{
            int tabstop,c;
            if((tabstop = stringtointeger(argv))){
                if(tabstop > 10)
                    printf("Tab stop must be less than 10\n");
                else{
                    int k = tabstop;
                    while((c = getchar()) != EOF){
                        if(c != '\t'){
                            printf("%c",c);
                            if(k > 0)
                                --k;
                            else if(k == 0)
                                k = tabstop;
                            if(c == '\n')
                                k = tabstop;
                        }
                        else{
                            while(k > 0){
                                printf(" ");
                                --k;
                            }
                            k = tabstop;
                        }
                    }
                }
            }
        }
        return 0;
    }
    int stringtointeger(char **str){    /* returns int if argument is int, else returns 0 */
        int i= 0,c,t = 0;
        
        if((c = str[1][i]) < '0' || c > '9')
            return 0;
        else{
            for(i = 0;((c = str[1][i]) != '\0' && c >= '0' && c <= '9');++i)
                t = (t * 10) + (c - '0');
            if(c != '\0')
                return 0;
            return t;
        }
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. An exercise from K&R
    By GL.Sam in forum C Programming
    Replies: 4
    Last Post: 05-07-2010, 09:31 AM
  2. detab---improper spacing
    By dgoodmaniii in forum C Programming
    Replies: 2
    Last Post: 11-15-2009, 08:15 AM
  3. Detab Function Loop Hang
    By neu_greg in forum C Programming
    Replies: 6
    Last Post: 01-27-2009, 05:33 PM
  4. Exercise
    By bumfluff in forum C++ Programming
    Replies: 15
    Last Post: 04-21-2006, 12:18 PM
  5. Help with K&R Exercise 1.13
    By Yannis in forum C Programming
    Replies: 2
    Last Post: 09-21-2003, 02:51 PM