लगभग सभी भाषाओं में ए foreach
लूप या कुछ समान होता है। क्या C के पास एक है? क्या आप कुछ उदाहरण कोड पोस्ट कर सकते हैं?
foreach
C प्रोग्राम में लूप लिखने की कोशिश करना कितना कठिन रहा होगा ?
लगभग सभी भाषाओं में ए foreach
लूप या कुछ समान होता है। क्या C के पास एक है? क्या आप कुछ उदाहरण कोड पोस्ट कर सकते हैं?
foreach
C प्रोग्राम में लूप लिखने की कोशिश करना कितना कठिन रहा होगा ?
जवाबों:
C के पास फॉर्च्यूनर नहीं है, लेकिन मैक्रोज़ का उपयोग अक्सर उस अनुकरण के लिए किया जाता है:
#define for_each_item(item, list) \
for(T * item = list->head; item != NULL; item = item->next)
और इस्तेमाल किया जा सकता है
for_each_item(i, processes) {
i->wakeup();
}
किसी सरणी पर परिवर्तन भी संभव है:
#define foreach(item, array) \
for(int keep = 1, \
count = 0,\
size = sizeof (array) / sizeof *(array); \
keep && count != size; \
keep = !keep, count++) \
for(item = (array) + count; keep; keep = !keep)
और इस्तेमाल किया जा सकता है
int values[] = { 1, 2, 3 };
foreach(int *v, values) {
printf("value: %d\n", *v);
}
संपादित करें: यदि आप C ++ समाधान में रुचि रखते हैं, तो C ++ में प्रत्येक के लिए एक देशी सिंटैक्स है, जिसे "श्रेणी के लिए आधारित" कहा जाता है।
#define foreach(item, array) int count=0, size=sizeof(array)/sizeof(*(array)); for(item = (array); count != size; count++, item = (array)+count)
एक समस्या जो मैं देख सकता हूं वह यह है कि चर गिनती और आकार लूप के लिए बाहर रहते हैं, और संघर्ष का कारण हो सकते हैं। क्या यह कारण है कि आप दो छोरों के लिए उपयोग करते हैं? [कोड यहाँ पेस्ट किया गया ( pastebin.com/immndpwS )]
if(...) foreach(int *v, values) ...
। यदि वे लूप के बाहर हैं, तो यह फैलता है if(...) int count = 0 ...; for(...) ...;
और टूट जाएगा।
यहाँ C99 में प्रत्येक मैक्रो के लिए एक पूर्ण प्रोग्राम उदाहरण दिया गया है:
#include <stdio.h>
typedef struct list_node list_node;
struct list_node {
list_node *next;
void *data;
};
#define FOR_EACH(item, list) \
for (list_node *(item) = (list); (item); (item) = (item)->next)
int
main(int argc, char *argv[])
{
list_node list[] = {
{ .next = &list[1], .data = "test 1" },
{ .next = &list[2], .data = "test 2" },
{ .next = NULL, .data = "test 3" }
};
FOR_EACH(item, list)
puts((char *) item->data);
return 0;
}
list[]
परिभाषा में डॉट क्या करता है ? क्या आप next
इसके बजाय बस नहीं लिख सकते थे .next
?
free()
) और दूसरे के लिए इसकी परिभाषा के अंदर मूल्य का संदर्भ है। यह वास्तव में कुछ का एक उदाहरण है जो अभी भी बहुत चालाक है; कोड का उद्देश्य पर्याप्त रूप से उद्देश्यपूर्णता के साथ चतुराई को जोड़ने के बिना। कर्निघन की कामोत्तेजना ( stackoverflow.com/questions/1103299/… ) लागू होती है!
सी में कोई फॉर्च्यूनर नहीं है।
आप डेटा के माध्यम से लूप के लिए लूप का उपयोग कर सकते हैं, लेकिन लंबाई जानने की जरूरत है या डेटा को एक मान मान (जैसे शून्य) द्वारा समाप्त करने की आवश्यकता है।
char* nullTerm;
nullTerm = "Loop through my characters";
for(;nullTerm != NULL;nullTerm++)
{
//nullTerm will now point to the next character.
}
जैसा कि आप शायद पहले से ही जानते हैं, सी में कोई "फॉर्च्यूनर" -स्टाइल लूप नहीं है।
हालाँकि इसके चारों ओर काम करने के लिए पहले से ही महान मैक्रोज़ उपलब्ध हैं, शायद आपको यह मैक्रो उपयोगी लगे:
// "length" is the length of the array.
#define each(item, array, length) \
(typeof(*(array)) *p = (array), (item) = *p; p < &((array)[length]); p++, (item) = *p)
... जिसका उपयोग for
(के रूप में for each (...)
) किया जा सकता है ।
इस दृष्टिकोण के लाभ:
item
घोषित किया गया है और बयान के लिए बढ़ा दिया गया है (ठीक अजगर की तरह!)।p
, item
) में बनाए गए सभी चर , लूप के दायरे के बाहर दिखाई नहीं देते हैं (क्योंकि वे लूप हैडर के लिए घोषित किए गए हैं)।नुकसान:
typeof()
, जो एक GNU एक्सटेंशन है, मानक C का हिस्सा नहीं हैबस आपको कुछ समय बचाने के लिए, यहां बताया गया है कि आप इसे कैसे परख सकते हैं:
typedef struct {
double x;
double y;
} Point;
int main(void) {
double some_nums[] = {4.2, 4.32, -9.9, 7.0};
for each (element, some_nums, 4)
printf("element = %lf\n", element);
int numbers[] = {4, 2, 99, -3, 54};
// Just demonstrating it can be used like a normal for loop
for each (number, numbers, 5) {
printf("number = %d\n", number);
if (number % 2 == 0)
printf("%d is even.\n", number);
}
char* dictionary[] = {"Hello", "World"};
for each (word, dictionary, 2)
printf("word = '%s'\n", word);
Point points[] = {{3.4, 4.2}, {9.9, 6.7}, {-9.8, 7.0}};
for each (point, points, 3)
printf("point = (%lf, %lf)\n", point.x, point.y);
// Neither p, element, number or word are visible outside the scope of
// their respective for loops. Try to see if these printfs work
// (they shouldn't):
// printf("*p = %s", *p);
// printf("word = %s", word);
return 0;
}
डिफ़ॉल्ट रूप से gcc और clang पर काम करने लगता है; अन्य संकलक का परीक्षण नहीं किया है।
यह एक काफी पुराना प्रश्न है, लेकिन मुझे यह पोस्ट करना चाहिए। यह GNU C99 के लिए एक फॉरेस्ट लूप है।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define FOREACH_COMP(INDEX, ARRAY, ARRAY_TYPE, SIZE) \
__extension__ \
({ \
bool ret = 0; \
if (__builtin_types_compatible_p (const char*, ARRAY_TYPE)) \
ret = INDEX < strlen ((const char*)ARRAY); \
else \
ret = INDEX < SIZE; \
ret; \
})
#define FOREACH_ELEM(INDEX, ARRAY, TYPE) \
__extension__ \
({ \
TYPE *tmp_array_ = ARRAY; \
&tmp_array_[INDEX]; \
})
#define FOREACH(VAR, ARRAY) \
for (void *array_ = (void*)(ARRAY); array_; array_ = 0) \
for (size_t i_ = 0; i_ && array_ && FOREACH_COMP (i_, array_, \
__typeof__ (ARRAY), \
sizeof (ARRAY) / sizeof ((ARRAY)[0])); \
i_++) \
for (bool b_ = 1; b_; (b_) ? array_ = 0 : 0, b_ = 0) \
for (VAR = FOREACH_ELEM (i_, array_, __typeof__ ((ARRAY)[0])); b_; b_ = 0)
/* example's */
int
main (int argc, char **argv)
{
int array[10];
/* initialize the array */
int i = 0;
FOREACH (int *x, array)
{
*x = i;
++i;
}
char *str = "hello, world!";
FOREACH (char *c, str)
printf ("%c\n", *c);
return EXIT_SUCCESS;
}
इस कोड को GNU / Linux पर gcc, icc और clang के साथ काम करने के लिए परीक्षण किया गया है।
जबकि C के पास प्रत्येक निर्माण के लिए नहीं है, यह हमेशा एक सरणी के अंत में एक अतीत के लिए एक मुहावरेदार प्रतिनिधित्व करता है (&arr)[1]
। यह आपको प्रत्येक लूप के लिए एक सरल मुहावरेदार लिखने की अनुमति देता है:
int arr[] = {1,2,3,4,5};
for(int *a = arr; a < (&arr)[1]; ++a)
printf("%d\n", *a);
(&arr)[1]
सरणी के अंत में एक सरणी आइटम का मतलब नहीं है, इसका मतलब है कि सरणी के अंत में एक सरणी अतीत है। (&arr)[1]
सरणी [0] का अंतिम आइटम नहीं है, यह सरणी [1] है, जो पहले तत्व (सरणी [1]) के लिए एक सूचक में तय होता है। मेरा मानना है कि यह करना const int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
और फिर बेहतर, सुरक्षित और मुहावरेदार होगा for(const int* a = begin; a != end; a++)
।
C में 'for' और 'जबकि' keywords हैं। यदि C # जैसी भाषा में एक फ़ॉरवर्ड स्टेटमेंट इस तरह दिखता है ...
foreach (Element element in collection)
{
}
... तो C में इस फ़ॉरवर्ड स्टेटमेंट के बराबर हो सकता है:
for (
Element* element = GetFirstElement(&collection);
element != 0;
element = GetNextElement(&collection, element)
)
{
//TODO: do something with this element instance ...
}
जब मैं सी के साथ फंस गया हूं तो यहां मैं वही उपयोग कर रहा हूं। आप एक ही आइटम नाम का दो बार एक ही दायरे में उपयोग नहीं कर सकते हैं, लेकिन यह वास्तव में एक मुद्दा नहीं है क्योंकि हम सभी को नए नए कंपाइलरों का उपयोग करने के लिए नहीं मिलता है :(
#define FOREACH(type, item, array, size) \
size_t X(keep), X(i); \
type item; \
for (X(keep) = 1, X(i) = 0 ; X(i) < (size); X(keep) = !X(keep), X(i)++) \
for (item = (array)[X(i)]; X(keep); X(keep) = 0)
#define _foreach(item, array) FOREACH(__typeof__(array[0]), item, array, length(array))
#define foreach(item_in_array) _foreach(item_in_array)
#define in ,
#define length(array) (sizeof(array) / sizeof((array)[0]))
#define CAT(a, b) CAT_HELPER(a, b) /* Concatenate two symbols for macros! */
#define CAT_HELPER(a, b) a ## b
#define X(name) CAT(__##name, __LINE__) /* unique variable */
उपयोग:
int ints[] = {1, 2, 0, 3, 4};
foreach (i in ints) printf("%i", i);
/* can't use the same name in this scope anymore! */
foreach (x in ints) printf("%i", x);
EDIT: यहाँ FOREACH
नामस्थान प्रदूषण से बचने के लिए c99 सिंटैक्स का उपयोग करने का विकल्प दिया गया है:
#define FOREACH(type, item, array, size) \
for (size_t X(keep) = 1, X(i) = 0; X(i) < (size); X(keep) = 1, X(i)++) \
for (type item = (array)[X(i)]; X(keep); X(keep) = 0)
VAR(i) < (size) && (item = array[VAR(i)])
सरणी तत्व का मान होने के बाद 0. बंद हो जाएगा। इसलिए double Array[]
सभी तत्वों के माध्यम से पुनरावृति नहीं हो सकती है। लगता है जैसे लूप टेस्ट एक या दूसरे होने चाहिए: i<n
या A[i]
। शायद स्पष्टता के लिए नमूना उपयोग के मामलों को जोड़ें।
if ( bla ) FOREACH(....) { } else....
FOREACH
जो नामस्थान प्रदूषण से बचने के लिए c99 सिंटैक्स का उपयोग करता है।
एरिक का जवाबजब आप "ब्रेक" या "जारी" का उपयोग कर रहे हैं तो काम नहीं करता है।
यह पहली पंक्ति को फिर से लिखकर तय किया जा सकता है:
मूल पंक्ति (सुधारित):
for (unsigned i = 0, __a = 1; i < B.size(); i++, __a = 1)
फिक्स्ड:
for (unsigned i = 0, __a = 1; __a && i < B.size(); i++, __a = 1)
यदि आप इसकी तुलना जोहान्स लूप से करते हैं, तो आप देखेंगे कि वह वास्तव में ऐसा ही कर रहा है, बस थोड़ा और अधिक जटिल और बदसूरत।
यहाँ एक सरल है, लूप के लिए एकल:
#define FOREACH(type, array, size) do { \
type it = array[0]; \
for(int i = 0; i < size; i++, it = array[i])
#define ENDFOR } while(0);
int array[] = { 1, 2, 3, 4, 5 };
FOREACH(int, array, 5)
{
printf("element: %d. index: %d\n", it, i);
}
ENDFOR
सूचकांक में आप जो चाहते हैं, वह आपको देना चाहिए ( i
) और वर्तमान आइटम जिसे हम अधिक पुनरावृत्त कर रहे हैं ( it
)। ध्यान दें कि आपके पास नामकरण के मुद्दे हो सकते हैं जब लूप्स को घोंसले में डालते हैं, तो आप आइटम और इंडेक्स नामों को मैक्रो में पैरामीटर बना सकते हैं।
संपादित करें: यहां स्वीकृत उत्तर का एक संशोधित संस्करण है foreach
। आप निर्दिष्ट करने देता start
सूचकांक, size
इतना है कि यह सड़ा हुआ सरणियों (संकेत) पर काम करता है, के लिए कोई ज़रूरत नहीं int*
है और उसे बदला count != size
करने के लिए i < size
सिर्फ मामले में उपयोगकर्ता गलती से संशोधित 'मैं' से भी बड़ा होने के लिए size
और अनंत लूप में अटक जाते हैं।
#define FOREACH(item, array, start, size)\
for(int i = start, keep = 1;\
keep && i < size;\
keep = !keep, i++)\
for (item = array[i]; keep; keep = !keep)
int array[] = { 1, 2, 3, 4, 5 };
FOREACH(int x, array, 2, 5)
printf("index: %d. element: %d\n", i, x);
आउटपुट:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
यदि आप फ़ंक्शन पॉइंटर्स के साथ काम करने की योजना बना रहे हैं
#define lambda(return_type, function_body)\
({ return_type __fn__ function_body __fn__; })
#define array_len(arr) (sizeof(arr)/sizeof(arr[0]))
#define foreachnf(type, item, arr, arr_length, func) {\
void (*action)(type item) = func;\
for (int i = 0; i<arr_length; i++) action(arr[i]);\
}
#define foreachf(type, item, arr, func)\
foreachnf(type, item, arr, array_len(arr), func)
#define foreachn(type, item, arr, arr_length, body)\
foreachnf(type, item, arr, arr_length, lambda(void, (type item) body))
#define foreach(type, item, arr, body)\
foreachn(type, item, arr, array_len(arr), body)
उपयोग:
int ints[] = { 1, 2, 3, 4, 5 };
foreach(int, i, ints, {
printf("%d\n", i);
});
char* strs[] = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%s\n", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%s\n", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
लेकिन मुझे लगता है कि यह केवल gcc (निश्चित नहीं) पर काम करेगा।
C का कार्यान्वयन नहीं होता है for-each
। एक बिंदु के रूप में एक सरणी को पार्स करते समय रिसीवर को पता नहीं होता है कि सरणी कितनी लंबी है, इस प्रकार यह बताने का कोई तरीका नहीं है कि आप सरणी के अंत तक कब पहुंचते हैं। याद रखें, सी मेंint*
में एक स्मृति पते का एक बिंदु है जिसमें एक int है। कोई पूर्णांक वस्तु नहीं है जिसमें इस बात की जानकारी हो कि कितने पूर्णांक अनुक्रम में रखे गए हैं। इस प्रकार, प्रोग्रामर को इस पर नज़र रखने की आवश्यकता है।
हालांकि, सूचियों के लिए, for-each
लूप जैसा दिखने वाला कुछ लागू करना आसान है ।
for(Node* node = head; node; node = node.next) {
/* do your magic here */
}
सरणियों के लिए समान कुछ हासिल करने के लिए आप दो चीजों में से एक कर सकते हैं।
निम्नलिखित ऐसी संरचना का एक उदाहरण है:
typedef struct job_t {
int count;
int* arr;
} arr_t;
foreach
" क्या?