প্রায় সমস্ত ভাষায় একটি foreach
লুপ বা অনুরূপ কিছু থাকে। সি আছে কি? আপনি কিছু উদাহরণ কোড পোস্ট করতে পারেন?
foreach
একটি সি প্রোগ্রামে একটি লুপ লেখার চেষ্টা করা কতটা কঠিন হত ?
প্রায় সমস্ত ভাষায় একটি foreach
লুপ বা অনুরূপ কিছু থাকে। সি আছে কি? আপনি কিছু উদাহরণ কোড পোস্ট করতে পারেন?
foreach
একটি সি প্রোগ্রামে একটি লুপ লেখার চেষ্টা করা কতটা কঠিন হত ?
উত্তর:
সি এর ভবিষ্যদ্বাণী নেই, তবে ম্যাক্রোগুলি প্রায়শই এটি অনুকরণ করতে ব্যবহৃত হয়:
#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);
}
সম্পাদনা করুন: আপনি যদি সি ++ সমাধানগুলিতেও আগ্রহী হন তবে, সি ++ এর জন্য প্রতিটি পরিসংখ্যানের জন্য "রেঞ্জ ভিত্তিক"
#define foreach(item, array) int count=0, size=sizeof(array)/sizeof(*(array)); for(item = (array); count != size; count++, item = (array)+count)
একটি সমস্যা যা আমি দেখতে পাচ্ছি তা হ'ল ভেরিয়েবলগুলি গণনা এবং আকার লুপের বাইরে লাইভ করে এবং সংঘাতের কারণ হতে পারে। আপনি লুপের জন্য দুটি ব্যবহার করার কারণে এটি কি? [কোডটি এখানে আটকানো হয়েছে ( পেস্টবিন.com / আইএমএনডিপিডব্লিউএস )]
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()
) এবং অন্যটির জন্য এটির সংজ্ঞাটির অভ্যন্তরের মানের একটি উল্লেখ রয়েছে। এটি সত্যিই এমন কিছু উদাহরণ যা খুব চতুর চালাক; কোডের উদ্দেশ্য জটিলভাবে এটি চতুরতা যুক্ত না করেই যথেষ্ট। কার্নিগানের অ্যাফোরিজম ( স্ট্যাকওভারফ্লো.com / প্রশ্নস / ১১১০৩৯৯/২ ) প্রযোজ্য!
সি তে কোন পূর্বাভাস নেই।
আপনি ডেটা দিয়ে লুপের জন্য লুপের জন্য ব্যবহার করতে পারেন তবে দৈর্ঘ্যটি জানতে হবে বা একটি জ্ঞাত মান (উদাহরণস্বরূপ নাল) দ্বারা ডেটাটি শেষ করা দরকার।
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 এক্সটেনশন, মান সি এর অংশ নয়আপনার কিছুটা সময় বাঁচাতে আপনি এখানে এটি পরীক্ষা করতে পারেন কীভাবে:
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;
}
ডিফল্টরূপে জিসিসি এবং ঝনঝনিতে কাজ বলে মনে হচ্ছে; অন্যান্য সংকলক পরীক্ষা করেনি।
এটি মোটামুটি পুরানো প্রশ্ন, তবে আমার যদিও এটি পোস্ট করা উচিত। এটি জিএনইউ সি 99 এর জন্য একটি অগ্রণী লুপ।
#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;
}
এই কোডটি জিএনইউ / লিনাক্সে জিসিসি, আইসিসি এবং ঝাঁকুনির সাথে কাজ করার জন্য পরীক্ষা করা হয়েছে।
যদিও প্রতিটি কন্সট্রাক্টের জন্য সি নেই, এটি সর্বদা অ্যারের শেষের জন্য একটি আইডোম্যাটিক উপস্থাপনা করেছে (&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++)
।
সি এর 'জন্য' এবং 'যখন' কীওয়ার্ড রয়েছে। যদি সি # এর মতো কোনও ভাষায় ভবিষ্যতবাণী বিবৃতিটি এরকম দেখায় ...
foreach (Element element in collection)
{
}
... তাহলে সি এর এই পূর্বাভাস বিবৃতিটির সমতুল্য হতে পারে:
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);
সম্পাদনা:FOREACH
নেমস্পেস দূষণ এড়াতে সি 99 সিনট্যাক্স ব্যবহারের জন্য এখানে একটি বিকল্প রয়েছে :
#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 হওয়ার পরে একবার বন্ধ হয়ে যাবে So সুতরাং এটি ব্যবহার করে double Array[]
সমস্ত উপাদানগুলির মধ্যে পুনরাবৃত্তি নাও হতে পারে। লুপ পরীক্ষাটি মনে হয় এক বা অন্যটি হওয়া উচিত: i<n
বা A[i]
। স্বচ্ছতার জন্য নমুনা ব্যবহারের ক্ষেত্রে যুক্ত করুন add
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
যায় যদি ব্যবহারকারী দুর্ঘটনাক্রমে 'i' এর চেয়ে বড় হয়ে 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);
তবে আমি মনে করি এটি কেবল জিসিসিতে কাজ করবে (নিশ্চিত নয়)।
সি এর কোন প্রয়োগ নেই for-each
। বিন্যাস হিসাবে একটি অ্যারে পার্স করার সময় রিসিভার জানেন না যে অ্যারে কত দীর্ঘ, সুতরাং আপনি অ্যারের শেষে পৌঁছানোর সময় কোনও উপায় নেই tell মনে রাখবেন, সি তেint*
তে একটি মেমরির ঠিকানার একটি বিন্দু থাকে containing অনুক্রমের মধ্যে কতগুলি পূর্ণসংখ্যা স্থাপন করা হয় সে সম্পর্কে তথ্য সহ কোনও শিরোনামের অবজেক্ট নেই। সুতরাং, প্রোগ্রামার এটি ট্র্যাক রাখা প্রয়োজন।
তবে তালিকার জন্য, 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
" কি?