Я написал эту функцию, которая должна выполнять 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;
}
Это работает, но имеет некоторые странные побочные эффекты ... некоторые другие переменные меняются. Как я могу это исправить?





Аргумент, который вы передали "Hello", находится в области постоянных данных. Если вы не выделили достаточно памяти для строки char *, она переходит в другие переменные.
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
strncpy(buffer, "Hello", sizeof(buffer));
StringPadRight(buffer, 10, "0");
Обновлено: исправлено из стека в постоянную область данных.
вы слишком много копируете. Hello имеет тип char [6], но вы пытаетесь скопировать из него 1024 байта. это может только потерпеть неудачу. измените его на размер чтения "Hello" вместо второго sizeof (buffer)
strncpy (буфер, «Привет», sizeof (буфер)); уже заполняет весь буфер символом '\ 0', поэтому ваш memset () является избыточным.
@litb, strncpy: если конец исходной строки C (о которой сигнализирует нулевой символ) обнаружен до того, как было скопировано количество символов, пункт назначения дополняется нулями до тех пор, пока в него не будет записано общее количество символов.
@Chris, набор мемов после буфера - привычное дело. Я оставлю это там.
Вы должны убедиться, что во входной строке достаточно места для хранения всех символов заполнения. Попробуй это:
char hello[11] = "Hello";
StringPadRight(hello, 10, "0");
Обратите внимание, что я выделил 11 байтов для строки hello, чтобы учесть нулевой терминатор в конце.
Сама функция мне нравится. Проблема может заключаться в том, что вы не выделяете достаточно места для своей строки, чтобы добавить в нее такое количество символов. Вы могли бы избежать этой проблемы в будущем, передав аргумент size_of_string функции и убедившись, что вы не заполняете строку, когда длина почти превысит размер.
Ну ладно, имеет смысл. Итак, я сделал это:
char foo[10] = "hello";
char padded[16];
strcpy(padded, foo);
printf("%s", StringPadRight(padded, 15, " "));
Спасибо!
Было бы полезно знать, что printf выполняет заполнение для вас, используя% -10s, поскольку строка формата заполняет ввод прямо в поле длиной 10 символов
printf("|%-10s|", "Hello");
выведет
|Hello |
В этом случае символ - означает «выравнивание по левому краю», 10 означает «десять символов в поле», а s означает, что вы выравниваете строку.
Форматирование стиля Printf доступно на многих языках и имеет множество ссылок в Интернете. Вот одна из многих страниц, объясняющий флаги форматирования. Как обычно, Страница printf в Википедии тоже помогает (в основном урок истории того, насколько широко распространился printf).
Что, если вы хотите, чтобы строка была дополнена другим символом помимо пробелов? Есть ли способ сделать это с помощью printf?
Не похоже, что это возможно. (Выполнял поиск в Google. Также на странице руководства для printf, похоже, нет никаких указаний на такие функции.)
@victor - cplusplus.com/reference/clibrary/cstdio/printf - см. раздел «флаги» и раздел «ширина».
@tom - да, «результат дополняется пробелами». Так что, похоже, это невозможно. Как уже говорилось, та же информация доступна на странице руководства. Кроме того, хотя printf должен вести себя в основном одинаково, если не идентично, этот является C, а не C++.
@Виктор. Извините, я думал, вы отвечаете на мой ответ, а не на следующий вопрос Питера. Да, вы можете выбрать заполнение только 0 или "" больше ничего.
@Leys: А, ладно. :-) Не беспокойся!
@TomLeys -flag всегда заполняет пробелом справа ?. может ли он прокладывать 0 справа
Для '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]
Кажется, я продублировал еще один опубликованный ответ здесь: Набивка в принте разного размера
Одна вещь, которая определенно неверна в функции, которая формирует исходный вопрос в этом потоке, о которой я не видел, чтобы кто-то упоминал, заключается в том, что она объединяет дополнительные символы в конец строкового литерала, который был передан в качестве параметра. Это даст непредсказуемые результаты. В примере вызова функции строковый литерал «Hello» будет жестко закодирован в программе, поэтому, предположительно, конкатенация в его конце приведет к опасной перезаписи кода. Если вы хотите вернуть строку, которая больше оригинала, вам нужно убедиться, что вы выделяете ее динамически, а затем удалите ее в вызывающем коде, когда закончите.
#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
#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
#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);
}
Вы все еще передаете строковый литерал ...: P