Rembourrage de chaîne en C

J'ai écrit cette fonction qui est censée faire StringPadRight ("Bonjour", 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;
}

Cela fonctionne mais a des effets secondaires étranges... certains des autres variables sont modifiées. Comment puis-je résoudre ce problème?

60
demandé sur Jake 2008-11-10 04:19:50

10 réponses

Il peut être utile de savoir que printf fait du remplissage pour vous, en utilisant % - 10s car la chaîne de format remplira l'entrée dans un champ de 10 caractères

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

Affichera

|Hello     |

Dans ce cas, le symbole-signifie "alignement gauche", le 10 signifie "dix caractères dans le champ" et le s signifie que vous alignez une chaîne.

Le formatage de style Printf est disponible dans de nombreuses langues et a beaucoup de références sur le web. Voici l'une des nombreuses pages expliquant l' drapeaux de formatage. Comme d'habitude la page printf de WikiPedia {[10] } est également utile (surtout une leçon d'histoire de la propagation de printf).

128
répondu Tom Leys 2016-04-30 18:04:57

Pour 'C', il existe une utilisation alternative (plus complexe) de [s]printf qui ne nécessite aucun malloc() ou pré-formatage, lorsque le remplissage personnalisé est souhaité.

L'astuce consiste à utiliser des spécificateurs de longueur ' * ' (min et max) pour %s, plus une chaîne remplie de votre caractère de remplissage à la longueur potentielle maximale.

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 

Le"%*.*s" peut être placé avant ou après votre "%s", selon le désir de remplissage gauche ou droit.

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

J'ai trouvé ça le printf PHP (ici) prend en charge la possibilité de donner un caractère de remplissage personnalisé, en utilisant le guillemet simple ( ' ) suivi de votre caractère de remplissage personnalisé , au format %S.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
produit:
[####monkey]

32
répondu J Jorgenson 2015-06-03 13:15:22

Vous devez vous assurer que la chaîne d'entrée a suffisamment d'espace pour contenir tous les caractères de remplissage. Essayez ceci:

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

Notez que j'ai alloué 11 octets pour la chaîne hello pour tenir compte du terminateur nul à la fin.

1
répondu Greg Hewgill 2008-11-10 01:25:13

L'argument que vous avez passé "Hello" est sur la zone de données constantes. Sauf si vous avez alloué suffisamment de mémoire à char * string, il dépasse les autres variables.

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

Edit: corrigé de la pile à la zone de données constante.

1
répondu Eugene Yokota 2008-11-10 01:33:16

Oh OK, c'est logique. J'ai donc fait ceci:

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

Merci!

1
répondu 2008-11-10 01:37:17
#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
répondu Naga 2016-08-01 11:58:09

La fonction elle-même me semble bien. Le problème pourrait être que vous n'allouez pas assez d'espace pour que votre chaîne remplisse autant de caractères dessus. Vous pouvez éviter ce problème à l'avenir en passant un argument size_of_string à la fonction et assurez-vous de ne pas remplir la chaîne lorsque la longueur est sur le point d'être supérieure à la taille.

0
répondu Jeremy Ruten 2008-11-10 01:25:27

Une chose qui est définitivement fausse dans la fonction qui forme la question originale dans ce thread, que je n'ai vu personne mentionner, est qu'elle concatène des caractères supplémentaires sur la fin du littéral de chaîne qui a été passé en paramètre. Cela donnera des résultats imprévisibles. Dans l'exemple d'appel de la fonction, le littéral de chaîne "Hello" sera codé en dur dans le programme, donc probablement concaténer sur la fin de celui-ci écrira dangereusement sur le code. Si vous voulez renvoyez une chaîne plus grande que l'original, vous devez vous assurer de l'allouer dynamiquement, puis la supprimer dans le code appelant lorsque vous avez terminé.

0
répondu user4478828 2015-01-21 15:02:32
#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;
}

Sortie:

$ gcc -Wall -ansi -pedantic padding.c
$ ./a.out 
###############Hello
0
répondu Izya Budman 2018-03-08 00:56:59
#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
répondu Ayodeji 2018-08-27 16:17:43