أكثر برامج يعشقها برمجي لغه السي ، هي تلك البرامج التي لا يفهمها أي أحد ، حتى هم أنفسهم ، وعاده تطلق عليها برامج “مشوشه” Obfuscated وهناك بعض المسابقات تقام ، لأكثر برنامج “مشوش” ، وقد تكلمنا عن برامج الـ Obfuscated في هذا الموضوع .
برامج الـ Quines (في بعض الأحيان تسمى Self-Reproducing program ) تعتبر أحد أنواع البرامج المشوشه هذه ، ولها ثقلها في المسابقات الغريبه تلك ، الأسم quine أتي من أسم مخترعها الفيلسوف Willard Van Orman Quine وفكرتها في أن مخرج البرنامج هو نفسه السورس كود ،الصورة التالية تبين مخرج برنامج جافا وستجد أن المخرج هو نفسه الكود
لنلق نظره أكثر ، قم بنسخ هذا الكود وقم بتشغيله ، ويفضل تشغيله في Visual C++ لأن هناك التنفيذ لا ينتهي وتبقى الشاشه السوداء موجوده ، أو قم بوضعه في البيئه المفضله لديك ، ولا تنسى وضع system(“pause”) أو أي جمله أدخال getchar في نهايه البرنامج ، وقم بوضع جمله الأدخال أيضا داخل المصفوفه الحرفيه التي يحتوي على كود البرنامج ، وستلاحظ أنه أطول متغير في البرنامج . أو ريح نفسك وشغل البرنامج من نافذه الاوامر Command Prompt .
نعود الى برنامجنا ، لا تسألني عن مخرجاته
/* * Quine Program * Coded By : wajdy essam * Date : 08-09-2007 * This is Very Simple Form of Quine Program * I make it's easy for Beginners */ #include <stdio.h> void charAnalysis (const char ch[] ); int main () { int i; char programCode[] = "/*\n" " * Quine Program\n " "* Coded By : Romansy\n " "* Feed Back : SudanGeek@HotMail.com\n " "* Date : 08-09-2007\n " "* This is Very Simple Form Of Quine Program\n " "* I make it's easy for Beginners\n " "*/\n\n" "#include <stdio.h>\n\n" "void charAnalysis (const char ch[] ); \n\n" "int main () \n" "{\n" " int i;\n" " char programCode[] = \n ###; \n\n\n" " // Now Analysis Prgram char\n\n" " int i= 0;\n" " for (; programCode[i]; i++)\n " " { \n" " if ( programCode[i] == '#' && programCode[i+1] == '#'" " && programCode[i+2] == '#') \n" " {\n" " charAnalysis(programCode); \n" " i += 2; // skip second and third # \n" " }\n\n" " else \n" " printf(\"%c\",programCode[i]); \n" " } \n\n" " return 0;\n" "}\n" "void charAnalysis ( const char ch[] )\n" "{\n int i;\n printf(\" \\\" \");\n\n for (i=0; ch[i]; i++)\n" " {\n\n if ( ch[i] =='\\\\' )\n printf(\"\\\\\\\\\");\n\n" " else if ( ch[i] == '\"' )\n printf(\"\\\\\\\"\");\n\n" " else\n printf(\"%c\",ch[i]);\n\n if ( i % 49 == 47)\n" " printf(\"\\\"\\n \\\"\");\n }\n\n printf(\"\\\"\");\n\n}\n\n"; // Now Analysis Program char for ( i=0; programCode[i]; i++) { if ( programCode[i] == '#' && programCode[i+1] == '#' && programCode[i+2] == '#') { charAnalysis(programCode); i += 2; // skip second and third # } else printf("%c",programCode[i]); } return 0; } void charAnalysis ( const char ch[] ) { int i; printf(" \" "); for (i=0; ch[i]; i++) { if ( ch[i] =='\\' ) printf("\\\\"); else if ( ch[i] == '"' ) printf("\\\""); else if ( ch[i] == '\n' ) printf("\\n"); else printf("%c",ch[i]); if ( i % 49 == 47) printf("\"\n \""); } printf("\""); }
وهذا البرنامج أيضا من الـ Wikipeadia :
/* A simple quine (self-printing program), in standard C. */ /* Note: in designing this quine, we have tried to make the code clear * and readable, not concise and obscure as many quines are, so that * the general principle can be made clear at the expense of length. * In a nutshell: use the same data structure (called "progdata" * below) to output the program code (which it represents) and its own * textual representation. */ #include <stdio.h> void quote(const char *s) /* This function takes a character string s and prints the * textual representation of s as it might appear formatted * in C code. */ { int i; printf(" \""); for (i=0; s[i]; ++i) { /* Certain characters are quoted. */ if (s[i] == '\\') printf("\\\\"); else if (s[i] == '"') printf("\\\""); else if (s[i] == '\n') printf("\\n"); /* Others are just printed as such. */ else printf("%c", s[i]); /* Also insert occasional line breaks. */ if (i % 48 == 47) printf("\"\n \""); } printf("\""); } /* What follows is a string representation of the program code, * from beginning to end (formatted as per the quote() function * above), except that the string _itself_ is coded as two * consecutive '@' characters. */ const char progdata[] = "/* A simple quine (self-printing program), in st" "andard C. */\n\n/* Note: in designing this quine, " "we have tried to make the code clear\n * and read" "able, not concise and obscure as many quines are" ", so that\n * the general principle can be made c" "lear at the expense of length.\n * In a nutshell:" " use the same data structure (called \"progdata\"\n" " * below) to output the program code (which it r" "epresents) and its own\n * textual representation" ". */\n\n#include <stdio.h>\n\nvoid quote(const char " "*s)\n /* This function takes a character stri" "ng s and prints the\n * textual representati" "on of s as it might appear formatted\n * in " "C code. */\n{\n int i;\n\n printf(\" \\\"\");\n " " for (i=0; s[i]; ++i) {\n /* Certain cha" "racters are quoted. */\n if (s[i] == '\\\\')" "\n printf(\"\\\\\\\\\");\n else if (s[" "i] == '\"')\n printf(\"\\\\\\\"\");\n e" "lse if (s[i] == '\\n')\n printf(\"\\\\n\");" "\n /* Others are just printed as such. */\n" " else\n printf(\"%c\", s[i]);\n " " /* Also insert occasional line breaks. */\n " " if (i % 48 == 47)\n printf(\"\\\"\\" "n \\\"\");\n }\n printf(\"\\\"\");\n}\n\n/* What fo" "llows is a string representation of the program " "code,\n * from beginning to end (formatted as per" " the quote() function\n * above), except that the" " string _itself_ is coded as two\n * consecutive " "'@' characters. */\nconst char progdata[] =\n@@;\n\n" "int main(void)\n /* The program itself... */\n" "{\n int i;\n\n /* Print the program code, cha" "racter by character. */\n for (i=0; progdata[i" "]; ++i) {\n if (progdata[i] == '@' && prog" "data[i+1] == '@')\n /* We encounter tw" "o '@' signs, so we must print the quoted\n " " * form of the program code. */\n {\n " " quote(progdata); /* Quote all. */\n" " i++; /* Skip second '" "@'. */\n } else\n printf(\"%c\", p" "rogdata[i]); /* Print character. */\n }\n r" "eturn 0;\n}\n"; int main(void) /* The program itself... */ { int i; /* Print the program code, character by character. */ for (i=0; progdata[i]; ++i) { if (progdata[i] == '@' && progdata[i+1] == '@') /* We encounter two '@' signs, so we must print the quoted * form of the program code. */ { quote(progdata); /* Quote all. */ i++; /* Skip second '@'. */ } else printf("%c", progdata[i]); /* Print character. */ } return 0; }
لن أقوم بتشريح الكود ، فالمخرج واضح ، وعمليه شرح هذه الأكواد ، سوف يدخلنا في متاهات ، أفضل تجربه الكود بنفسك .
ينبغي معرفه أن مثل هذه البرامج تحتاج الى خطوتين فقط لعملها ، أول خطوه هي كتابه كود البرنامج كاملا بكل ما فيه تعليقات داخل مصفوفه من الحروف . الخطوه الثانيه هي كود لطباعه محتويات هذه المصفوفه الحرفيه (اي طباعه الكود الذي كتبناه في المصفوفه) ، وطباعتها على انها حروف أي كما هي (يأخذ هذه المصفوفه ويعالجها بطريقه ما ، سوف يطبعها) .
بشكل مبسط ننشيء مصفوفه s ونكتب فيها كود البرنامج كاملا ، من البدايه الى النهايه ،
لكن هناك نقطتان مهمتان ،
اولأ مثلا لدى جمله
printf("hello") ;
عندما أضعها داخل مصفوفه من الحروف ، يجب أن أضع علامه \ على كل من ” بداخل جمله الطباعه ، لأنني اذا لم أضعها سيعتبرها المترجم نهايه المصوفه .
نفس الكلام بالنسبه الى الاشاره \ عندما أريد أن اضعها ، أكتب \\ .
النطقه الثانيه ،
عندما أبدأ في كتابه الكود داخل المصفوفه ، وأصل الى نفس المتغير ، أضع علامه ما مثلا حرفين ## .هذه العلامه ضروريه لاننا هي بمثابه الجزء الذي أريد طباعته بالاضافه الى الكود .
الان في سأطبع المصفوفه الحرفيه كما هي ، ولانها تحتوي على الكود ، سينطبع الكود .
وفي خلال طباعه الكود ، سأطبع المصفوفه الحرفيه على أنها حروف ، أي أقوم باستبدال مثلا \n ب \\n حتى تطبع كما هي وبدون تنفيذها . متى أعرف أننا وصلنا ألى المصفوفه الحرفيه ونحن نطبع حروف في الأصل ، هل تذكر العلامتان ## وهن يشيران الى بدايه المصفوفه .
ربما لن تفهم أي شيء الى الأن -وهذا محتمل- لكن هذه هي برامج الـ Obfuscated ، أفضل طريقه هي كتابه البرنامج من الصفر بنفسك ، وستلاحظ مدى بساطه الفكره وسهولتها ، وصعوبه شرحها .
برنامج أخر ، قم بتشريحه بنفسك (مع العلم 34 تشير الى ” ) :
main() { char *s = "int main() { char* s = %c%s%c; printf(s, 34, s, 34); }"; printf(s, 34, s, 34); }
وهذه العشرات من البرامج في المرفق لسي و سي++ ، قم بتحميلها من هنا للتسليه .
اتذكر ان هناك مكتبات تطبع السورس كود بالكامل من خلال سطر واحد فقط
بدون الحاجة الى تلك المتاهات
المكتبات موجودة فى لغة السي وانا مازلت ابحث عن بديل لها فى لغة الجافا