السلام عليكم ،
أكثر برامج يعشقها برمجي لغه السي ، هي تلك البرامج التي لا يفهمها أي أحد ، حتى هم أنفسهم ، وعاده تطلق عليها برامج "مشوشه" Obfuscated وهناك بعض المسابقات تقام ، لأكثر برنامج "مشوش" .
برامج الـ Quines (في بعض الأحيان تسمى Self-Reproducing prgraom ) تعتبر أحد أنواع البرامج المشوشه هذه ، ولها ثقلها في المسابقات الغريبه تلك ، الأسم quine أتي من أسم مخترعها الفيلسوف Willard Van Orman Quine
لنلق نظره أكثر ، قم بنسخ هذا الكود وقم بتشغيله ، ويفضل تشغيله في Visual C++ لأن هناك التنفيذ لا ينتهي وتبقى الشاشه السوداء موجوده ، أو قم بوضعه في البيئه المفضله لديك ، ولا تنسى وضع system("pause") أو أي جمله أدخال getchar في نهايه البرنامج ، وقم بوضع جمله الأدخال أيضا داخل المصفوفه الحرفيه التي يحتوي على كود البرنامج ، وستلاحظ أنه أطول متغير في البرنامج .
أو ريح نفسك وشغل البرنامج من نافذه الاوامر Command Prompt .
نعود الى برنامجنا ، لا تسألني عن مخرجاته :) .
/*
* Quine Program
* Coded By : Romansy
* Feed Back : SudanGeek@HotMail.com
* Date : 08-09-2007
* This is Very Simple Form of Quine Prgraom
* 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++)\n "
" { \n"
" if ( programCode == '#' && 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); \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++)\n"
" {\n\n if ( ch =='\\\\' )\n printf(\"\\\\\\\\\");\n\n"
" else if ( ch == '\"' )\n printf(\"\\\\\\\"\");\n\n"
" else\n printf(\"%c\",ch);\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++)
{
if ( programCode == '#' && programCode[i+1] == '#' && programCode[i+2] == '#')
{
charAnalysis(programCode);
i += 2; // skip second and third #
}
else
printf("%c",programCode);
}
return 0;
}
void charAnalysis ( const char ch[] )
{
int i;
printf(" \" ");
for (i=0; ch; i++)
{
if ( ch =='\\' )
printf("\\\\");
else if ( ch == '"' )
printf("\\\"");
else if ( ch == '\n' )
printf("\\n");
else
printf("%c",ch);
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) {
/* Certain characters are quoted. */
if (s == '\\')
printf("\\\\");
else if (s == '"')
printf("\\\"");
else if (s == '\n')
printf("\\n");
/* Others are just printed as such. */
else
printf("%c", s);
/* 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) {\n /* Certain cha"
"racters are quoted. */\n if (s == '\\\\')"
"\n printf(\"\\\\\\\\\");\n else if (s["
"i] == '\"')\n printf(\"\\\\\\\"\");\n e"
"lse if (s == '\\n')\n printf(\"\\\\n\");"
"\n /* Others are just printed as such. */\n"
" else\n printf(\"%c\", s);\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 == '@' && 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); /* 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) {
if (progdata == '@' && 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); /* Print character. */
}
return 0;
}لن أقوم بتشريح الكود ، فالمخرج واضح :) ، وعمليه شرح هذه الأكواد ، سوف يدخلنا في متاهات ، أفضل تجربه الكود بنفسك .
ينبغي معرفه أن مثل هذه البرامج تحتاج الى خطوتين فقط لعملها ، أول خطوه هي كتابه كود البرنامج كاملا بكل ما فيه تعليقات داخل مصفوفه من الحروف . الخطوه الثانيه هي كود لطباعه محتويات هذه المصفوفه الحرفيه (اي طباعه الكود الذي كتبناه في المصفوفه) ، وطباعتها على انها حروف أي كما هي (يأخذ هذه المصفوفه ويعالجها بطريقه ما ، سوف يطبعها) .
بشكل مبسط ننشيء مصفوفه s ونكتب فيها كود البرنامج كاملا ، من البدايه الى النهايه ،
لكن هناك نقطتان مهمتان ،
اولأ مثلا لدى جمله
printf("hello") ;
عندما أضعها داخل مصفوفه من الحروف ، يجب أن أضع علامه \ على كل من " بداخل جمله الطباعه ، لأنني اذا لم أضعها سيعتبرها المترجم نهايه المصوفه .
نفس الكلام بالنسبه الى الاشاره \ عندما أريد أن اضعها ، أكتب \\ .
النطقه الثانيه ،
عندما أبدأ في كتابه الكود داخل المصفوفه ، وأصل الى نفس المتغير ، أضع علامه ما مثلا حرفين ## .هذه العلامه ضروريه لاننا هي بمثابه الجزء الذي أريد طباعته بالاضافه الى الكود .
الان في سأطبع المصفوفه الحرفيه كما هي ، ولانها تحتوي على الكود ، سينطبع الكود .
وفي خلال طباعه الكود ، سأطبع المصفوفه الحرفيه على أنها حروف ، أي أقوم باستبدال مثلا \n ب \\n حتى تطبع كما هي وبدون تنفيذها . متى أعرف أننا وصلنا ألى المصفوفه الحرفيه ونحن نطبع حروف في الأصل ، هل تذكر العلامتان ## وهن يشيران الى بدايه المصفوفه .
ربما لن تفهم أي شيء الى الأن -وهذا محتمل- لكن هذه هي برامج الـ
Obfuscated :) ، أفضل طريقه هي كتابه البرنامج من الصفر بنفسك ، وستلاحظ مدى بساطه الفكره وسهولتها ، وصعوبه شرحها :) .
برنامج أخر ، قم بتشريحه بنفسك (مع العلم 34 تشير الى " ) :
int main() { char *s = "int main() { char* s = %c%s%c; printf(s, 34, s, 34); }"; printf(s, 34, s, 34); }وهذه العشرات من البرامج في المرفق لسي و سي++ ، قم بتحميلها للتسليه .
أتمنى أن يكون الموضوع غير مكرر ، بحثت بالقسم قبل طرحه ووجدت من سأل هنا في القسم ، ولم يجد إجابه
Happy Quine :)