String Padding in C


81

Tôi đã viết hàm này được cho là để thực hiện 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;
}

Nó hoạt động nhưng có một số tác dụng phụ kỳ lạ ... một số biến số khác bị thay đổi. Làm thế nào tôi có thể sửa lỗi này?

c  string  padding 

Câu trả lời:


170

Có thể hữu ích khi biết rằng printf không đệm cho bạn, sử dụng% -10s làm chuỗi định dạng sẽ đệm đầu vào ngay trong một trường dài 10 ký tự

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

sẽ xuất ra

|Hello     |

Trong trường hợp này, biểu tượng - có nghĩa là "Căn trái", 10 có nghĩa là "Mười ký tự trong trường" và s có nghĩa là bạn đang căn một chuỗi.

Định dạng kiểu printf có sẵn ở nhiều ngôn ngữ và có nhiều tài liệu tham khảo trên web. Đây là một trong nhiều trang giải thích các cờ định dạng. Như thường lệ , trang printf của WikiPedia cũng có ích (hầu hết là một bài học lịch sử về mức độ lan truyền rộng rãi của printf).


4
Điều gì sẽ xảy ra nếu bạn muốn chuỗi được đệm bởi một ký tự khác ngoài dấu cách? Có cách nào để làm điều này w C's printf?
Peter Ajtai

Nó không giống như vậy là có thể. (Đã làm một số Google. Ngoài ra, trang người đàn ông cho printfdường như không có bất kỳ dấu hiệu nào về các tính năng như vậy.)
Victor Zamanian

@victor - cplusplus.com/reference/clibrary/cstdio/printf - xem mục 'cờ' và phần 'width'.
Tom Leys

1
@tom - có, "kết quả được đệm bằng khoảng trống". Vì vậy, nó dường như là không thể. Như đã nêu, thông tin tương tự có sẵn trong trang người đàn ông. Ngoài ra, mặc dù printfsẽ hoạt động gần như giống nhau nếu không giống nhau, đây C, không phải C ++.
Victor Zamanian,

1
@Victor. Xin lỗi, tôi nghĩ bạn đang trả lời câu trả lời của tôi, không phải câu hỏi tiếp theo của Peter. Có, bạn chỉ có thể chọn đệm bằng 0 hoặc bằng '' không có gì khác.
Tom Leys

42

Đối với 'C', có cách sử dụng [s] printf thay thế (phức tạp hơn) mà không yêu cầu bất kỳ malloc () hoặc định dạng trước nào, khi muốn có đệm tùy chỉnh.

Mẹo là sử dụng các chỉ định độ dài '*' (tối thiểu và tối đa) cho% s, cộng với một chuỗi chứa đầy ký tự đệm của bạn với độ dài tiềm năng tối đa.

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" có thể được đặt trước HOẶC sau "% s" của bạn, tùy thuộc vào mong muốn cho phần đệm TRÁI hoặc PHẢI.

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

Tôi thấy rằng PHP printf ( ở đây ) hỗ trợ khả năng cung cấp một ký tự đệm tùy chỉnh, sử dụng dấu nháy đơn (') theo sau là ký tự đệm tùy chỉnh của bạn , trong định dạng% s.
printf("[%'#10s]\n", $s); // use the custom padding character '#'
sản xuất:
[####monkey]


Có vẻ như tôi đã nhân đôi số của người khác gửi câu trả lời ở đây: varible kích thước đệm trong printf
J Jorgenson

2

Bạn phải đảm bảo rằng chuỗi nhập có đủ không gian để chứa tất cả các ký tự đệm. Thử đi:

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

Lưu ý rằng tôi đã phân bổ 11 byte cho hellochuỗi tài khoản cho dấu chấm hết null ở cuối.


1

Đối số bạn đã truyền "Hello" nằm trên vùng dữ liệu không đổi. Trừ khi bạn đã cấp đủ bộ nhớ cho chuỗi ký tự *, nó sẽ chạy quá mức cho các biến khác.

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

Chỉnh sửa: Đã sửa từ ngăn xếp thành vùng dữ liệu không đổi.


Bạn tôi vẫn đang đi qua một literal chuỗi ...: P
Jeremy Ruten

bạn đang sao chép quá nhiều. Hello thuộc loại char [6], nhưng bạn cố gắng sao chép 1024 byte ra khỏi nó. điều đó chỉ có thể thất bại. thay đổi nó để đọc sizeof "Hello" thay vì sizeof thứ hai (đệm)
Johannes Schaub - litb

1
strncpy (đệm, "Xin chào", sizeof (đệm)); đã lấp đầy toàn bộ bộ đệm bằng '\ 0', vì vậy memset () của bạn là dư thừa.
Chris Young

@litb, strncpy: Nếu tìm thấy phần cuối của chuỗi C nguồn (được báo hiệu bằng ký tự null) trước khi ký tự num được sao chép, đích sẽ được đệm bằng các số không cho đến khi tổng số ký tự num được ghi vào nó.
Eugene Yokota

@Chris, memset sau khi đệm là một thói quen. Tôi sẽ để nó trong đó.
Eugene Yokota

1

Ồ được rồi, có lý. Vì vậy, tôi đã làm điều này:

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

Cảm ơn!


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

Đừng quên giải phóng 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;
}

Đầu ra:

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

0

Bản thân chức năng này có vẻ ổn đối với tôi. Vấn đề có thể là bạn không phân bổ đủ không gian cho chuỗi của mình để chèn nhiều ký tự vào đó. Bạn có thể tránh vấn đề này trong tương lai bằng cách truyền một size_of_stringđối số cho hàm và đảm bảo rằng bạn không chèn chuỗi khi độ dài sắp lớn hơn kích thước.


0

Một điều chắc chắn sai trong hàm tạo thành câu hỏi ban đầu trong chuỗi này, mà tôi chưa thấy ai đề cập đến, đó là nó đang nối các ký tự phụ vào cuối chuỗi ký tự đã được chuyển vào dưới dạng tham số. Điều này sẽ cho kết quả không thể đoán trước. Trong cuộc gọi ví dụ của hàm, chuỗi ký tự "Xin chào" sẽ được mã hóa cứng vào chương trình, vì vậy có lẽ việc nối vào cuối của nó sẽ gây nguy hiểm ghi đè lên mã. Nếu bạn muốn trả về một chuỗi lớn hơn chuỗi ban đầu thì bạn cần đảm bảo rằng bạn phân bổ động chuỗi và sau đó xóa nó trong mã gọi khi bạn hoàn tất.


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);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.