Строка заполнения в C - PullRequest
65 голосов
/ 10 ноября 2008

Я написал эту функцию, которая должна выполнять 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;
}

Это работает, но имеет некоторые странные побочные эффекты ... некоторые другие переменные изменены. Как я могу это исправить?

Ответы [ 10 ]

139 голосов
/ 10 ноября 2008

Может быть полезно знать, что printf выполняет заполнение за вас, используя% -10s в качестве строки формата, чтобы заполнить ввод прямо в поле длиной 10 символов

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

выдаст

|Hello     |

В этом случае символ - означает «Выравнивание по левому краю», 10 означает «Десять символов в поле», а символ s означает, что вы выравниваете строку.

Форматирование в стиле Printf доступно на многих языках и имеет множество ссылок в Интернете. Вот одна из многих страниц , объясняющая флаги форматирования. Как обычно, printf-страница WikiPedia также помогает (в основном урок истории о том, как широко распечатался printf).

38 голосов
/ 16 марта 2012

Для 'C' существует альтернативное (более сложное) использование [s] printf, которое не требует каких-либо malloc () или предварительного форматирования, когда требуется пользовательское заполнение.

Хитрость в том, чтобы использовать% * спецификаторы длины (min и max) для% 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" может быть помещен перед ИЛИ после вашего "% s", в зависимости от желаемого заполнения влево или вправо.

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

Я обнаружил, что PHP printf ( здесь ) действительно поддерживает возможность давать пользовательский символ заполнения, , используя одинарную кавычку ('), за которой следует ваш пользовательский символ заполнения , в пределах формат% s.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
производит:
[####monkey]

1 голос
/ 01 августа 2016
#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;
}
1 голос
/ 10 ноября 2008

О, хорошо, имеет смысл. Итак, я сделал это:

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

Спасибо! * * 1004

1 голос
/ 10 ноября 2008

Вы должны убедиться, что во входной строке достаточно места для размещения всех символов заполнения. Попробуйте это:

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

Обратите внимание, что я выделил 11 байтов для строки hello для учета нулевого терминатора в конце.

1 голос
/ 10 ноября 2008

Аргумент, который вы передали "Hello", находится в области постоянных данных. Если вы не выделили достаточно памяти для строки char *, она переполняется другими переменными.

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

Редактировать: исправлено из стека в постоянную область данных.

0 голосов
/ 27 августа 2018
#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);
}
0 голосов
/ 08 марта 2018
#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 голосов
/ 21 января 2015

Одна вещь, которая определенно не так в функции, которая формирует исходный вопрос в этой теме, о которой я не видел упоминания, это то, что она объединяет дополнительные символы в конце строкового литерала, который был передан как параметр. Это даст непредсказуемые результаты. В примере вызова функции строковый литерал «Hello» будет жестко запрограммирован в программе, поэтому, предположительно, конкатенация в конце его будет опасно перезаписывать код. Если вы хотите вернуть строку, которая больше, чем оригинал, вам нужно убедиться, что вы выделяете ее динамически, а затем удалите ее в коде вызова, когда закончите.

0 голосов
/ 10 ноября 2008

Сама функция выглядит хорошо для меня. Проблема может заключаться в том, что вы не выделяете достаточно места для вашей строки, чтобы разместить на ней столько символов. Вы можете избежать этой проблемы в будущем, передав аргумент size_of_string в функцию и убедитесь, что вы не дополняете строку, когда длина будет больше, чем размер.

...