2008-11-10 23 views
54

Tôi đã viết hàm này có nghĩa vụ phải làm StringPadRight ("Xin chào", 10, "0") -> "Hello00000".Chuỗi đệm trong C

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ụ lạ ... một số biến khác bị thay đổi. Làm thế nào tôi có thể sửa lỗi này?

Trả lời

119

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

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

chí đầu ra

|Hello  | 

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

Định dạng kiểu bản in có sẵn bằng nhiều ngôn ngữ và có nhiều tham chiếu trên web. Dưới đây là one of many pages giải thích các cờ định dạng. Như thường lệ, WikiPedia's printf page cũng được giúp đỡ (chủ yếu là một bài học lịch sử về mức độ lây lan của printf).

+3

Điều gì xảy ra nếu bạn muốn chuỗi bị chèn bởi một ký tự khác ngoài dấu cách? Có cách nào để làm printf của w C này? –

+0

Nó không giống như vậy là có thể. (Đã làm một số Googling. Ngoài ra người đàn ông trang cho 'printf' dường như không có bất kỳ dấu hiệu của các tính năng như vậy.) –

+0

@victor - http://www.cplusplus.com/reference/clibrary/cstdio/printf/ - see phần 'cờ' và phần 'chiều rộng'. –

1

Đối số bạn đã chuyển "Xin chào" nằm trên vùng dữ liệu không đổi. Trừ khi bạn đã phân bổ đủ bộ nhớ cho chuỗi char *, nó sẽ tràn ngập 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 sang vùng dữ liệu không đổi.

+0

Bạn tôi vẫn đang đi qua một chuỗi chữ ...: P –

+0

tôi nhận thấy rằng quá. Buồn cười. –

+0

bạn đang sao chép quá nhiều. Xin chào là 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ì kích thước thứ hai (buffer) –

1

Bạn phải đảm bảo rằng chuỗi đầu vào có đủ không gian để giữ tất cả các ký tự đệm. Hãy thử điều này:

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

Lưu ý rằng tôi đã phân bổ 11 byte cho chuỗi ký tự null ở cuối.

0

Chức năng chính nó có vẻ ổn với tôi. Vấn đề có thể là bạn không phân bổ đủ không gian cho chuỗi của bạn để dá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 chuyển đối số size_of_string cho hàm và đảm bảo bạn không dán chuỗi khi độ dài sắp lớn hơn kích thước.

1

Oh okay, có ý nghĩa. 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!

29

Đối với 'C', sử dụng 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 tùy chỉnh đệm.

Bí quyết là sử dụng các chỉ số độ dài '*' (tối thiểu và tối đa) cho% s, cộng với chuỗi được điền bằng ký tự đệm của bạn với độ dài tối đa tiềm năng.

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 

Có thể đặt "% *. * S" trước OR sau "% s", tùy thuộc vào mong muốn của LEFT hoặc RIGHT padding.

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

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

+0

Có vẻ như tôi đã sao chép một số câu trả lời được đăng khác tại đây: [Variable size padding in printf] (http://stackoverflow.com/questions/4133318/varible-sized-padding-in-printf) –

0

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

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

Đừng quên tự do str1 –

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