web-dev-qa-db-ja.com

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

それは動作しますが、いくつかの奇妙な副作用があります...他の変数のいくつかは変更されます。どうすれば修正できますか?

66
jackson

Printfがパディングを行うことを知っておくと便利です。%-10sを使用すると、フォーマット文字列は10文字長のフィールドに入力をパディングします。

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

出力します

|Hello     |

この場合、-記号は「左揃え」を意味し、10は「フィールド内の10文字」を意味し、sは文字列を揃えることを意味します。

Printfスタイルの書式設定は多くの言語で利用でき、ウェブ上で多くの参照があります。 多くのページの1つ フォーマットフラグを説明しています。いつものように WikiPediaのprintfページ も役立ちます(主にprintfの普及の歴史の教訓です)。

143
Tom Leys

'C'には、カスタムパディングが必要な場合に、malloc()または事前フォーマットを必要としない[s] printfの代替(より複雑な)使用があります。

トリックは、%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」の後のORの前に配置できます。

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

PHP printf( here )はカスタムパディング文字を提供する機能をサポートしていること、一重引用符( ')に続いて、%s形式内のカスタムパディング文字が続きます。
printf("[%'#10s]\n", $s); // use the custom padding character '#'
生産:
_[####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

「Hello」を渡した引数は、定数データ領域にあります。 char * stringに十分なメモリを割り当てていない限り、他の変数に対してオーバーランしています。

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

編集:スタックから定数データ領域に修正。

1
Eugene Yokota

入力文字列にすべてのパディング文字を保持するのに十分なスペースがあることを確認する必要があります。これを試して:

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

hello文字列に11バイトを割り当てて、最後のヌルターミネータに対応していることに注意してください。

1
Greg Hewgill

わかりました。だから私はこれをやった:

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

ありがとう!

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

出力:

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

関数自体は私には問題ありません。問題は、文字列がそれに多くの文字を埋め込むのに十分なスペースを割り当てていないことです。将来、この問題を回避するには、size_of_string引数を関数に渡し、長さがサイズよりも大きくなるときに文字列をパディングしないようにします。

0
Jeremy Ruten

このスレッドの元の質問を形成する関数で間違いなく間違っていることの1つは、誰も言及していないが、パラメータとして渡された文字列リテラルの末尾に余分な文字を連結していることです。これは予測不可能な結果を​​もたらします。関数の呼び出し例では、文字列リテラル「Hello」がプログラムにハードコーディングされているため、おそらくその末尾に連結するとコードが上書きされて危険です。元の文字列よりも大きい文字列を返したい場合は、動的に割り当ててから、終了時に呼び出し元のコードで削除する必要があります。

0
user4478828