使用C中的终端列格式化输出

时间:2016-12-30 12:56:29

标签: c

我正在尝试使用write使用C中的终端列大小格式化文件列表。我正在尝试将输出格式化为如下所示,不使用printf或其他格式化函数。 enter image description here

这就是我所得到的 enter image description here

这是我的代码

#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 个答案:

答案 0 :(得分:2)

您打印列表的循环应如下所示:

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++;
}

对于每一行,您跳过了一个项目,因为您只打印了一个'\n'而不是该项目。输出中缺少“ft_env_utils.o”。 您忘记将剩余列数减少填充字节数。

这应该可以修复不正确的列宽。如果还希望逐列而不是逐行打印,则需要进行一些额外的排序。