将文本与16个字符对齐

时间:2014-04-29 22:20:44

标签: c

我正在尝试创建一个在16 * 8屏幕上居中文本的功能(一行8行和16个字母),长度<1的部分。 16工作正常,但当我有多行时,我找不到如何解决问题,这是我的代码:

char* align_text(char* text)

    int i=0, j=0, k;
    int modulo, diff;
    int size = strlen(text);
    char space[16];
    char tmp[16];
    char tmp2[16];
    char* tmp3;

    char median[150];
    char* final;

    if(size==16)
        return text;
    else if(size<16)
    {
        diff = 16 - size;
        modulo = diff%2;
        if(modulo==0)
        {
            for(j=0;j<diff/2;j++)
                space[j] = ' ';
            space[j] = '\0';
            strcat(median, space);
            strcat(median, text);
            strcat(median, space);
        }
        else
        {
            for(j=0;j<(int)(diff/2);j++)
                space[j] = ' ';
            space[j] = '\0';
            strcat(median, space);
            strcat(median, text);
            space[j] = ' ';
            space[j+1] = '\0';
            strcat(median, space);
        }
        final = (char*)malloc(strlen(median)*sizeof(char));
        strcpy(final, median);
        return final;
    }
    else
    {
        while(text[i] != '\0')
        {

            if(text[i] == ' ')
            {
                if(strlen(tmp2)>16 && strlen(tmp)<=16)
                {
                    tmp3 = align_text(tmp);
                    if(strlen(median) == 0)
                        strcpy(median, tmp3);
                    else
                        strcat(median, tmp3);
                    free(tmp3);
                    j=0;
                    tmp2[0] = '\0';
                    i = k;
                }

                strcpy(tmp, tmp2);
                tmp2[j++]=text[i++];
                tmp2[j]='\0';
                k = i;
            }
            else
            {
                tmp2[j++]=text[i++];
                tmp2[j]='\0';
            }
        }

        if(strlen(tmp2)>16 && strlen(tmp)<=16)
        {
            tmp3 = align_text(tmp);
            if(strlen(median) == 0)
                strcpy(median, tmp3);
            else
                strcat(median, tmp3);
            free(tmp3);
        }

        j=0;
        tmp2[0] = '\0';
        i = k;

        while(text[i] != '\0' )
        {
            tmp2[j] = text[i];
            tmp3 = align_text(tmp2);
            strcat(median, tmp3);
            free(tmp3);
        }

        final = (char*)malloc(strlen(median)*sizeof(char));
        strcpy(final, median);
        return final;
    }
}

2 个答案:

答案 0 :(得分:0)

我相信经过一些测试后这会有效。我不会声称自己具有很高的优雅水平,但它干净而实用。

这里的方法是将输入作为一个以空字符结尾的文本字符串。输入字符串的副本是由于strtok用于提取每个非空字符串,strtok修改字符串。通过一次构建一行(在line缓冲区中)来管理输出,然后在该行被复制到输出时被认为已满时对该行进行居中。函数format_line将行的副本复制到必须居中的输出。如果您想要左对齐或右对齐,只需修改format_line即可。因为strtok用于拉动#34;令牌&#34;从带有空白分隔符的输入中,在输出的每个单词之间重新插入一个空格。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


static const int cols = 16;
static const int rows = 8;


void format_line(char *out_text, char line[], int col)
{
    int nspaces;

    // Back off the trailing space if there is one
    //
    if ( line[col-1] == ' ' )
        col -= 1;

    line[col] = '\0';

    // Center the text to the output buffer
    //
    nspaces = cols - col;

    memset(out_text, ' ', nspaces/2);
    out_text += nspaces/2;

    *out_text = '\0';

    strcat(out_text, line);
    out_text += strlen(line);

    memset(out_text, ' ', nspaces - nspaces/2);
    out_text += nspaces - nspaces/2;

    *out_text = '\0';
}


char *align_text(char *text)
{
    int col, row;
    char *fit_text, *ret_text;
    char *np;
    char line[cols+1];
    char *ptext;

    // Copy the input text so we don't destroy the original w/strtok
    ptext = malloc(strlen(text) + 1);
    strcpy(ptext, text);

    // Create the buffer for the output text
    ret_text = fit_text = malloc(cols * rows + 1);

    // Initialize the working line/row
    line[col = 0] = '\0';
    row = 0;

    // Parse each string in the input text with space as delimeter
    //
    for (np = strtok(ptext, " "); (np != NULL) && (row < rows); np = strtok(NULL, " "))
    {
        // If the next string fits on the current line
        //   then we'll put it there
        //
        if ((col + strlen(np)) < cols)
        {
            col += strlen(np);
            strcat(line, np);

            // Append a space delimeter if there's room
            //
            if (col < cols)
                line[col++] = ' ';

            line[col] = '\0';

            // If we hit the end of the line, copy it to the output text
            // buffer and reset the to the beginning of the working line
            //
            if (col == cols)
            {
                memcpy(fit_text, line, col);
                fit_text += cols;
                line[col = 0] = '\0';
                row += 1;
            }
        }
        else  // The next string doesn't fit on the current line
        {
            // If there is text on the current line, then
            //    space pad it, append it to the output (centered), and reset working line
            //
            if ( col > 0 )
            {
                format_line(fit_text, line, col);
                fit_text += cols;
            }

            // If the current string is longer than a line, then
            // copy over the long chunks
            //
            while ( strlen(np) >= cols )
            {
                memcpy(fit_text, np, cols);
                fit_text += cols;
                np += cols;
                row += 1;
            }

            // Copy the rest of the current string to the fresh working line
            //
            strcpy(line, np);
            col = strlen(np);
            line[col++] = ' ';
            line[col] = '\0';
            row += 1;
        }
    }

    // Copy over and center the last one
    //
    if ( (col > 0) && (row < rows) )
    {
        format_line(fit_text, line, col);
        fit_text += cols;
    }

    *fit_text = '\0';

    return ret_text;
}

int main(int argc, char *argv[])
{
    if ( argc > 1 )
    {
        printf("%s\n", align_text(argv[1]));
        printf("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\n");
    }

    return 0;
}

答案 1 :(得分:-1)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum { left, center, right } position;

int pos_calc(int width, int max_width, position pos){
    int d;
    if((d=max_width - width)< 0)
        return -1;

    switch(pos){
    case   left: return 0;
    case  right: return d;
    case center: return d/2;
    }
}

char *puton(char *buff, int width, position pos, const char *data){
    int len = strlen(data);
    int offset = pos_calc(len, width, pos);
    memset(buff, ' ', width);
    buff[width]='\0';
    memcpy(buff + offset, data, len);
    return buff;
}

char* join(char c, size_t arrsize, const char *arr[]){
    size_t i, total, len[arrsize];
    char *buff, *ret;

    for(total=i=0;i<arrsize;++i)
        total+=(len[i]=strlen(arr[i]));
    if(NULL==(ret=buff=malloc((total + arrsize)*sizeof(char))))
        return NULL;
    for(i=0;i<arrsize;++i){
        memcpy(buff, arr[i], len[i]);
        buff+=len[i];
        *buff++=c;
    }
    *--buff='\0';
    return ret;
}

char *align_text(const char *str){
    static const int row = 8;
    static const int col = 16;
    static const char *delimiter = " \t\n";

    char *text = strdup(str);
    char *words[col], *p, *cat;
    int wc, total_len, r;
    char *buff = malloc(row * col * sizeof(char) + 1);
    //memset(buff, ' ', row*col);
    //buff[row*col] = '\0';
    for(r=total_len=wc=0, p=strtok(text, delimiter); p ; p = strtok(NULL, delimiter)){
        int len = strlen(p);
        //if(len > col){...}
        words[wc++] = p;
        total_len += len;
        if(total_len  + wc - 1 > col){
            cat = join(' ', wc - 1, words);
            puton(buff + col * r++, col, center, cat);
            //if(r >= row){...}
            free(cat);
            words[0] = words[wc-1];
            wc = 1;
            total_len = len;
        }
    }
    cat = join(' ', wc, words);
    puton(buff + col * r++, col, center, cat);
    free(cat);
    free(text);
    return buff;
}

void print(const char *text, int width){
    int i;
    for(i=1;*text;++i){
        putchar(*text++);
        if(i % width == 0)
            putchar('\n');
    }
}

int main(){
    char *text = align_text("Hello how are you");
    //printf("%s", text);
    print(text, 16);
    free(text);

    return 0;
}