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?
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).
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]
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.
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.
#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;
}
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.
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é.
#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
#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);
}