2

I'm trying to format a list of files using Terminal columns size in C, using write. I'm trying to format the output to look like the following, Without using printf or other formatting functions. enter image description here

This's what I'm getting enter image description here

here's my code

#include <stdio.h>
#include <sys/ioctl.h>  /* ioctl, TIOCGWINSZ */
#include <err.h>    /* err */
#include <fcntl.h>  /* open */
#include <string.h>
#include <unistd.h>

size_t  ft_strlen(const char *s)
{
    size_t  i;

    i = 0;
    while (s[i])
        i++;
    return (i);
}

int get_cols()
{
    struct winsize ws;
    int fd;
    int cols;

    cols = 0;
    /* Open the controlling terminal. */
    fd = open("/dev/tty", O_RDWR);
    if (fd < 0)
        err(1, "/dev/tty");

    /* Get window size of terminal. */ 
    if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
        err(1, "/dev/tty");
    close(fd);
    cols = ws.ws_col;
    return (cols);
}

void    print_item(const char *str, int num_sp)
{
    char sp = ' ';

    write(1, str, ft_strlen(str));
    while (num_sp--)
        write(1, &sp, 1);
}

int get_max_strlen(const char *list[])
{
    int len = 0;
    int i = 0;

    while (list[i])
    {
        if (ft_strlen(list[i]) > len)
            len = ft_strlen(list[i]);
        i++;
    }
    return (len);
}

void    print_list(const char *list[], int cols)
{
    int max_len = get_max_strlen(list);
    int i = 0;
    int curr_len;
    int tmp_cols = cols;

    while (list[i])
    {
        curr_len = ft_strlen(list[i]);
        if (curr_len < tmp_cols)
        {
            print_item(list[i], max_len - curr_len + 1); //+1 for space
            tmp_cols -= curr_len;
        }
        else
        {
            write(1, "\n", 1);
            tmp_cols = cols;
        }
        i++;
    }
}

int main()
{
    const char *list[] = 
    {
        "21sh", "21sh.fr.pdf", "author", "ft_auto_misc.o", "ft_auto_search.o",
        "ft_auto_utils.o", "ft_bck_i_search.o", "ft_cd.o", "ft_cmd_utils.o",
        "ft_commands.o", "ft_ctrl_c_signal_handler.o", "ft_ctrl_keyboard.o",
        "ft_ctrl_terminal.o", "ft_cut.o", "ft_echo.o", "ft_env.o", "ft_env_utils.o",
        "ft_execute.o", "ft_export.o", "ft_free.o", "ft_get_data.o", "ft_hash_table.o",
        "ft_hash_table_utils.o", "ft_here_doc.o", "ft_here_doc_utils.o", "ft_history.o",
        "ft_hist_utils.o", "ft_logical_op.o","ft_manage_buff.o", "ft_manage_hist.o", 
        "ft_manage_pipes.o", "ft_more_utils.o", "ft_parenthesis.o", "ft_parenthesis_utils.o",
        "ft_redirection.o", "ft_redirection_utils.o", "ft_signals.o", "ft_sub.o",
        "ft_term_utils.o", "ft_utils.o", "includes", "libft", "main.o", "Makefile",
        "nbproject", "README.md", "src", "TODO", 
        0
    };

    print_list(list, get_cols());
    return 0;
}

1 Answer 1

2

Your loop to print the list should look like this:

while (list[i])
{
    curr_len = ft_strlen(list[i]);
    if (curr_len > tmp_cols)
    {
        write(1, "\n", 1);
        tmp_cols = cols;
    }

    // Always print the item. Do not skip it.
    print_item(list[i], max_len - curr_len + 1); //+1 for space
    tmp_cols -= maxlen+1;  <=== Not only curr_len
    i++;
}

For each line you skipped one item as you only printed a '\n' instead of the item. "ft_env_utils.o" is missing in your output. You forgot to reduce remaining columns count by the number of padding bytes.

This should fix the incorrect column width. If printing column by column instead of row by row is also desired some extra sorting will be needed.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, somehow the last item prints extra spaces and I have changed \n to \r.
Yes, you print padding spaces for every item including the last one. To avoid this you might add some parameter to print_item indicating if it is the last item in the list.
OK, thanks I added write(1, "\r", 1); at the end of the loop to fix it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.