2011-12-18 3 views
11

क्या किसी को किसी भी सी 99 प्रीप्रोसेसर जादू के बारे में पता है जो स्ट्रिंग बनाने की अनुमति देता है जिसमें दूसरी स्ट्रिंग दो बार बार-बार होती है?सी प्रीप्रोसेसर मैक्रो एक स्ट्रिंग को वापस करने के लिए

उदा।

STRREP("%s ", 3) 

पूर्व प्रसंस्करण के बाद

"%s %s %s " 

हो जाता है।

केवल एक चीज मैं अपने आप को के बारे में सोच सकता है इस

#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 
... 

जो अच्छी तरह से काम करता है की तरह कुछ था, लेकिन जैसा कि मैंने मैन्युअल रूप से प्रत्येक पुनरावृत्ति लंबाई के लिए एक मैक्रो निर्धारित करने के लिए है बदसूरत है। मैं इसे विविधता मैक्रोज़ और मैक्रो के साथ here दिखाए गए मैक्रो तर्कों की संख्या लौटने के साथ एक साथ उपयोग करना चाहता हूं।

+2

मैं बहुत यकीन है कि यह संभव नहीं है हूँ। यहां एक और प्रश्न देखें जो समान है - http://stackoverflow.com/questions/319328/writing-a-while-loop-in-the-c-preprocessor – mattjgalloway

+0

धन्यवाद, @mattjgalloway। आप सही लग रहे हैं। प्रीप्रोसेसर का उपयोग कर शुद्ध सी 99 में परिवर्तनीय रिकर्सन लम्बाई का कोई तरीका नहीं है। तो मेरा विचार एकमात्र (बदसूरत!) तरीका प्रतीत होता है। – sonntam

उत्तर

4

मेरा सुझाव बूस्ट का उपयोग करना है।

उदा।

#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

केवल सी ++ के लिए बूस्ट नहीं है? –

+0

@Alex, यह कोड टेम्पलेट का उपयोग कर सी में काम करता है (जैसे सी ++ का लाभ उठाने के लिए) सी का उपयोग नहीं करता है, यह इस तरह के प्रीप्रोसेसर का उपयोग कर सकता है। – BLUEPIXY

+0

'BOOST_PP_REPEAT' में' BOOST_PP_LIMIT_REPEAT' सीमा '256' (1.48 के लिए) पर सेट है। वैसे भी, समाधान के लिए +1। – maverik

0

सुनिश्चित नहीं हूं कि यह मैक्रो के साथ किया जा सकता है, लेकिन आप की तरह समारोह के साथ यह कर सकते हैं:

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

युपीडी:

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

अब आप इसका इस्तेमाल कर सकते हैं तो malloc/free से बचना चाहते हैं यह पहला कोड का एक प्रकार है:

/* .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; 
} 

अब:

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

ओटीओएच, यह पहले की तुलना में भी उलझन में दिखता है।

+3

बेशक, यह फ़ंक्शंस का उपयोग करके किया जा सकता है, लेकिन मैं संकलन समय पर ज्ञात स्ट्रिंग रखना चाहता हूं। – sonntam

17

चूंकि यह एक मैक्रो है और एन एक संख्यात्मक स्थिर है वैसे भी, इसके बारे में कैसे? तो शायद इस एल्गोरिथ्म केवल जीसीसी के लिए काम करता है -

#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

अच्छा विचार! मैं इसे अपनी आस्तीन रखूंगा। धन्यवाद। – sonntam

+6

\ * सभी स्क्रीन पर उल्टी \ * लेकिन +1 का उपयोग करना बहुत आसान है – Thomas

0

मैं हाल ही में जो स्वचालित रूप से इलाज किया जाता है __INCLUDE_LEVEL__ पूर्वप्रक्रमक शाब्दिक से अधिक सीपीपी सी पूर्वप्रक्रमक फ़ाइल शामिल किए जाने के तंत्र के साथ एक प्रत्यावर्तन योजना की खोज की?!?

  • एल्गोरिदम अवधारणात्मक रूप से असीमित है, इसे अतिरिक्त फ़ाइल संकेत के साथ बढ़ाया जा सकता है।
  • herin प्रस्तुत कोड ITERATION_SEPARATOR आप एन तत्वों, या एन concatenations साथ 1 तत्व, स्ट्रिंग repetitions के लिए उपयुक्त उत्पन्न कर सकते हैं की टिप्पणी/टिप्पणी हटाएं साथ 0-39,202
  • एक ITERATION_COUNT संभालती है।
  • ITERATION_ELEMENT मैक्रो "पुनरावृत्ति तत्व"

आप कोड नियमित रूप से संकलन कर सकते हैं, किसी भी अतिरिक्त परिभाषित करता है बिना के रूप में प्रयोग किया जाता है।कोड के अंदर मैक्रो आमंत्रण बेवकूफ है।

एक अनुकरणीय उत्पादन:

> जीसीसी iterate.c -ओ पुनरावृति -Wall -s -O3 & & ./iterate.exe

0-1591 काउंटर

1592 तत्वों


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