C 中的字符串填充

我编写了这个函数,它应该执行 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;
}

它起作用了,但有些奇怪的副作用,一些其他的变量被改变了。我该怎么补救?

199698 次浏览

The argument you passed "Hello" is on the constant data area. Unless you've allocated enough memory to char * string, it's overrunning to other variables.

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

Edit: Corrected from stack to constant data area.

You must make sure that the input string has enough space to hold all the padding characters. Try this:

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

Note that I allocated 11 bytes for the hello string to account for the null terminator at the end.

The function itself looks fine to me. The problem could be that you aren't allocating enough space for your string to pad that many characters onto it. You could avoid this problem in the future by passing a size_of_string argument to the function and make sure you don't pad the string when the length is about to be greater than the size.

Oh okay, makes sense. So I did this:

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

Thanks!

It might be helpful to know that printf does padding for you, using %-10s as the format string will pad the input right in a field 10 characters long

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

will output

|Hello     |

In this case the - symbol means "Left align", the 10 means "Ten characters in field" and the s means you are aligning a string.

Printf style formatting is available in many languages and has plenty of references on the web. Here is one of many pages explaining the formatting flags. As usual WikiPedia's printf page is of help too (mostly a history lesson of how widely printf has spread).

For 'C' there is alternative (more complex) use of [s]printf that does not require any malloc() or pre-formatting, when custom padding is desired.

The trick is to use '*' length specifiers (min and max) for %s, plus a string filled with your padding character to the maximum potential length.

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

The "%*.*s" can be placed before OR after your "%s", depending desire for LEFT or RIGHT padding.

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

I found that the PHP printf (here) does support the ability to give a custom padding character, using the single quote (') followed by your custom padding character, within the %s format.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
produces:
[####monkey]

One thing that's definitely wrong in the function which forms the original question in this thread, which I haven't seen anyone mention, is that it is concatenating extra characters onto the end of the string literal that has been passed in as a parameter. This will give unpredictable results. In the example call of the function, the string literal "Hello" will be hard-coded into the program, so presumably concatenating onto the end of it will dangerously write over code. If you want to return a string which is bigger than the original then you need to make sure you allocate it dynamically and then delete it in the calling code when you're done.

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

Output:

$ 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);
}