C의 문자열 패딩


81

StringPadRight ( "Hello", 10, "0")-> "Hello00000"을 수행하는 함수를 작성했습니다.

char *StringPadRight(char *string, int padded_len, char *pad) {
    int len = (int) strlen(string);
    if (len >= padded_len) {
        return string;
    }
    int i;
    for (i = 0; i < padded_len - len; i++) {
        strcat(string, pad);
    }
    return string;
}

작동하지만 이상한 부작용이 있습니다. 다른 변수 중 일부는 변경됩니다. 이 문제를 어떻게 해결할 수 있습니까?

c  string  padding 

답변:


170

printf가 패딩을 수행한다는 것을 아는 것이 도움이 될 수 있습니다. % -10s를 형식 문자열로 사용하면 10 자 길이의 필드에서 입력을 바로 채 웁니다.

printf("|%-10s|", "Hello");

출력됩니다

|Hello     |

이 경우-기호는 "왼쪽 정렬"을 의미하고 10은 "필드의 10 개 문자"를 의미하며 s는 문자열을 정렬하고 있음을 의미합니다.

Printf 스타일 서식은 여러 언어로 제공되며 웹에서 많은 참조가 있습니다. 다음은 서식 플래그를 설명하는 여러 페이지 중 하나입니다 . 평소처럼 WikiPedia의 printf 페이지 도 도움이됩니다 (대부분 printf가 얼마나 널리 퍼 졌는지에 대한 역사 교훈).


4
공백 외에 다른 문자로 문자열을 채우려면 어떻게해야합니까? 이 w C의 printf를 수행하는 방법이 있습니까?
Peter Ajtai

그것은 가능하지 않은 것 같습니다. (일부 인터넷 검색을 했습니까? 또한의 man 페이지 printf에는 이러한 기능에 대한 표시가없는 것 같습니다.)
Victor Zamanian

@victor-cplusplus.com/reference/ clibrary / cstdio/ printf- 'flags'섹션 및 'width'섹션을 참조하십시오.
Tom Leys 2012

1
@tom-예, "결과는 공백으로 채워집니다". 그래서 가능하지 않은 것 같습니다. 언급했듯이 동일한 정보가 매뉴얼 페이지에서 제공됩니다. 또한, 비록 printf하지 않을 경우 동일 대부분 같은 행동해야, 이것은 이다 C가 아니라 C ++는.
Victor Zamanian 2012

1
@승리자. 죄송합니다. Peter의 후속 질문이 아니라 제 답변에 대한 답변이라고 생각했습니다. 예, 0으로 만 채우거나 ''로만 채울 수 있습니다.
Tom Leys

42

'C'의 경우 사용자 정의 패딩이 필요할 때 malloc () 또는 사전 서식 지정이 필요하지 않은 [s] printf의 대체 (더 복잡한) 사용이 있습니다.

트릭은 % s에 대해 '*'길이 지정자 (최소 및 최대)를 사용하고 패딩 문자로 최대 잠재적 길이까지 채워진 문자열을 사용하는 것입니다.

int targetStrLen = 10;           // Target output length  
const char *myString="Monkey";   // String for output 
const char *padding="#####################################################";

int padLen = targetStrLen - strlen(myString); // Calc Padding length
if(padLen < 0) padLen = 0;    // Avoid negative length

printf("[%*.*s%s]", padLen, padLen, padding, myString);  // LEFT Padding 
printf("[%s%*.*s]", myString, padLen, padLen, padding);  // RIGHT Padding 

"% *. * s"는 LEFT 또는 RIGHT 패딩에 대한 요구에 따라 "% s"앞 또는 뒤에 배치 할 수 있습니다.

[####Monkey] <-- Left padded, "%*.*s%s"
[Monkey####] <-- Right padded, "%s%*.*s"

PHP printf ( here )는 % s 형식 내에서 작은 따옴표 ( ') 다음에 사용자 정의 패딩 문자를 사용하여 사용자 정의 패딩 문자를 제공하는 기능을 지원 한다는 것을 발견했습니다 .
printf("[%'#10s]\n", $s); // use the custom padding character '#'
생성 :
[####monkey]


: 내가 어떤 사람의 여기에 대답을 게시 복제 것 같다 Varible는 printf와의 패딩 크기
J 겐슨

2

입력 문자열에 모든 패딩 문자를 담을 수있는 충분한 공간이 있는지 확인해야합니다. 이 시도:

char hello[11] = "Hello";
StringPadRight(hello, 10, "0");

hello마지막에 null 종결자를 설명하기 위해 문자열에 11 바이트를 할당했습니다 .


1

"Hello"를 전달한 인수는 상수 데이터 영역에 있습니다. char * string에 충분한 메모리를 할당하지 않으면 다른 변수에 오버런됩니다.

char buffer[1024];
memset(buffer, 0, sizeof(buffer));
strncpy(buffer, "Hello", sizeof(buffer));
StringPadRight(buffer, 10, "0");

편집 : 스택에서 상수 데이터 영역으로 수정되었습니다.


여전히 문자열 리터럴을 전달하고 있습니다 ... : P
Jeremy Ruten

너무 많이 복사하고 있습니다. Hello는 char [6] 유형이지만 1024 바이트를 복사하려고합니다. 실패 할 수 있습니다. 두 번째 sizeof (buffer) 대신 "Hello"크기를 읽도록 변경
Johannes Schaub-litb

1
strncpy (buffer, "Hello", sizeof (buffer)); 이미 전체 버퍼를 '\ 0'으로 채우므로 memset ()은 중복됩니다.
Chris Young

@litb, strncpy : num 개의 문자가 복사되기 전에 소스 C 문자열 (널 문자로 신호 됨)의 끝이 발견되면 총 num 개의 문자가 기록 될 때까지 대상이 0으로 채워집니다.
Eugene Yokota

@Chris, 버퍼 후 memset은 습관적인 것입니다. 거기에 남겨 둘 게요.
Eugene Yokota

1

오, 알겠습니다. 그래서 이렇게했습니다.

    char foo[10] = "hello";
    char padded[16];
    strcpy(padded, foo);
    printf("%s", StringPadRight(padded, 15, " "));

감사!


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

using namespace std;

int main() {
    // your code goes here
    int pi_length=11; //Total length 
    char *str1;
    const char *padding="0000000000000000000000000000000000000000";
    const char *myString="Monkey";

    int padLen = pi_length - strlen(myString); //length of padding to apply

    if(padLen < 0) padLen = 0;   

    str1= (char *)malloc(100*sizeof(char));

    sprintf(str1,"%*.*s%s", padLen, padLen, padding, myString);

    printf("%s --> %d \n",str1,strlen(str1));

    return 0;
}

무료 STR1하는 것을 잊지 마세요
피에르 - 루이 소바 쥬에게

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

int main(void) {
    char buf[BUFSIZ] = { 0 };
    char str[] = "Hello";
    char fill = '#';
    int width = 20; /* or whatever you need but less than BUFSIZ ;) */

    printf("%s%s\n", (char*)memset(buf, fill, width - strlen(str)), str);

    return 0;
}

산출:

$ gcc -Wall -ansi -pedantic padding.c
$ ./a.out 
###############Hello

0

기능 자체는 나에게 괜찮아 보입니다. 문제는 문자열에 많은 문자를 채우기에 충분한 공간을 할당하지 않았기 때문일 수 있습니다. size_of_string함수에 인수를 전달하여 나중에이 문제를 피할 수 있으며 길이가 크기보다 크려고 할 때 문자열을 채우지 않도록합니다.


0

이 스레드에서 원래 질문을 형성하는 함수에서 확실히 잘못된 한 가지는 매개 변수로 전달 된 문자열 리터럴 끝에 추가 문자를 연결한다는 것입니다. 이것은 예측할 수없는 결과를 제공합니다. 함수 호출의 예에서 문자열 리터럴 "Hello"는 프로그램에 하드 코딩되므로 아마도 그 끝에 연결하면 코드를 덮어 쓰게됩니다. 원본보다 큰 문자열을 반환하려면 동적으로 할당했는지 확인한 다음 완료되면 호출 코드에서 삭제해야합니다.


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


void padLeft(int length, char pad, char* inStr,char* outStr) {
    int minLength = length * sizeof(char);
    if (minLength < sizeof(outStr)) {
        return;
    }

    int padLen = length - strlen(inStr);
    padLen = padLen < 0 ? 0 : padLen;

    memset(outStr, 0, sizeof(outStr));
    memset(outStr, pad,padLen);
    memcpy(outStr+padLen, inStr, minLength - padLen);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.