Заполнение строк в C

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
82
0
165 365
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

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

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

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

Вы все еще передаете строковый литерал ...: P

Jeremy Ruten 10.11.2008 04:33

вы слишком много копируете. Hello имеет тип char [6], но вы пытаетесь скопировать из него 1024 байта. это может только потерпеть неудачу. измените его на размер чтения "Hello" вместо второго sizeof (buffer)

Johannes Schaub - litb 10.11.2008 04:52

strncpy (буфер, «Привет», sizeof (буфер)); уже заполняет весь буфер символом '\ 0', поэтому ваш memset () является избыточным.

Chris Young 10.11.2008 09:24

@litb, strncpy: если конец исходной строки C (о которой сигнализирует нулевой символ) обнаружен до того, как было скопировано количество символов, пункт назначения дополняется нулями до тех пор, пока в него не будет записано общее количество символов.

Eugene Yokota 10.11.2008 11:34

@Chris, набор мемов после буфера - привычное дело. Я оставлю это там.

Eugene Yokota 10.11.2008 11:39

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

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?

Peter Ajtai 01.10.2011 22:01

Не похоже, что это возможно. (Выполнял поиск в Google. Также на странице руководства для printf, похоже, нет никаких указаний на такие функции.)

Victor Zamanian 04.02.2012 16:54

@victor - cplusplus.com/reference/clibrary/cstdio/printf - см. раздел «флаги» и раздел «ширина».

Tom Leys 08.02.2012 02:31

@tom - да, «результат дополняется пробелами». Так что, похоже, это невозможно. Как уже говорилось, та же информация доступна на странице руководства. Кроме того, хотя printf должен вести себя в основном одинаково, если не идентично, этот является C, а не C++.

Victor Zamanian 08.02.2012 23:24

@Виктор. Извините, я думал, вы отвечаете на мой ответ, а не на следующий вопрос Питера. Да, вы можете выбрать заполнение только 0 или "" больше ничего.

Tom Leys 20.02.2012 01:48

@Leys: А, ладно. :-) Не беспокойся!

Victor Zamanian 21.02.2012 02:41

@TomLeys -flag всегда заполняет пробелом справа ?. может ли он прокладывать 0 справа

Ratatouille 22.08.2018 11:44

Для '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]

Кажется, я продублировал еще один опубликованный ответ здесь: Набивка в принте разного размера

J Jorgenson 16.03.2012 20:39

Одна вещь, которая определенно неверна в функции, которая формирует исходный вопрос в этом потоке, о которой я не видел, чтобы кто-то упоминал, заключается в том, что она объединяет дополнительные символы в конец строкового литерала, который был передан в качестве параметра. Это даст непредсказуемые результаты. В примере вызова функции строковый литерал «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

Pierre-Louis Sauvage 12.03.2017 18:07
#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);
}

Другие вопросы по теме