Relleno de cuerdas en C

6 minutos de lectura

Escribí esta función que se supone que debe hacer StringPadRight (“Hola”, 10, “0”) -> “Hola00000”.

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;
}

Funciona pero tiene algunos efectos secundarios extraños… algunas de las otras variables cambian. ¿Cómo puedo arreglar esto?

avatar de usuario
tom leys

Puede ser útil saber que printf hace el relleno por usted, usando %-10s ya que la cadena de formato rellenará la entrada en un campo de 10 caracteres de largo

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

dará salida

|Hello     |

En este caso, el símbolo – significa “Alinear a la izquierda”, el 10 significa “Diez caracteres en el campo” y la s significa que está alineando una cadena.

El formato de estilo Printf está disponible en muchos idiomas y tiene muchas referencias en la web. Aquí está una de tantas paginas explicando las banderas de formato. Como siempre Página de impresión de WikiPedia también es de ayuda (principalmente una lección de historia de cuán ampliamente se ha extendido printf).

  • ¿Qué sucede si desea que la cadena se rellene con otro carácter además de espacios? ¿Hay alguna manera de hacer esto con el printf de C?

    -Peter Ajtai

    1 oct 2011 a las 18:01

  • No parece que eso sea posible. (Hice algunas búsquedas en Google. También la página de manual para printf no parece tener ninguna indicación de tales características).

    – Víctor Zamanian

    4 de febrero de 2012 a las 12:54


  • @Víctor – cplusplus.com/reference/clibrary/cstdio/printf – ver sección ‘banderas’ y sección ‘ancho’.

    – Tom Leys

    7 febrero 2012 a las 22:31

  • @tom: sí, “el resultado se rellena con espacios en blanco”. Entonces, no parece ser posible. Como se indicó, la misma información está disponible en la página del manual. También, aunque printf debería comportarse mayormente igual, si no idénticamente, este es C, no C++.

    – Víctor Zamanian

    8 de febrero de 2012 a las 19:24

  • @Víctor. Lo siento, pensé que estabas respondiendo a mi respuesta, no a la pregunta posterior de Peter. Sí, solo puede elegir rellenar con 0 o con ” nada más.

    – Tom Leys

    19 de febrero de 2012 a las 21:48

avatar de usuario
J Jorgenson

Para ‘C’ hay un uso alternativo (más complejo) de [s]printf que no requiere ningún malloc() o formato previo, cuando se desea un relleno personalizado.

El truco consiste en utilizar especificadores de longitud ‘*’ (mín. y máx.) para %s, además de una cadena rellena con el carácter de relleno hasta la máxima longitud potencial.

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 

El “%*.*s” se puede colocar antes O después de su “%s”, según desee el relleno IZQUIERDO o DERECHO.

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

Encontré que PHP printf (aquí) admite la capacidad de dar un carácter de relleno personalizado, usando la comilla simple (‘) seguida de su carácter de relleno personalizadodentro del formato %s.
printf("[%'#10s]\n", $s); // use the custom padding character '#'

produce:
[####monkey]

  • Parece que he duplicado la respuesta publicada por otra persona aquí: relleno de tamaño variable en printf

    – J Jorgenson

    16 de marzo de 2012 a las 16:39


avatar de usuario
Izya Budman

#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;
}

Producción:

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

Debe asegurarse de que la cadena de entrada tenga suficiente espacio para contener todos los caracteres de relleno. Prueba esto:

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

Tenga en cuenta que asigné 11 bytes para el hello cadena para tener en cuenta el terminador nulo al final.

avatar de usuario
eugenio yokota

El argumento que pasó “Hola” está en el área de datos constantes. A menos que haya asignado suficiente memoria para char * string, se está sobrecargando con otras variables.

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

Editar: corregido de la pila al área de datos constantes.

  • Todavía estás pasando un literal de cadena… 😛

    – Paige Ruten

    10 de noviembre de 2008 a las 1:33

  • Estás copiando demasiado. hola es de tipo char[6] , pero intenta copiar 1024 bytes de él. eso solo puede fallar. cámbielo para leer el tamaño de “Hola” en lugar del segundo tamaño de (búfer)

    – Johannes Schaub – litb

    10 de noviembre de 2008 a las 1:52

  • strncpy(buffer, “Hola”, sizeof(buffer)); ya llena todo el búfer con ‘\0’, por lo que su memset() es redundante.

    – Chris joven

    10 de noviembre de 2008 a las 6:24

  • @litb, strncpy: si se encuentra el final de la cadena C de origen (que se indica mediante un carácter nulo) antes de que se hayan copiado num caracteres, el destino se rellena con ceros hasta que se haya escrito un total de num caracteres.

    – Eugene Yokota

    10 de noviembre de 2008 a las 8:34

  • @Chris, memset after buffer es algo habitual. Lo dejaré ahí.

    – Eugene Yokota

    10 de noviembre de 2008 a las 8:39

Oh, está bien, tiene sentido. Así que hice esto:

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

¡Gracias!

  • Todavía estás pasando un literal de cadena… 😛

    – Paige Ruten

    10 de noviembre de 2008 a las 1:33

  • Estás copiando demasiado. hola es de tipo char[6] , pero intenta copiar 1024 bytes de él. eso solo puede fallar. cámbielo para leer el tamaño de “Hola” en lugar del segundo tamaño de (búfer)

    – Johannes Schaub – litb

    10 de noviembre de 2008 a las 1:52

  • strncpy(buffer, “Hola”, sizeof(buffer)); ya llena todo el búfer con ‘\0’, por lo que su memset() es redundante.

    – Chris joven

    10 de noviembre de 2008 a las 6:24

  • @litb, strncpy: si se encuentra el final de la cadena C de origen (que se indica mediante un carácter nulo) antes de que se hayan copiado num caracteres, el destino se rellena con ceros hasta que se haya escrito un total de num caracteres.

    – Eugene Yokota

    10 de noviembre de 2008 a las 8:34

  • @Chris, memset after buffer es algo habitual. Lo dejaré ahí.

    – Eugene Yokota

    10 de noviembre de 2008 a las 8:39

#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;
}

  • No olvides liberar str1

    – Pierre-Louis Sauvage

    12 de marzo de 2017 a las 15:07

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad