2011-05-04 46 views
18

Có cách nào tốt hơn để nối nhiều chuỗi lại với nhau trong c ngoài việc có nhiều cuộc gọi đến strcat() tất cả trong một hàng, như dưới đây?cách nào tốt hơn để nối nhiều chuỗi trong c?

char prefix[100] = ""; 
strcat(prefix, argv[0]); 
strcat(prefix, ": "); 
strcat(prefix, cmd_argv[0]); 
strcat(prefix, ": "); 
strcat(prefix, cmd_argv[1]); 
perror(prefix); 
+4

bạn có thể sử dụng dấu vân tay ... – forsvarir

+6

Đây là trường hợp của [Shlemiel the Painter] (http://en.wikipedia.org/wiki/Schlemiel_the_Painter%27s_algorithm). –

+0

Cẩn thận với '_snprintf' của Microsoft không đảm bảo kết thúc null của bộ đệm đích. –

Trả lời

8

snprintf sẽ là tùy chọn tốt nhất và dễ sử dụng nhất, mặc dù nó có thể không "nhanh". Bạn đã không nói tiêu chí của bạn là gì. Đơn giản chắc chắn đây là, mặc dù:

snprintf(prefix, sizeof(prefix), "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]); 
16
sprintf(prefix,"%s: %s: %s",argv[0],cmd_argv[0],cmd_argv[1]); 

Hoặc snprintf để ngăn chặn vượt đệm.

+11

Chắc chắn thay đổi nó thành 'snprintf'. 'sprintf' đơn giản không nên được sử dụng trong mã hiện đại. –

+0

Hoặc chúng tôi có thể tải toán tử + và làm cho nó tương tự như java. – Sohaib

2

Nếu bạn đang cố xây dựng một chuỗi từ các chuỗi khác (ví dụ của bạn gợi ý), thì bạn có thể sử dụng dấu vân tay.

char prefix[100] = ""; 
snprintf(prefix, sizeof(prefix), "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]); 

Nếu bạn đang cố gắng ghép nối chuỗi hiện tại, nơi bạn không thể sử dụng phương pháp định dạng, có thể bạn sẽ bị kẹt với nhiều cuộc gọi tới strcat, mặc dù tôi thực sự khuyên bạn nên có thể muốn cân nhắc sử dụng strncat thay vào đó và kiểm tra để đảm bảo bạn không bị tràn bộ đệm.

2

bạn có thể sử dụng chức năng snprintf

char prefix[100]; 
snprintf(prefix, 100, "%s: %s: %s", argv[0], cmd_argv[0], cmd_argv[1]); 
+3

tốt hơn không nên sử dụng% s cho ":" bạn có thể chỉ cần đặt: thay vì% s – Reza

+0

Đồng ý và chỉnh sửa! –

3

tôi có thể mất một hit đại diện cho điều này, nhưng những gì heck. Điều tồi tệ nhất có thể xảy ra là tôi sẽ học điều gì đó.

Tôi không thực sự sử dụng C những ngày này và tôi thường không sử dụng chuỗi kiểu C trong C++. Nhưng tôi có ý tưởng là để viết một strcpy sửa đổi() trả về sự kết thúc của chuỗi:

char* my_strcpy(char*dest, const char* src) 
{ 
    while ((*dest = *src++)) 
     ++dest; 
    return dest; 
} 

Bây giờ Shlemiel có thể mang lại xô anh cùng với anh ta:

char prefix[100] = ""; 
char* bucket = my_strcpy(prefix, argv[0]); 
bucket = my_strcpy(bucket, ": "); 
bucket = my_strcpy(bucket, cmd_argv[0]); 
bucket = my_strcpy(bucket, ": "); 
bucket = my_strcpy(bucket, cmd_argv[1]); 
perror(prefix); 

tôi đã không kiểm tra điều này. Bình luận?

EDIT: Đã xóa chức năng my_strcat() không cần thiết. Ngoài ra, nó cũng giống như stpcpy(), dường như là một phần của POSIX vào năm 2008. Xem http://www.manpagez.com/man/3/stpcpy/.

+3

'my_strcpy()' được gọi là 'stpcpy()' trong POSIX - và bạn không cần 'my_strcat()', vì 'my_strcpy()' cũng hoạt động tốt (vì bạn đã có con trỏ đến cuối của chuỗi). – caf

+0

@caf: Tôi đã nghĩ đến điểm 'my_strcat()' sau khi đăng, nhưng tôi không biết về 'stpcpy()'. Xem, tôi đã học được điều gì đó! –

+0

@caf: Thực ra, nó xuất hiện 'stpcpy()' không phải là POSIX: "Hàm stpcpy() không phù hợp với tiêu chuẩn." (từ http://www.manpagez.com/man/3/stpcpy/) –

3

Tôi sẽ sử dụng sprintf() như những người khác đã gợi ý, nhưng điều này là cho đầy đủ:

Nếu bạn có stpcpy(), sau đó bạn có thể làm:

char prefix[100] = ""; 
stpcpy(stpcpy(stpcpy(sptcpy(stpcpy(prefix, argv[0]), ": "), 
     cmd_argv[0]), ": "), cmd_argv[1]); 
perror(prefix); 

Sự tiện lợi với stpcpy() là nó có thể được " chuỗi ", như trên. Ngoài ra, vì stpcpy() trả về một con trỏ ở cuối chuỗi kết quả, các cuộc gọi stpcpy() sau đó không cần phải đi qua lại dữ liệu cũ. Vì vậy, nó hiệu quả hơn nhiều strcat() s và có lẽ hiệu quả hơn sprintf(). stpcpy() là POSIX: 2008.

1

Giả sử bạn có thẻ [fixed_size] như được đăng, chứ không phải char *, bạn có thể sử dụng macro đơn lẻ, sáng tạo để thực hiện tất cả cùng một lúc với lệnh đặt cout thay vì định dạng kiểu printf rời rạc.Nếu bạn đang làm việc với các hệ thống nhúng, phương pháp này sẽ cho phép bạn thoát khỏi nhóm các chức năng lớn như snprintf() (Điều này cũng ngăn không cho ăn kiêng) và thậm chí không yêu cầu malloc() hoặc bất kỳ chức năng nào từ <string.h>.

#include <unistd.h> //for write 
//note: you should check if offset==sizeof(buf) after use 
#define strcpyALL(buf, offset, ...) do{ \ 
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \ 
    const char *s, \ 
    *a[] = { __VA_ARGS__,NULL}, \ 
    **ss=a; \ 
    while((s=*ss++)) \ 
     while((*s)&&(++offset<(int)sizeof(buf))) \ 
      *bp++=*s++; \ 
    if (offset!=sizeof(buf))*bp=0; \ 
}while(0) 

char buf[100]; 
int len=0; 
strcpyALL(buf,len, argv[0],": ", cmd_argv[0],": ",cmd_argv[1]); 
if (len==sizeof(buf))write(2,"error\n",6); 
else write(1,buf,len); 
  • Note 1, bạn có thể sử dụng bất kỳ chức năng mà kết quả đầu ra một char *, bao gồm các chức năng chuẩn như itoa() để chuyển đổi số nguyên với các loại chuỗi.
  • Lưu ý 2, nếu bạn đang sử dụng thư viện dùng chung hoặc đang sử dụng chức năng kiểu printf ở bất kỳ đâu trong chương trình được xây dựng tĩnh, lý do duy nhất không sử dụng snprintf() (vì mã được biên dịch sẽ lớn hơn với phương thức này) là vì nó được gạch chân và không gọi bất kỳ chức năng bên ngoài nào, vì vậy nó phải tương đối nhanh.
Các vấn đề liên quan