web-dev-qa-db-fra.com

Rembourrage de cordes en C

J'ai écrit cette fonction supposée faire 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;
}

Cela fonctionne mais a des effets secondaires étranges ... certaines des autres variables sont modifiées. Comment puis-je réparer cela?

66
jackson

Il peut être utile de savoir que printf effectue le remplissage à votre place, en utilisant% -10s car la chaîne de format insère l'entrée dans un champ de 10 caractères.

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

va sortir

|Hello     |

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

Le formatage de style Printf est disponible dans de nombreuses langues et contient de nombreuses références sur le Web. Voici ne des nombreuses pages expliquant les drapeaux de formatage. Comme d'habitude la page printf de WikiPedia est également utile (principalement une leçon d'histoire sur l'étendue de la diffusion de printf).

143
Tom Leys

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

L'astuce consiste à utiliser les spécificateurs de longueur '*' (min et max) pour% s, ainsi qu'une chaîne remplie avec 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 OR après votre "% s", selon le souhait du remplissage à gauche ou à droite.

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

J'ai trouvé que le PHP printf ( here ) prend en charge la possibilité de donner un caractère de remplissage personnalisé () à l'aide du guillemet simple ( ') suivi de votre caractère de remplissage personnalisé , dans le format% s.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
produit:
[####monkey]

38
J Jorgenson
#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
Naga

L'argument que vous avez passé "Bonjour" est dans la zone de données constantes. Si vous n'avez pas alloué suffisamment de mémoire à char * string, les autres variables sont dépassées.

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

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

1
Eugene Yokota

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

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

Notez que j'ai alloué 11 octets pour la chaîne hello afin de prendre en compte le terminateur nul à la fin.

1
Greg Hewgill

Oh d'accord, ça a du sens. Alors j'ai fait ça:

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

Merci!

1
jackson
#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
Ayodeji
#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
Izya Budman

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

0
Jeremy Ruten

Une chose qui ne va absolument pas dans la fonction qui constitue la question initiale dans ce fil, ce que je n'ai vu personne, est la concaténation de caractères supplémentaires à la fin du littéral de chaîne qui a été transmis en tant que 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. Par conséquent, la concaténation à la fin de celui-ci risque d'écrire dangereusement sur le code. Si vous souhaitez renvoyer une chaîne plus grande que l'original, vous devez vous assurer de l'affecter de manière dynamique, puis de la supprimer dans le code d'appel lorsque vous avez terminé.

0
user4478828