Wyściełanie strun w C

Napisałem tę funkcję, która ma wykonywać 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;
}
Działa, ale ma dziwne skutki uboczne... niektóre inne zmienne ulegają zmianie. Jak mogę to naprawić?
Author: Jake, 2008-11-10

10 answers

Pomocne może być wiedzieć, że printf wykonuje wypełnianie za ciebie, używając % - 10s, ponieważ łańcuch formatujący będzie umieszczał dane wejściowe bezpośrednio w polu o długości 10 znaków

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

Wyświetli

|Hello     |

W tym przypadku - symbol oznacza "Left align", 10 oznacza "dziesięć znaków w polu", A s oznacza, że wyrównujesz łańcuch znaków.

Formatowanie stylu Printf jest dostępne w wielu językach i ma wiele odniesień w Internecie. Oto jedna z wielu stron wyjaśniająca flagi formatowania. Jak zwykle Strona printf Wikipedii jest również pomocna(głównie lekcja historii o tym, jak szeroko rozprzestrzenił się printf).

 128
Author: Tom Leys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-30 18:04:57

Dla 'C' istnieje alternatywne (bardziej złożone) użycie [s]printf, które nie wymaga malloc() ani wstępnego formatowania, gdy wymagane jest niestandardowe wypełnienie.

Sztuczka polega na użyciu określeń długości ' * ' (min i max) dla %s oraz ciągu wypełnionego znakiem wypełnienia do maksymalnej potencjalnej długości.

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 "można umieścić przed lub po "%s", w zależności od lewej lub prawej padding.

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

I found that PHP printf (tutaj ) obsługuje możliwość nadawania niestandardowego znaku wypełnienia, używając pojedynczego cudzysłowu ( ' ), po którym następuje niestandardowy znak wypełnienia, w formacie %s.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
produkuje:
[####monkey]

 32
Author: J Jorgenson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-03 13:15:22

Należy upewnić się, że łańcuch wejściowy ma wystarczająco dużo miejsca, aby pomieścić wszystkie znaki dopełniające. Spróbuj tego:

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

Zauważ, że przypisałem 11 bajtów dla ciągu hello, aby uwzględnić Terminator null na końcu.

 1
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 01:25:13

Podany przez Ciebie argument "Hello" znajduje się w obszarze danych stałych. Jeśli nie przydzieliłeś wystarczającej ilości pamięci do łańcucha znaków*, jest on zastępowany przez inne zmienne.

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

Edit: Poprawiono ze stosu do stałego obszaru danych.

 1
Author: Eugene Yokota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 01:33:16

To ma sens. Więc zrobiłem to:

    char foo[10] = "hello";
    char padded[16];
    strcpy(padded, foo);
    printf("%s", StringPadRight(padded, 15, " "));
Dzięki!
 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Naga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-01 11:58:09

Sama funkcja wygląda dobrze dla mnie. Problemem może być to, że nie przydzielasz wystarczającej ilości miejsca na łańcuch do padu, że wiele znaków na nim. Możesz uniknąć tego problemu w przyszłości, przekazując do funkcji argument size_of_string i upewnij się, że nie wstawiasz ciągu, gdy długość ma być większa niż rozmiar.

 0
Author: Jeremy Ruten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 01:25:27

Jedna rzecz, która jest zdecydowanie błędna w funkcji, która tworzy oryginalne pytanie w tym wątku, o którym nie widziałem, aby ktoś wspomniał, jest to, że łączy Dodatkowe znaki na końcu literalnego ciągu znaków, który został przekazany jako parametr. Da to nieprzewidywalne wyniki. W przykĹ 'adowym wywoĹ' aniu funkcji, literaĺ ' "Hello" bÄ ™ dzie zakodowany na twardo w programie, wiÄ ™ c prawdopodobnie poĹ 'Ä ... czenie siÄ ™ na jego kodzie niebezpiecznie bÄ ™ dzie zapisywaĺ' o kod. Jeśli chcesz zwróć ciąg znaków, który jest większy od oryginału, a następnie upewnij się, że przydzielasz go dynamicznie, a następnie usuwasz go w kodzie wywoławczym, gdy skończysz.

 0
Author: user4478828,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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;
}

Wyjście:

$ gcc -Wall -ansi -pedantic padding.c
$ ./a.out 
###############Hello
 0
Author: Izya Budman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Ayodeji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-27 16:17:43