2011-12-18 24 views
11

Có ai biết về bất kỳ ma thuật tiền xử lý C99 nào cho phép tạo chuỗi bao gồm một chuỗi N lần lặp lại không?Macro tiền xử lý C để trả về một chuỗi lặp lại một số lần nhất định

Ví dụ:

STRREP("%s ", 3) 

trở thành

"%s %s %s " 

sau khi tiền xử lý.

Điều duy nhất tôi có thể nghĩ đến bản thân mình là một cái gì đó như thế này

#define STRREP(str, N) STRREP_##N(str)  
#define STRREP_0(str) "" 
#define STRREP_1(str) str 
#define STRREP_2(str) str str 
#define STRREP_3(str) str str str 
... 

mà hoạt động tốt, nhưng là xấu xí như tôi phải xác định một macro cho mỗi chiều dài lặp lại bằng tay. Tôi muốn sử dụng nó cùng với các macro variadic và macro trả lại số đối số macro được hiển thị here.

+2

Tôi khá chắc chắn rằng nó là không thể. Xem một câu hỏi khác ở đây tương tự - http://stackoverflow.com/questions/319328/writing-a-while-loop-in-the-c-preprocessor – mattjgalloway

+0

Cảm ơn bạn, @mattjgalloway. Bạn có vẻ đúng. Không có cách nào có độ dài đệ quy thay đổi trong C99 thuần túy sử dụng bộ tiền xử lý. Ý tưởng của tôi có vẻ là cách duy nhất (xấu xí!). – sonntam

Trả lời

4

Đề xuất của tôi là sử dụng tăng.

Ví dụ:

#include <stdio.h> 
#include <boost/preprocessor/repetition/repeat.hpp> 

#define Fold(z, n, text) text 

#define STRREP(str, n) BOOST_PP_REPEAT(n, Fold, str) 

int main(){ 
    printf("%s\n", STRREP("%s ", 3));//STRREP("%s ", 3) -> "%s %s %s " 
    return 0; 
} 
+2

Không phải là Boost cho C++? –

+0

@ Alex, Mã này hoạt động trong C. sử dụng mẫu (như tận dụng lợi thế của C++) không sử dụng C. nó có thể sử dụng bộ tiền xử lý này. – BLUEPIXY

+0

'BOOST_PP_REPEAT' có giới hạn' BOOST_PP_LIMIT_REPEAT' được đặt thành '256' (tương đương với 1,48). Dù sao, 1 cho giải pháp. – maverik

0

Không chắc liệu nó có thể được thực hiện với sự vĩ mô nhưng bạn có thể làm điều đó với các chức năng như:

char *strrep(const char *str, int nrep) 
{ 
    if (nrep <= 0 || !str) return NULL; 
    char *buf = malloc(strlen(str) * nrep + 1); 
    if (!buf) return NULL; 
    for (int i = 0; i < nrep; ++i) { 
     strcat(buf, str); 
    } 
    return buf; 
} 

Bây giờ bạn có thể sử dụng nó:

char *r = strrep("%s", 3); 
if (r) { 
    ... 
    free(r); 
} 

UPD: Nếu bạn muốn tránh malloc/free đây là một biến thể của mã đầu tiên:

/* .h */ 
#define STRREP_MAX_CHARS 1024 
#define STRREP_INIT static char __strrep_buffer[STRREP_MAX_CHARS] 
#define STRREP(str, nrep) strrep(str, nrep) ? __strrep_buffer : "" 

char *strrep(const char *str, int nrep); 

/* .c */ 
STRREP_INIT; 

char *strrep(const char *str, int nrep) 
{ 
    if (nrep <= 0 || !str) return 0; 
    if (strlen(str) * nrep >= STRREP_MAX_CHARS) return 0; 
    memset(__strrep_buffer, 0, STRREP_MAX_CHARS); 
    for (int i = 0; i < nrep; ++i) { 
     strcat(__strrep_buffer, str); 
    } 
    return __strrep_buffer; 
} 

Bây giờ:

printf("%s\n", STRREP("%s", 3)); 

OTOH, điều này thậm chí còn xấu hơn lần đầu tiên.

+3

Tất nhiên, nó có thể được thực hiện bằng cách sử dụng chức năng, nhưng tôi muốn có chuỗi được biết đến tại thời gian biên dịch. – sonntam

17

Vì đó là macro và N là một hằng số, dù sao thì sao?

#include <stdio.h> 

#define REP0(X) 
#define REP1(X) X 
#define REP2(X) REP1(X) X 
#define REP3(X) REP2(X) X 
#define REP4(X) REP3(X) X 
#define REP5(X) REP4(X) X 
#define REP6(X) REP5(X) X 
#define REP7(X) REP6(X) X 
#define REP8(X) REP7(X) X 
#define REP9(X) REP8(X) X 
#define REP10(X) REP9(X) X 

#define REP(HUNDREDS,TENS,ONES,X) \ 
    REP##HUNDREDS(REP10(REP10(X))) \ 
    REP##TENS(REP10(X)) \ 
    REP##ONES(X) 

int main(void) 
{ 
    printf(REP(9,0,7, "*")); // "*" repeated 907 times 
    printf(REP(0,9,2, "#")); // "#" repeated 92 times 
    printf(REP(0,0,1, "@")); // "@" repeated 1 times 
    return 0; 
} 
+0

Ý tưởng hay! Tôi sẽ giữ nó lên tay áo của tôi. Cảm ơn bạn. – sonntam

+6

\ * Vượt qua mọi màn hình \ * nhưng nó khá dễ sử dụng mặc dù +1 – Thomas

0

thời gian gần đây tôi phát hiện ra một chương trình đệ quy với c-Preprocessor cơ chế tập tin bao gồm CPP qua tiền xử lý __INCLUDE_LEVEL__ đen mà được xử lý tự động - vì vậy có lẽ thuật toán này chỉ hoạt động cho gcc?!?

  • Thuật toán là khái niệm không giới hạn, nó có thể được mở rộng với thêm tập tin bổ sung.
  • Các Herin giới đang xử lý một ITERATION_COUNT 0-39.202
  • Với những nhận xét/bỏ ghi chú của ITERATION_SEPARATOR bạn có thể tạo các phần tử N hoặc 1 phần tử với N concatenations, thích hợp cho lần lặp lại chuỗi.
  • vĩ mô ITERATION_ELEMENT được sử dụng như những "yếu tố lặp lại"

Bạn có thể biên dịch mã regulary, mà không cần bất kỳ định nghĩa bổ sung.Lệnh gọi macro bên trong mã là idempotent.

Một đầu ra gương mẫu:

> gcc -o iterate.c lặp Wall -s O3 & & ./iterate.exe

0-1591 Counter

1592 Elements


iterate.c:

#include <stdio.h> 
#include <inttypes.h> 

int main(void) { 

const char * preproc_array[] = { 
#define ITERATION_COUNT   1592    //0-(199*197-1)39202 (maximum counter) 
#define ITERATION_SEPARATOR ,      //this macro, if active, determines wheather there exits N separate elements otherwise, if outcommented, just 1 element with N concatenations 
#define ITERATION_ELEMENT 0-__COUNTER__ Counter\n //the expanded macro as an arbitrary element 
#include "iterate.h" 
}; 

return !printf("%s%"PRIu32" Elements",preproc_array[ 
#ifndef NO_ITERATION_SEPARATOR 
__COUNTER__-1 
#else 
0 
#endif 
], sizeof(preproc_array)/sizeof(const char *)); 

} 

iterate.h:

#define  ITERATION_START 1 //start index of first inclusion 
#define  ITERATION_LIMIT  199 //conforming to CPP preprocessor manual pg. 54 chapter 11.5, a limit of 200 is set arbitrary 
#define  ITERATION(...)  _ITERATION(__VA_ARGS__) 
#define  _ITERATION(...)  #__VA_ARGS__ ITERATION_SEPARATOR 

#ifndef ITERATION_SEPARATOR 
#define ITERATION_SEPARATOR 
#define NO_ITERATION_SEPARATOR 
#endif 

//here begins the recursive algorithm via preprocessor file inclusion, enable the warnings if you want to see how it loops through 

#if __INCLUDE_LEVEL__ <= ITERATION_COUNT/ITERATION_LIMIT 
//~ #warning DIV 
#define ITERATION_END ITERATION_COUNT/ITERATION_LIMIT+3 // + offset 
#include "loop.h" 
#define ITERATION_END ITERATION_LIMIT 
#include "loop.h" 
#include "iterate.h" 
#endif 

#if __INCLUDE_LEVEL__ == ITERATION_START 
//~ #warning MOD 
#define ITERATION_END ITERATION_COUNT%ITERATION_LIMIT+ITERATION_START 
#include "loop.h" 
#if ITERATION_COUNT  % ITERATION_LIMIT 
#define ITERATION_END 3 // + offset 
#include "loop.h" 
#endif 
#endif 

//end of alogrithm 

loop.h:

#if __INCLUDE_LEVEL__ < ITERATION_END 
#include "loop.h" 
ITERATION(ITERATION_ELEMENT) 
#undef ITERATION_END 
#endif 
Các vấn đề liên quan