C中的字符串填充


81

我写了应该做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;
}

它可以工作,但有一些怪异的副作用……其他一些变量被更改了。我怎样才能解决这个问题?

c  string  padding 

Answers:


170

知道printf会为您进行填充可能会有所帮助,使用%-10s作为格式字符串将在长度为10个字符的字段中填充输入内容

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

将输出

|Hello     |

在这种情况下,-符号表示“左对齐”,10表示“字段中的十个字符”,而s表示您正在对齐字符串。

Printf样式格式支持多种语言,并且在网络上具有大量参考。这是解释格式标志的众多页面之一。像往常一样,WikiPedia的printf页面也有帮助(主要是关于printf广泛传播的历史课程)。


4
如果要用空格以外的其他字符填充字符串怎么办?有没有办法做到这一点?
2011年

看起来这不可能。(做了一些谷歌搜索。此外,手册页printf似乎也没有显示这些功能。)
Victor Zamanian 2012年

@ victor-cplusplus.com / reference/ clibrary / cstdio/ printf-请参见“标志”部分和“宽度”部分。
汤姆·莱斯

1
@tom-是的,“结果用空格填充”。因此,这似乎是不可能的。如前所述,手册页中提供了相同的信息。同样,即使printf行为不尽相同,即使行为基本相同,但这还是C而不是C ++。
Victor Zamanian

1
@胜利者。抱歉,我以为您是在回答我的回答,而不是Peter随后提出的问题。是的,您只能选择以0或''填充。
汤姆·莱斯

42

对于“ C”,需要自定义填充时,可以使用[s] printf进行替代(更复杂),不需要任何malloc()或预格式化。

诀窍是对%s使用'*'长度说明符(最小和最大),再加上一个用填充字符填充到最大可能长度的字符串。

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”放在“%s”之前或之后,这取决于对LEFT或RIGHT填充的期望。

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

我发现PHP printf(here)确实支持使用%s格式的单引号(')和您的自定义填充字符来给出自定义填充字符的功能。
printf("[%'#10s]\n", $s); // use the custom padding character '#'
产生:
[####monkey]


看来我在这里重复了其他人发布的答案:printf中的可变大小填充
J Jorgenson 2012年

2

您必须确保输入字符串具有足够的空间来容纳所有填充字符。试试这个:

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

请注意,我为hello字符串分配了11个字节,以解决最后的空终止符。


1

您传递的参数“ Hello”在常量数据区域中。除非您为char * string分配了足够的内存,否则它将超出其他变量。

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

编辑:从堆栈更正为恒定数据区域。


您仍在传递字符串文字...:P
杰里米·鲁滕

您复制太多。Hello的类型为char [6],但是您尝试从中复制1024个字节。那只会失败。更改为读取sizeof“ Hello”而不是第二个sizeof(buffer)
Johannes Schaub-litb

1
strncpy(buffer,“ Hello”,sizeof(buffer)); 已经用'\ 0'填充了整个缓冲区,因此您的memset()是多余的。
克里斯·杨

@ litb,strncpy:如果在复制num个字符之前找到了源C字符串的末尾(由空字符表示),则将目标填充为零,直到总共写入了num个字符为止。
尤金(Eugene Yokota)

@Chris,缓冲后的memset是一种习惯。我会把它留在那里。
尤金(Eugene Yokota)

1

哦,好的,很有道理。所以我这样做:

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

谢谢!


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

不要忘记释放str1
Pierre-Louis Sauvage

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

输出:

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

0

该功能本身对我来说很好。问题可能是您没有为字符串分配足够的空间来将那么多字符填充到字符串上。将来可以通过size_of_string向函数传递参数来避免此问题,并确保在长度要大于大小时不要填充字符串。


0

在该线程中构成原始问题的函数中,绝对有错的一件事(我没有看到任何人提到过)是将多余的字符连接到作为参数传递的字符串文字的末尾。这将带来不可预测的结果。在该函数的示例调用中,字符串文字“ Hello”将被硬编码到程序中,因此,大概将其串联到其末尾将很危险地覆盖代码。如果要返回大于原始字符串的字符串,则需要确保动态分配它,然后在完成后在调用代码中将其删除。


0
#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);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.