Заповнення рядків у C


80

Я написав цю функцію, яка повинна виконувати StringPadRight ("Привіт", 10, "0") -> "Hello00000".

Це працює, але має деякі дивні побічні ефекти ... деякі інші змінні змінюються. Як я можу це виправити?

c  string  padding 

Відповіді:


173

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

буде виводити

У цьому випадку символ - означає "Вирівнювання за лівим краєм", 10 означає "Десять символів у полі", а s означає, що ви вирівнюєте рядок.

Форматування у стилі Printf доступне багатьма мовами та містить безліч посилань в Інтернеті. Ось одна із багатьох сторінок, що пояснює прапорці форматування. Як зазвичай , сторінка друку WikiPedia також може допомогти (в основному урок історії про те, як широко розповсюдився printf).


4
Що робити, якщо ви хочете, щоб рядок доповнювався іншим символом, крім пробілів? Чи є спосіб зробити це w c printf?
Peter Ajtai,

Не схоже, що це можливо. (Зробив якийсь гугл. Також на сторінці користувача для printf, схоже, немає вказівки на такі особливості.)
Віктор Заманян

@victor - cplusplus.com/reference/clibrary/cstdio/printf - див. розділи "прапори" та "ширина".
Tom Leys

1
@tom - так, "результат заповнюється пробілами". Отже, це, здається, неможливо. Як зазначалося, та сама інформація доступна на сторінці довідок. Крім того , незважаючи на те, printfповинен вести себе в основному ті ж , якщо не ідентичне, це є C, а НЕ C ++.
Віктор Замянян

1
@Victor. Вибачте, я думав, що ви відповідаєте на мою відповідь, а не на подальше запитання Пітера. Так, ви можете вибрати лише прокладку з 0 або нічим іншим.
Tom Leys

42

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

Фокус полягає у використанні специфікаторів довжини '*' (мін та макс) для% s, а також рядок, заповнений символом заповнення, до максимальної потенційної довжини.

"% *. * 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]


Здається, я продублював тут іншу опубліковану відповідь: Доповнення різних розмірів у printf
J Jorgenson

2

Ви повинні переконатися, що вхідний рядок має достатньо місця, щоб вмістити всі заповнені символи. Спробуйте це:

Зверніть увагу, що я виділив 11 байт для helloрядка для обліку нульового термінатора в кінці.


1

Аргумент, який ви передали "Привіт", знаходиться в області постійних даних. Якщо ви не виділили достатньо пам’яті для символу *, це перевизначає інші змінні.

Редагувати: виправлено зі стеку на постійну область даних.


Ви все ще передаєте строковий літерал ...: P
Джеремі Рутен

ви занадто багато копіюєте. Привіт має тип char [6], але ви намагаєтеся скопіювати з нього 1024 байти. що може тільки зазнати невдачі. змінити його на читання розміру "Привіт" замість другого розміру (буфера)
Йоханнес Шауб - litb

1
strncpy (буфер, "Привіт", sizeof (буфер)); вже заповнює весь буфер '\ 0', тому ваш memset () надлишковий.
Кріс Янг,

@litb, strncpy: Якщо кінець вихідного рядка С (який сигналізується нульовим символом) знайдено до того, як було скопійовано число символів, пункт призначення заповнюється нулями, поки в нього не буде записано загальну кількість символів.
Євген Йокота

@Chris, мемсет після буфера - звична річ. Я залишу його там.
Євген Йокота

1

О гаразд, це має сенс. Отже, я зробив це:

Дякую!


1

Не забудьте звільнити str1
Pierre-Louis Sauvage

1

Вихід:


0

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


0

Одне, що безумовно помиляється у функції, яка формує вихідне запитання в цьому потоці, про що я не бачив, щоб хтось згадував, це те, що вона об’єднує зайві символи в кінець рядкового літералу, який був переданий як параметр. Це дасть непередбачувані результати. У прикладі виклику функції, строковий літерал "Hello" буде жорстко закодований в програму, тому, імовірно, об'єднання в кінець буде небезпечно переписувати код. Якщо ви хочете повернути рядок, який перевищує оригінал, вам потрібно переконатись, що ви динамічно його розподіляєте, а потім видалите його у коді виклику, коли закінчите.


0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.