programing

printf()가 있는 문자열 중심 맞추기

telebox 2023. 10. 9. 22:29
반응형

printf()가 있는 문자열 중심 맞추기

기본적으로,printf()문자열을 오른쪽으로 정렬하는 것 같습니다.

printf("%10s %20s %20s\n", "col1", "col2", "col3");
/*       col1                 col2                 col3 */

텍스트를 다음과 같이 왼쪽으로 정렬할 수도 있습니다.

printf("%-10s %-20s %-20s", "col1", "col2", "col3");

텍스트 가운데로 빠르게 이동할 수 있는 방법이 있습니까?아니면 문자열을 다음과 같이 바꾸는 함수를 써야 하나요?test안으로(space)(space)test(space)(space)그 열에 대한 텍스트 너비가 8이면?

printf 자체로는 트릭을 수행할 수 없지만 인수에서 읽어 너비를 지정하는 "indirect" 너비를 사용하여 재생할 수 있습니다.한번 해보자구요 (좋아요, 완벽하진 않아요)

void f(char *s)
{
        printf("---%*s%*s---\n",10+strlen(s)/2,s,10-strlen(s)/2,"");
}
int main(int argc, char **argv)
{
        f("uno");
        f("quattro");
        return 0;
}

@GiuseppeGuerrini의 것은 인쇄 형식 지정자를 사용하는 방법을 제안하고 공백을 구분하여 도움이 되었습니다.안타깝게도 텍스트를 잘라낼 수 있습니다.

다음은 자르기 문제를 해결합니다(지정된 필드가 실제로 텍스트를 담을 수 있을 정도로 충분히 크다고 가정함).

void centerText(char *text, int fieldWidth) {
    int padlen = (fieldWidth - strlen(text)) / 2;
    printf("%*s%s%*s\n", padLen, "", text, padlen, "");
} 

거기에는 없다printf()형식 지정자를 가운데 텍스트로 지정합니다.

사용자가 원하는 기능을 제공하는 라이브러리를 찾거나 직접 기능을 작성해야 합니다.

이 문제에 대해 자체 함수를 써 볼 수 있습니다.

/**
 * Returns a sting "str" centered in string of a length width "new_length".
 * Padding is done using the specified fill character "placeholder".
 */
char *
str_center(char str[], unsigned int new_length, char placeholder)
{
    size_t str_length = strlen(str);

    // if a new length is less or equal length of the original string, returns the original string
    if (new_length <= str_length)
        return str;

    char *buffer;
    unsigned int i, total_rest_length;

    buffer = malloc(sizeof(char) * new_length);

    // length of a wrapper of the original string
    total_rest_length = new_length - str_length;

    // write a prefix to buffer
    i = 0;
    while (i < (total_rest_length / 2)) {
        buffer[i] = placeholder;
        ++i;
    }
    buffer[i + 1] = '\0';

    // write the original string
    strcat(buffer, str);

    // write a postfix to the buffer
    i += str_length;
    while (i < new_length) {
        buffer[i] = placeholder;
        ++i;
    }
    buffer[i + 1] = '\0';

    return buffer;
}

결과:

puts(str_center("A", 0, '-')); // A
puts(str_center("A", 1, '-')); // A
puts(str_center("A", 10, '-')); // ----A-----
puts(str_center("text", 10, '*')); // ***text***
puts(str_center("The C programming language", 26, '!')); // The C programming language
puts(str_center("The C programming language", 27, '!')); // The C programming language!
puts(str_center("The C programming language", 28, '!')); // !The C programming language!
puts(str_center("The C programming language", 29, '!')); // !The C programming language!!
puts(str_center("The C programming language", 30, '!')); // !!The C programming language!!
puts(str_center("The C programming language", 31, '!')); // !!The C programming language!!!

두 가지 해결책이 있는데, 첫 번째는 매크로를 printf에 배치하여 위와 유사한 것이고, 두 번째는 커스텀 매크로로 snprintf를 통해 미리 포맷된 문자열의 길이를 계산한 후 printf 함수를 호출하여 출력하는 것입니다.

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

#define LEFT(str, w) \
    ({int m = w + strlen(str); m % 2 ? (m + 1) / 2 : m / 2;})

#define RIGHT(str, w) \
({ int m = w - strlen(str); m % 2 ? (m - 1) / 2 : m / 2; })

#define STR_CENTER(str, width) \
    LEFT(str, width), str, RIGHT(str, width), ""

#define PRINTF_CENTER(width, start, fmt, end, ...) ({ \
    int n = snprintf(NULL, 0, fmt, __VA_ARGS__);     \
    int m = width - n;                               \
    int left = m % 2 ? (m + 1) / 2 : m / 2;          \
    int right = m % 2 ? (m - 1) / 2 : m / 2;         \
    printf(start "%*s" fmt "%*s" end, left, "",      \
           __VA_ARGS__, right, "");                  \
})

#define MYFORMAT_CENTER(width, fmt, ...)  \
    PRINTF_CENTER(40, "[", fmt  , "]\n", __VA_ARGS__)

int main(int argc, char const *argv[])
{
    printf("%*s%*s\n\n", STR_CENTER("--- Hello World ---", 40));
    printf("[%*s%*s]\n", STR_CENTER("I am okay today", 40));
    
    MYFORMAT_CENTER(40, "%d, e is %f", 1, 2.71828);
    MYFORMAT_CENTER(40, "%d, pi is %f", 2, 3.1415926);
    MYFORMAT_CENTER(40, "%s %d.", "This is such a long string that it exceeds the given size:", 40);

    return 0;
}

출력:

           --- Hello World ---

[             I am okay today            ]
[            1, e is 2.718280            ]
[            2, pi is 3.141593           ]
[           This is such a long string that it exceeds the given size: 40.           ]

printf로 연속으로 테이블 헤더의 중심을 잡으려고 하는 비슷한 문제를 처리한 후에 2센트를 떨어뜨릴 것입니다.

다음 매크로는 텍스트 앞/뒤에 인쇄해야 하며 텍스트 길이에 관계없이 정렬됩니다.홀수 길이의 문자열이 있는 경우(정상적인 분할로 인해 공백이 발생하므로) 정렬이 필요하지 않습니다.따라서 종합적인 조사가 필요하며, 이것이 바로 이 문제를 해결하는 우아한 방법이라고 생각합니다.

#define CALC_CENTER_POSITION_PREV(WIDTH, STR) (((WIDTH + ((int)strlen(STR))) % 2) \
       ? ((WIDTH + ((int)strlen(STR)) + 1)/2) : ((WIDTH + ((int)strlen(STR)))/2))
#define CALC_CENTER_POSITION_POST(WIDTH, STR) (((WIDTH - ((int)strlen(STR))) % 2) \
       ? ((WIDTH - ((int)strlen(STR)) - 1)/2) : ((WIDTH - ((int)strlen(STR)))/2))

사용 예:

printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
                , "Header"
                , CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");

예, "test" 등을 반환하는 함수를 직접 작성해야 합니다.

printf("%s %s %s", center("col1", 10), center("col2", 20), center("col3", 20));

또는 다음과 같은 center_print 함수가 있습니다.

void center_print(const char *s, int width)
{
        int length = strlen(s);
        int i;
        for (i=0; i<=(width-length)/2; i++) {
                fputs(" ", stdout);
        }
        fputs(s, stdout);
        i += length;
        for (; i<=width; i++) {
                fputs(" ", stdout);
        }
}

위의 PADYMKO 기능을 좀 더 콤팩트하게 변형한 것(메모리 누수는 여전):

char *str_center(char str[], unsigned int new_length, char placeholder)
{
    size_t str_length = strlen(str);
    char *buffer;
    /*------------------------------------------------------------------
     * If a new length is less or equal length of the original string, 
     * returns the original string 
     *------------------------------------------------------------------*/
    if (new_length <= str_length)
    {
        return(str);
    }
    buffer = malloc(sizeof(char) * (new_length + 1));
    memset(buffer, placeholder, new_length);
    buffer[new_length] = '\0';
    bcopy(str, buffer + (( new_length - str_length) / 2), str_length);
    return(buffer);
}

이렇게 하면 새로 할당된 버퍼 전체가 패딩 문자로 설정되고 null로 종료된 다음 버퍼 중간에 중심이 될 문자열을 드롭합니다. 루프가 없거나 복사할 위치를 추적할 수 없습니다.

이 이를 수 있기를 a.printf()이 GNU clib면,다를 할 수 .printf()문자열의 중심을 맞추기 위해 사용자 자신의 변환 지정자와 함께.하여 변환 추가register_printf_function(). 문서를 보려면 여기를 참조하십시오. https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html 다른 답변에서는 중앙에서 문자열을 수동으로 인쇄하는 방법에 대한 솔루션을 이미 제공하고 있으며, 이는 자신의 변환 지정자를 사용할 때에도 여전히 필요합니다.

다음 두 가지 옵션 중 하나를 사용할 수 있습니다.

char name[] = "Name1";

//Option One
printf("%*s", 40+strlen(name)/2, name, 40-strlen(name)/2, "");
puts("");//skip one line
//Option two
printf("%*s", 40+strlen("Name2")/2, "Name2", 40-strlen("Name2")/2, "");

출력은 다음과 같습니다.

1 1()
름2데)

언급URL : https://stackoverflow.com/questions/2461667/centering-strings-with-printf

반응형