რას ნიშნავს int main გ. განსხვავება int main() და int main(void) შორის? ფორმალური და ფაქტობრივი პარამეტრები

ფუნქცია მთავარი.

ყველა C და C++ პროგრამას უნდა ჰქონდეს მთავარი ფუნქცია; და თქვენზეა დამოკიდებული სად განათავსებთ მას. ზოგიერთი პროგრამისტი მას ათავსებს ფაილის დასაწყისში, ზოგი კი ბოლოს. თუმცა, მიუხედავად მისი პოზიციისა, თქვენ უნდა გახსოვდეთ შემდეგი: არგუმენტები "მთავარი" ფუნქციისთვის. Borland C++ დაწყების პროცედურა აგზავნის სამ პარამეტრს (არგუმენტს) მთავარ ფუნქციას: argc, argv და env. - argc, მთელი რიცხვი, არის მთავარ ფუნქციაზე გაგზავნილი ბრძანების ხაზის არგუმენტების რაოდენობა, - argv არის სტრიქონების მაჩვენებლების მასივი (char *). DOS 3.x-ში და შემდეგში, argv განისაზღვრება, როგორც გასაშვები პროგრამის სრული გზა. DOS-ის ადრინდელი ვერსიით გაშვებისას, argv მიუთითებს null სტრიქონზე (""). argv მიუთითებს პირველ ბრძანების ხაზზე პროგრამის სახელის შემდეგ. argv მიუთითებს მეორე ბრძანების სტრიქონზე პროგრამის სახელის შემდეგ. argv მიუთითებს მთავარზე გაგზავნილ ბოლო არგუმენტზე. argv შეიცავს NULL-ს. - env ​​ასევე არის სტრიქონების მაჩვენებლების მასივი. თითოეული env ელემენტი შეიცავს ENVVAR=მნიშვნელობის ფორმის სტრიქონს. ENVVAR არის გარემოს ცვლადის სახელი, როგორიცაა PATH ან 87.<значение>ეს არის მოცემული გარემოს ცვლადის მნიშვნელობა, მაგალითად C:\DOS;C:\TOOLS (PATH-ისთვის) ან YES (87-ისთვის). ამასთან, გაითვალისწინეთ, რომ თუ თქვენ მიუთითებთ ამ არგუმენტებიდან ზოგიერთს, თქვენ უნდა მიუთითოთ ისინი ამ თანმიმდევრობით: argc, argv, env. მაგალითად, შემდეგი არგუმენტების დეკლარაციები მოქმედებს: main() main(int argc) /* მოქმედებს, მაგრამ არა ძალიან კარგი */ main(int argc, char *argv) main(int argc, char *argv, char *env) მთავარი (int) დეკლარაცია argc) არც თუ ისე მოსახერხებელია, რადგან თუ იცით პარამეტრების რაოდენობა, თქვენ თვითონ არ გაქვთ მათზე წვდომა. env არგუმენტი ყოველთვის ხელმისაწვდომია environ გლობალური ცვლადის მეშვეობით. იხილეთ environ ცვლადი (მე-3 თავში) და putenv და getenv ფუნქციები (თავში 2). argc და argv პარამეტრები ასევე ხელმისაწვდომია _argc და _argv ცვლადების მეშვეობით. პროგრამის მაგალითი argc, argv და env გამოყენებით. ეს არის პროგრამის მაგალითი ARGS.EXE, რომელიც აჩვენებს მთავარ ფუნქციაზე გადაცემული არგუმენტების გამოყენების უმარტივეს გზას. /* ARGS.C პროგრამა */ #include #შეიცავს void main(int argc, char *argv, char *env) ( int i; printf("argc-ის მნიშვნელობა არის %d \n\n",argc); printf("ბრძანების ხაზი შეიცავს %d პარამეტრებს \n\ n" ,argc); for (i=0; i<=argc; i++) printf(" argv[%d]: %s\n",i,argv[i]); printf("Среда содержит следующие строки:\n"); for (i=0; env[i] != NULL; i++) printf(" env[%d]: %s\n",i,env[i]); return 0; } Предположим, что вы запускаете программу ARGS.EXE со следующей командной строкой: C:> args first_arg "არგი ბლანკებით" 3 4 "ბოლო ერთი" გაჩერება! გაითვალისწინეთ, რომ თქვენ შეგიძლიათ გაგზავნოთ არგუმენტი ბლანკებით ორმაგ ბრჭყალებში ჩასმით, როგორც ეს ნაჩვენებია პროგრამის გამოძახების მაგალითში „ბლანკებით“ და „ბოლო ერთის“ მაგალითში. პროგრამის გაშვების შედეგად მიიღებთ ასეთ რაღაცას: argc-ის მნიშვნელობა არის 7 ბრძანების ხაზი შეიცავს 7 პარამეტრს argv: c:\turboc\testargs.exe argv: first_arg argv: arg ცარიელი argv: 3 argv: 4 argv: ბოლო, მაგრამ ერთი argv: შეჩერდი! გარემო შეიცავს შემდეგ ხაზებს: env: COMSPEC=C:\COMMAND.COM env: PROMPT=$p $g env: PATH=C:\SPRINT;C:\DOS;C:\BC ბრძანების მაქსიმალური საერთო სიგრძე მთავარ ფუნქციაზე გაგზავნილი ხაზი (მათ შორის სივრცეები და თავად პროგრამის სახელი), არ უნდა აღემატებოდეს 128 სიმბოლოს; ეს არის DOS შეზღუდვები. ბრძანების ხაზის გაქცევის სიმბოლოები ბრძანების ხაზის არგუმენტები შეიძლება შეიცავდეს გაქცევის სიმბოლოებს. თუმცა, მათ შეუძლიათ გააფართოვონ ყველა ფაილის სახელი, რომელიც ემთხვევა არგუმენტს ისევე, როგორც ეს კეთდება, მაგალითად, DOS ასლის ბრძანებით. გაქცევის სიმბოლოების გამოსაყენებლად, თქვენი პროგრამის ლინკერთან დაკავშირებისას თქვენ უნდა შეიყვანოთ WILDARGS.OBJ ობიექტის ფაილი, რომელიც მოყვება Borland C++-ს. თუ WILDARGS.OBJ ფაილი ერთვის თქვენს პროგრამას, შეგიძლიათ გამოიყენოთ არგუმენტები, როგორიცაა "*.*" ბრძანების სტრიქონზე. ამ შემთხვევაში, ამ ნიღბის შესაბამისი ყველა ფაილის სახელები შეიტანება argv მასივში. argv მასივის მაქსიმალური ზომა დამოკიდებულია მხოლოდ დინამიური მეხსიერების არეალის ზომაზე. თუ მოცემული ნიღბისთვის შესაფერისი ფაილი არ მოიძებნა, მაშინ არგუმენტი გადაეცემა იმ ფორმით, რომელშიც ის იყო აკრეფილი ბრძანების ხაზზე. (ანუ მთავარ ფუნქციას გადაეცემა გაქცევის სიმბოლოების შემცველი სტრიქონი). ორმაგ ბრჭყალებში ჩასმული არგუმენტები ("...") არ არის გაფართოებული. მაგალითი. შემდეგი ბრძანებები ადგენს ARGS.C ფაილს და აკავშირებს მას WILDARGS.OBJ მოდულთან და შემდეგ გაუშვით მიღებული პროგრამა ARGS.EXE: bcc args wildarg.obj args C:\BORLANDC\INCLUDE\*.H "*.C" ARGS.EXE-ის გაშვებისას, პირველი არგუმენტი აფართოებს ყველა ფაილის სახელს H გაფართოებით Borland C++ INCLUDE დირექტორიაში. გაითვალისწინეთ, რომ ყველა ხაზი მოიცავს სრულ მარშრუტს (მაგალითად C:\TC\INCLUDE\ALLOC.H). *.C არგუმენტი არ არის გაფართოებული, რადგან იგი ჩასმულია ბრჭყალებში. თუ თქვენ მუშაობთ ინტეგრირებულ გარემოში (BC.EXE), მაშინ თქვენ უბრალოდ უნდა მიუთითოთ პროექტის მენიუში პროექტის ფაილის სახელი, რომელიც უნდა შეიცავდეს შემდეგ ხაზებს: ARGS WILDARGS.OBJ შემდეგ, "Run/Arguments"-ის გამოყენებით. " ბრძანებებს, თქვენ უნდა დააყენოთ ბრძანების ხაზის პარამეტრები. კომენტარი. თუ გსურთ გაქცევის სიმბოლოების დამუშავება ყოველთვის მოხდეს, ე.ი. იმისათვის, რომ WILDARGS.OBJ ავტომატურად იყოს დაკავშირებული ბმულის რედაქტორის მიერ, თქვენ უნდა შეცვალოთ თქვენი სტანდარტული C?.LIB ბიბლიოთეკა, რომ შეიცავდეს ფაილს WILDARGS.OBJ. ამისათვის ამოიღეთ SETARGV ბიბლიოთეკიდან და დაამატეთ WILDARGS. ეს შეიძლება გაკეთდეს შემდეგი ბრძანებებით (ვვარაუდობთ, რომ სტანდარტული ბიბლიოთეკები და WILDARGS.OBJ შეიცავს მიმდინარე დირექტორიაში): TLIB აღწერილია მე-7 თავში, Utilities, მომხმარებლის სახელმძღვანელოს. tlib cs -setargv +wildargs tlib cc - setargv +wildargs tlib cm -setargv +wildargs tlib cl -setargv +wildargs tlib ch -setargv +wildargs კომპილაცია -p გადამრთველის გამოყენებით (პასკალის გამოძახების კონვენცია) თუ თქვენ შეადგენთ თქვენს პროგრამას პასკალის გამოძახების კონვენციის გამოყენებით (დაწვრილებით აღწერილია მე-9 თავში". ინტერფეისი ასამბლეის ენასთან“, „პროგრამის სახელმძღვანელო“), უნდა გახსოვდეთ, რომ მთავარი ფუნქცია აშკარად უნდა იყოს გამოცხადებული, როგორც C ფუნქცია. ეს შეიძლება გაკეთდეს გამოყენებით საკვანძო სიტყვა cdecl არის დაახლოებით ასეთი: cdecl main(int argc, char *argv, char *env) ძირითადი ფუნქციის მიერ დაბრუნებული მნიშვნელობა. მთავარი ფუნქცია აბრუნებს მნიშვნელობას, რომელიც არის პროგრამის გასასვლელი კოდი: ეს არის მთელი რიცხვი. თუმცა, თუ თქვენი პროგრამა გამოსასვლელად იყენებს exit (ან _exit) ფუნქციას, მაშინ დაბრუნებული მნიშვნელობა იქნება ამ ფუნქციის არგუმენტი. მაგალითად, თუ თქვენი პროგრამა შეიცავს გამოძახებას: exit(1), მაშინ გასასვლელი კოდი იქნება 1. თუ იყენებთ Borland C++ ინტეგრირებულ გარემოს (BC.EXE) პროგრამის გასაშვებად, მაშინ შეგიძლიათ ნახოთ მთავარის დაბრუნების მნიშვნელობა. ფუნქცია "ფაილი | ინფორმაციის მიღება" არჩევით.

გვერდი 53 85-დან

1.5.3. პარამეტრების გადაცემა მთავარ ფუნქციაზე

ძირითადი ფუნქცია, რომელიც იწყებს C პროგრამის შესრულებას, შეიძლება განისაზღვროს გარე გარემოდან გადაცემული პარამეტრებით, მაგალითად, ბრძანების სტრიქონიდან. გარე გარემოს აქვს მონაცემთა წარმოდგენის საკუთარი წესები, უფრო სწორად, ყველა მონაცემი წარმოდგენილია სიმბოლოების სტრიქონების სახით. ამ სტრიქონების მთავარ ფუნქციაზე გადასაცემად გამოიყენება ორი პარამეტრი, პირველი პარამეტრი გამოიყენება გადასაცემი სტრიქონების რაოდენობის გადასაცემად, მეორე გამოიყენება თავად სტრიქონების გადასაცემად. ამ პარამეტრების საერთო (მაგრამ არა აუცილებელი) სახელებია argc და argv. argc პარამეტრი არის int ტიპის, მისი მნიშვნელობა ყალიბდება ბრძანების ხაზის ანალიზიდან და უდრის ბრძანების სტრიქონზე სიტყვების რაოდენობას, მათ შორის გამოძახებული პროგრამის სახელს (სიტყვა არის ნებისმიერი ტექსტი, რომელიც არ შეიცავს სივრცეს. პერსონაჟი). argv პარამეტრი არის მაჩვენებლების მასივი სტრიქონებზე, თითოეული შეიცავს ერთ სიტყვას ბრძანების სტრიქონიდან. თუ სიტყვა უნდა შეიცავდეს ინტერვალის სიმბოლოს, ის უნდა იყოს ჩასმული ბრჭყალებში ბრძანების ხაზში ჩაწერისას.

მთავარ ფუნქციას ასევე შეიძლება ჰქონდეს მესამე პარამეტრი, რომელსაც ჩვეულებრივ უწოდებენ argp და რომელიც ემსახურება მთავარ ფუნქციაში გადატანას ოპერაციული სისტემის (გარემო) პარამეტრების, რომელშიც პროგრამა შესრულებულია C პროგრამირების ენაზე.

ძირითადი ფუნქციის სათაური ასე გამოიყურება:

თუ, მაგალითად, პროგრამის ბრძანების ხაზი C პროგრამირების ენაზე ასე გამოიყურება:

A:\>cprog მუშაობს "C პროგრამა" 1

შემდეგ არგუმენტები argc, argv, argp წარმოდგენილია მეხსიერებაში, როგორც ეს ნაჩვენებია დიაგრამაზე 1-ში.

არგკ[4]
argv --> -->
-->
-->
-->
argp --> -->
-->
-->
-->
ნახ.1. ბრძანების ხაზის პარამეტრების განლაგება

ოპერაციული სისტემა მხარს უჭერს მნიშვნელობების გადაცემას argc, argv, argp პარამეტრებისთვის და მომხმარებლის პასუხისმგებლობაა გადასცეს და გამოიყენოს ფაქტობრივი არგუმენტები მთავარ ფუნქციაზე.

შემდეგი მაგალითი არის პროგრამა, რომელიც ბეჭდავს მთავარ ფუნქციაზე გადაცემულ ფაქტობრივ არგუმენტებს ოპერაციული სისტემისა და ოპერაციული სისტემის პარამეტრებიდან.

მაგალითი:
int main (int argc, char *argv, char *argp)
(int i=0;
printf("\nპროგრამის სახელი %s", argv);
ამისთვის (i=1; i>=argc; i++)
printf("\n არგუმენტი %d არის %s", argv[i]);
printf("\nოპერაციული სისტემის პარამეტრები:");
ხოლო (*argp)
( printf ("\n %s",*argp);
argp ++;
}
დაბრუნება (0);
}

ოპერაციული სისტემის პარამეტრებზე წვდომა ასევე შესაძლებელია geteuv ბიბლიოთეკის ფუნქციის გამოყენებით; მისი პროტოტიპი ასე გამოიყურება:

char *geteuv (const char *varname);

ამ ფუნქციის არგუმენტი განსაზღვრავს გარემოს პარამეტრის სახელს, რომლის მნიშვნელობის მაჩვენებელი დაბრუნდება geteuv ფუნქციით. თუ მითითებული პარამეტრი ამჟამად არ არის განსაზღვრული გარემოში, დაბრუნების მნიშვნელობა არის NULL.

geteuv ფუნქციით მიღებული მაჩვენებლის გამოყენებით, თქვენ შეგიძლიათ წაიკითხოთ მხოლოდ ოპერაციული სისტემის პარამეტრის მნიშვნელობა, მაგრამ არ შეგიძლიათ მისი შეცვლა. puteuv ფუნქცია გამოიყენება სისტემის პარამეტრის მნიშვნელობის შესაცვლელად.

C პროგრამირების ენის შემდგენელი აშენებს C პროგრამას ისე, რომ პროგრამის დასაწყისში შესრულდეს გარკვეული ინიციალიზაცია, მათ შორის, მთავარ ფუნქციაზე გადაცემული არგუმენტების დამუშავება და გარემოს პარამეტრების მნიშვნელობების გადაცემა. ამ მოქმედებებს ასრულებენ ბიბლიოთეკის ფუნქციები _setargv და _seteuv, რომლებიც ყოველთვის თავსდება მთავარი ფუნქციის წინ კომპილატორის მიერ.

თუ პროგრამა C პროგრამირების ენაზე არ იყენებს არგუმენტების და ოპერაციული სისტემის პარამეტრების მნიშვნელობების გადაცემას, მაშინ მიზანშეწონილია აიკრძალოს ბიბლიოთეკის ფუნქციების _setargv და _seteuv გამოყენება პროგრამირების ენაში C პროგრამაში განთავსებით, ძირითადი ფუნქციის წინ, ფუნქციები იგივე სახელებით, მაგრამ რომლებიც არ ასრულებენ არანაირ მოქმედებას (სტუბები). პროგრამის დასაწყისი ამ შემთხვევაში ასე გამოიყურება:

setargv ()
}
-seteuv()
( დაბრუნება ; /* ცარიელი ფუნქცია */
}
int main()
( /* ძირითადი ფუნქცია არგუმენტების გარეშე */
...
...
renurn (0);
}

ზემოაღნიშნულ პროგრამაში ბიბლიოთეკის ფუნქციების _setargv და _seteuv გამოძახებისას გამოყენებული იქნება მომხმარებლის მიერ პროგრამაში განთავსებული ფუნქციები და არ შეასრულებს არანაირ მოქმედებას. ეს მნიშვნელოვნად შეამცირებს შედეგად მიღებული exe ფაილის ზომას.

Borland C++ მხარს უჭერს სამ არგუმენტს main(). პირველი ორი არის ტრადიციული argc და argv. ეს არის მთავარი ()-ის ერთადერთი არგუმენტები, რომლებიც განსაზღვრულია ANSI C სტანდარტით. ისინი საშუალებას აძლევს ბრძანების ხაზის არგუმენტების გადაცემას პროგრამაში. ბრძანების ხაზის არგუმენტები არის ინფორმაცია, რომელიც მიჰყვება პროგრამის სახელს ოპერაციული სისტემის ბრძანების ხაზზე. მაგალითად, როდესაც პროგრამა შედგენილია Borland ხაზის შემდგენელის გამოყენებით, ის ჩვეულებრივ აკრეფილია bcc პროგრამის_სახელი

სად პროგრამის_სახელიარის პროგრამა, რომელიც საჭიროებს კომპილაციას. პროგრამის სახელი არგუმენტად გადაეცემა შემდგენელს.

argc პარამეტრი შეიცავს ბრძანების ხაზის არგუმენტების რაოდენობას და არის მთელი რიცხვი. ის ყოველთვის უდრის მინიმუმ 1-ს, ვინაიდან პროგრამის სახელი კვალიფიცირდება როგორც პირველი არგუმენტი. argv პარამეტრი არის მაჩვენებელი სიმბოლოების მაჩვენებლების მასივის მიმართ. ამ მასივის თითოეული ელემენტი მიუთითებს ბრძანების ხაზის არგუმენტზე. ბრძანების ხაზის ყველა არგუმენტი არის სტრიქონები. პროგრამის მიერ ყველა ნომერი გარდაიქმნება შიდა ფორმატში. შემდეგი პროგრამა ბეჭდავს "Hello"-ს, რასაც მოჰყვება მომხმარებლის სახელი პროგრამის სახელის შემდეგ პირდაპირ აკრეფისას:

#შეიცავს

{
if (argc!=2)
{
printf ("თქვენ დაგავიწყდათ თქვენი სახელის აკრეფა\n");
დაბრუნება 1;
}
printf("გამარჯობა %s", argv);
დაბრუნება 0;
}

თუ ამ პროგრამის სახელს უწოდებთ და მომხმარებლის სახელია სერგეი, მაშინ პროგრამის დასაწყებად უნდა აკრიფოთ:
სახელი სერგეი.
პროგრამის შედეგად გამოჩნდება შემდეგი:
"გამარჯობა სერგეი."

ბრძანების ხაზის არგუმენტები უნდა იყოს გამოყოფილი ინტერვალით ან ჩანართებით. მძიმეები, მძიმით და მსგავსი სიმბოლოები არ განიხილება გამიჯვნად. Მაგალითად:

შედგება სამი ხაზისგან, ხოლო

ჰერბი, რიკი, ფრედი

ეს არის ერთი ხაზი - მძიმეები არ არის გამსაზღვრელი.

თუ თქვენ გჭირდებათ სტრიქონის გადაცემა, რომელიც შეიცავს სივრცეებს ​​ან ჩანართებს, როგორც ერთ არგუმენტს, უნდა ჩართოთ ის ორმაგ ბრჭყალებში. მაგალითად, ეს არის ერთი არგუმენტი:

"ეს ტესტია"

მნიშვნელოვანია argv-ის სწორად გამოცხადება. ყველაზე ტიპიური მეთოდია:

ცარიელი ფრჩხილები მიუთითებს, რომ მასივს არ აქვს ფიქსირებული სიგრძე. შეგიძლიათ წვდომა ინდივიდუალური ელემენტები argv ინდექსირების გამოყენებით. მაგალითად, argv მიუთითებს პირველ ხაზზე, რომელიც ყოველთვის შეიცავს პროგრამის სახელს. argv მიუთითებს შემდეგ ხაზზე და ასე შემდეგ.

ქვემოთ მოცემულია ბრძანების ხაზის არგუმენტების გამოყენების მცირე მაგალითი. ის ითვლის ბრძანების სტრიქონზე მითითებული მნიშვნელობიდან და გამოსცემს სიგნალს, როდესაც ის მიაღწევს ნულს. გაითვალისწინეთ, რომ პირველი არგუმენტი შეიცავს რიცხვს, რომელიც გარდაიქმნება მთელ რიცხვად სტანდარტული atoi() ფუნქციის გამოყენებით. თუ სტრიქონი "ჩვენება" არის მეორე არგუმენტად, მაშინ თავად მრიცხველი გამოჩნდება ეკრანზე.

/* დათვლის პროგრამა */

#შეიცავს
#შეიცავს
#შეიცავს
int main (int argc, char *argv)
{
int disp, დათვლა;
თუ (არგგ<2)
{
printf("თქვენ უნდა შეიყვანოთ დათვლის სიგრძე\n");
printf("ბრძანების სტრიქონზე. სცადეთ ისევ.\n");
დაბრუნება 1;
}
if (argc==3 && !strcmp(argv,"ჩვენება")) disp = 1;
else disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d ", count);
printf("%c", "\a"); /* უმეტეს კომპიუტერებზე ეს არის ზარი */
დაბრუნება 0;
}

გთხოვთ გაითვალისწინოთ, რომ თუ არგუმენტები არ არის მითითებული, შეცდომის შეტყობინება გამოჩნდება. ეს ყველაზე ტიპიურია პროგრამებისთვის, რომლებიც იყენებენ ბრძანების არგუმენტებს ინსტრუქციების გასაცემად, თუ მცდელობა იყო პროგრამის გაშვება სწორი ინფორმაციის გარეშე.

ბრძანების ცალკეულ სიმბოლოებზე წვდომისთვის, დაამატეთ მეორე ინდექსი argv-ს. მაგალითად, შემდეგი პროგრამა ბეჭდავს ყველა არგუმენტს, რომლითაც გამოიძახეს, თითო სიმბოლოთი:

#შეიცავს
int main (int argc, char *argv)
{
int t, i;
for(t=0; t {
i = 0;
ხოლო (argv[t][i])
{
printf("%c", argv[t][i]);
}
printf ("");
}
დაბრუნება 0;
}

უნდა გვახსოვდეს, რომ პირველი ინდექსი არის სტრიქონზე წვდომისთვის, ხოლო მეორე არის სიმბოლოზე წვდომისთვის.

როგორც წესი, argc და argv გამოიყენება წყაროს ბრძანებების მისაღებად. თეორიულად შესაძლებელია გქონდეთ 32767-მდე არგუმენტი, მაგრამ ოპერაციული სისტემების უმეტესობა არ გაძლევთ საშუალებას მიუახლოვდეთ ამას. როგორც წესი, ეს არგუმენტები გამოიყენება ფაილის სახელის ან ვარიანტების დასაზუსტებლად. ბრძანების ხაზის არგუმენტების გამოყენება პროგრამას აძლევს პროფესიონალურ იერს და საშუალებას აძლევს პროგრამას გამოიყენოს პარტიულ ფაილებში.

თუ თქვენ შეიცავს Borland C++-ით მოწოდებულ WILDARGS.OBJ ფაილს, შეგიძლიათ გამოიყენოთ შაბლონები *.EXE ტიპის არგუმენტებში. (Borland C++ ავტომატურად ამუშავებს ბუნებრივ ბარათებს და შესაბამისად ზრდის argc-ს.) მაგალითად, თუ დააკავშირებთ WILDARGS.OBJ შემდეგ პროგრამას, ის გეტყვით რამდენი ფაილი ემთხვევა ბრძანების სტრიქონში მითითებულ ფაილის სახელს:

/* დააკავშირეთ ეს პროგრამა WILDARGS.OBJ */

#შეიცავს
int main (int argc, char *argv)
{
რეგისტრაცია int i;
printf("%d ფაილი ემთხვევა მითითებულ სახელს\n", argc-1);
printf("ისინი არიან:");
for(i=1; i printf("%s", argv[i]);
დაბრუნება 0;
}

თუ ამ პროგრამას ვუწოდებთ WA, შემდეგ გავუშვით შემდეგნაირად, მივიღებთ ფაილების რაოდენობას EXE გაფართოებით და ამ ფაილების სახელების ჩამონათვალს:

გარდა argc და argv, Borland C++ ასევე უზრუნველყოფს მესამე ბრძანების არგუმენტს -env. env პარამეტრი საშუალებას აძლევს პროგრამას წვდომა ჰქონდეს ინფორმაცია ოპერაციული სისტემის გარემოს შესახებ. env პარამეტრი უნდა შეესაბამებოდეს argc და argv და გამოცხადებულია შემდეგნაირად:

როგორც ხედავთ, env დეკლარირებულია ისევე, როგორც argv. ისევე, როგორც argv, ის არის სტრიქონების მასივის მაჩვენებელი. თითოეული ხაზი არის ოპერაციული სისტემის მიერ განსაზღვრული გარემოს სტრიქონი. env პარამეტრს არ აქვს ეკვივალენტური argc პარამეტრი, რომელიც გვიჩვენებს გარემოს რამდენი მწკრივია. ამის ნაცვლად, გარემოს ბოლო ხაზი ნულოვანია. შემდეგი პროგრამა ბეჭდავს ოპერაციულ სისტემაში ამჟამად განსაზღვრულ გარემოს ყველა სტრიქონს:

/* ეს პროგრამა აჩვენებს გარემოს ყველა ხაზს */

#შეიცავს
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]/ t++)
printf("%s\n", env[t]);
დაბრუნება 0;
}

გთხოვთ გაითვალისწინოთ, რომ მიუხედავად იმისა, რომ argc და argv არ გამოიყენება პროგრამაში, ისინი უნდა იყოს წარმოდგენილი პარამეტრების სიაში. C არ იცის პარამეტრების სახელები. ამის ნაცვლად, მათი გამოყენება განისაზღვრება პარამეტრების დეკლარირებული თანმიმდევრობით. სინამდვილეში, თქვენ შეგიძლიათ დარეკოთ პარამეტრი რაც გსურთ. ვინაიდან argc, argv და env ტრადიციული სახელებია, უმჯობესია გააგრძელოთ მათი გამოყენება ისე, რომ ნებისმიერმა, ვინც კითხულობს პროგრამას, დაუყოვნებლივ გაიგოს, რომ ეს არის main() ფუნქციის არგუმენტები.

პროგრამებისთვის ტიპიური ამოცანაა გარემოს სტრიქონში განსაზღვრული მნიშვნელობის ძიება. მაგალითად, PATH ხაზის შინაარსი პროგრამებს საშუალებას აძლევს გამოიყენონ საძიებო ბილიკები. შემდეგი პროგრამა გვიჩვენებს, თუ როგორ უნდა იპოვოთ სტრიქონები, რომლებიც აცხადებენ სტანდარტულ საძიებო ბილიკებს. ის იყენებს ბიბლიოთეკის სტანდარტულ ფუნქციას strstr(), რომელსაც აქვს შემდეგი პროტოტიპი:

Char *strstr(const char *str1, const char *str2);

strstr() ფუნქცია ეძებს str1-ით მითითებულ სტრიქონს str2-ით მითითებულ სტრიქონში. თუ ასეთი სტრიქონი მოიძებნება, უბრუნდება მაჩვენებელი პირველ პოზიციას. თუ შესატყვისები არ არის ნაპოვნი, ფუნქცია აბრუნებს NULL-ს.

/* პროგრამა ეძებს გარემოს სტრიქონებს შორის ხაზს, რომელიც შეიცავს PATH */

#შეიცავს
#შეიცავს
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]; t++)
{
if (strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
დაბრუნება 0;
}

ნებისმიერი C პროგრამა იწყება main() ფუნქციის გამოძახებით. ეს ფუნქცია უნდა იყოს ყველა პროგრამაში.

ნებისმიერი სხვა ფუნქციის მსგავსად, main() ფუნქციას შეიძლება ჰქონდეს პარამეტრები. ზოგჯერ პროგრამის დაწყებისას სასარგებლოა მას გარკვეული ინფორმაციის გადაცემა. ეს ინფორმაცია გადაეცემა main()-ს ბრძანების ხაზის არგუმენტების გამოყენებით. ბრძანების ხაზის არგუმენტები– ეს არის ინფორმაცია, რომელიც შეიტანება ბრძანების სტრიქონში პროგრამის სახელის შემდეგ, როდესაც პროგრამა გაშვებულია პროგრამის განვითარების გარემოს გარეთ შესასრულებლად. მაგალითად, task.cpp ფაილის არქივის დასაწყებად, თქვენ უნდა აკრიფოთ შემდეგი ბრძანების ხაზზე:

winrar archTasktask.cpp // winrar.exe archTaskამოცანა.cpp

სადაც winrar არის არქივის პროგრამის სახელი და ხაზები " », « archTask"და" დავალება. cpp» წარმოადგენს ბრძანების არგუმენტებს, რომლებიც ეუბნებიან პროგრამას შექმნას არქივი (" ") სახელით archTaskერთი ფაილიდან დავალება. cpp.

ძირითადი() ფუნქციაზე პარამეტრების გადაცემისას ის ასე უნდა განისაზღვროს:

int main(int argc, char *argv) ( ) // ან void main(...)()

argc პარამეტრი შეიცავს არგუმენტების რაოდენობას ბრძანების სტრიქონზე და არის მთელი რიცხვი და ის ყოველთვის არის მინიმუმ 1, რადგან პირველი არგუმენტი ყოველთვის არის პროგრამის სახელი (პროგრამის სახელი პროგრამის სრული ბილიკით).

argv პარამეტრი არის მაჩვენებელი მაჩვენებლების მასივის მიმართ. ამ მასივში, თითოეული ელემენტი მიუთითებს მომდევნო ბრძანების არგუმენტზე. ცარიელი კვადრატული ფრჩხილები მიუთითებს, რომ მასივს განუსაზღვრელი სიგრძე აქვს. ცალკეულ არგუმენტებზე წვდომა შეგიძლიათ argv მასივის ინდექსირებით. მაგალითად, argv მიუთითებს პირველი სიმბოლოს სტრიქონზე, რომელიც ყოველთვის არის პროგრამის სახელი; argv მიუთითებს პირველ არგუმენტზე და ა.შ. არგუმენტების სია შემოიფარგლება NULL-ით, ე.ი. argv == NULL.

ბრძანების ერთ-ერთი არგუმენტის ინდივიდუალურ სიმბოლოზე წვდომისთვის, თქვენ უნდა გამოიყენოთ მეორე ინდექსი argv-ში. ანუ პირველი ინდექსი argv უზრუნველყოფს წვდომას სტრიქონზე, ხოლო მეორე ინდექსი უზრუნველყოფს მის ცალკეულ სიმბოლოებზე წვდომას.

ბრძანების ხაზის ყველა არგუმენტი არის სტრიქონები, ამიტომ რიცხვითი პარამეტრების სასურველ ფორმატში გადაყვანა უნდა იყოს გათვალისწინებული პროგრამაში მისი შემუშავებისას.

პროგრამის მაგალითი სიმბოლურ ფორმატში რიცხვების მთელ და რეალურ რიცხვებად გადაქცევის სხვადასხვა გზით:

#შეიცავს

#შეიცავს

// გაშვებისას ვაყენებთ, მაგალითად, შემდეგ არგუმენტებს: 100 2.7

void main(int a, char *b) (

k = strtol(b, &ptr, 10); // ptr = შეცდომის მისამართი ხაზში

f = strtod(b, &ptr);

sscanf(b, "%d", &k);

sscanf(b, "%lf", &f);

სახელები argc და argv ტრადიციულია, მაგრამ არ არის აუცილებელი. ამ ორ პარამეტრს main() ფუნქციაში შეიძლება ეწოდოს როგორც მოგწონთ.

ბრძანების ხაზის არგუმენტების გამოყენების მარტივი მაგალითი:

int main (int argc, char *argv) (

თუ (argc != 4) (

printf("პროგრამის გაშვების არასწორი პარამეტრები!\n");

k = atoi(argv); // რიცხვის პარამეტრის კონვერტაცია

printf("გამარჯობა, %s %d წლის %s ჯგუფიდან",

თუ პროგრამის სახელია ამოცანა, და თქვენი სახელია "ვასია", ჯგუფი "PM-11" პირველი წლიდან, მაშინ პროგრამის დასაწყებად უნდა შეიყვანოთ ბრძანების სტრიქონში:

დავალება ვასია PM-11 1

პროგრამის შესრულების შედეგად ეკრანზე გამოჩნდება შემდეგი შეტყობინება: „გამარჯობა, ვასია 1-ლი წლის PM-11 ჯგუფიდან“.

გთხოვთ გაითვალისწინოთ, რომ თუ ბრძანების ხაზის ყველა არგუმენტი არ არის მოწოდებული, გამოჩნდება შეცდომის შეტყობინება. პროგრამები, რომლებიც იღებენ ბრძანების ხაზის არგუმენტებს, ხშირად აკეთებენ შემდეგს: როდესაც მომხმარებელი აწარმოებს ამ პროგრამებს საჭირო ინფორმაციის შეყვანის გარეშე, ისინი აჩვენებს ინსტრუქციებს არგუმენტების სწორად მითითების შესახებ.

ბრძანების ხაზის არგუმენტები უნდა იყოს გამოყოფილი ინტერვალით. თუ არგუმენტში არის სივრცეები, მაშინ იმისათვის, რომ თავიდან აიცილოს მრავალი არგუმენტი, ეს არგუმენტი უნდა იყოს ჩასმული ორმაგ ბრჭყალებში. შედეგად, მთელი ციტირებული სტრიქონი ჩაითვლება ერთ არგუმენტად. მაგალითად, პროგრამის გაშვება შეიძლება ასე: დავალება „ვასია და პეტია“ PM-21 2. პროგრამის შესრულების შედეგად ეკრანზე გამოჩნდება შეტყობინება: „გამარჯობა, ვასია და პეტია მე-2 კურსიდან PM- 21 ჯგუფი."

რა არის char *argv? ეს მასივი, რომლის ელემენტებია მაჩვენებლები, ანუ მაჩვენებლების მასივი. ეს ნიშნავს, რომ პარამეტრების main()-ზე გადაცემისას შეიძლება განისაზღვროს ასე:

void main(int argc, char **argv) (

დავალება. აჩვენეთ ბრძანების ხაზის ყველა არგუმენტი (არ არის საჭირო პროგრამის სახელის ჩვენება).

#შეიცავს

void main (int argc, char *argv)(

ამისთვის (i = 1; i< argc; i++)

printf("%s\n", argv[i]);

მეორე ვარიანტი =================

#შეიცავს

void main(int argc, char **argv)(

while((p=*argv) != NULL) (

printf("%s\n", p);

როგორც წესი, ბრძანების ხაზის არგუმენტები გამოიყენება პროგრამისთვის საწყისი მონაცემების მიწოდებისთვის, რომელიც მას დასჭირდება გაშვებისას (მაგალითად, ბრძანების ხაზის არგუმენტები ხშირად გადასცემენ მონაცემებს, როგორიცაა ფაილის სახელი ან პროგრამის გაშვების პარამეტრები).

როდესაც პროგრამას არ სჭირდება ბრძანების ხაზის პარამეტრები, main() ფუნქცია იყენებს void საკვანძო სიტყვას მის პარამეტრთა სიაში (ან უბრალოდ არაფერს აკონკრეტებს).

როგორ ხდება გამართვა ძვ.წ. პროგრამები, რომლებიც საჭიროებენ ბრძანების არგუმენტებს. მენიუში Run→Arguments... უნდა შეიყვანოთ ბრძანების ხაზის არგუმენტები. არ არის საჭირო პროგრამის სახელის მითითება. შემდეგ შეგიძლიათ უბრალოდ გაუშვათ და გამართოთ პროგრამა განვითარების გარემოში, როგორც ყოველთვის.

გთხოვთ შეაჩეროთ AdBlock ამ საიტზე.

მაშ, რატომ გვჭირდება პერსონალური ფუნქციები? საჭიროა მომხმარებლის მიერ განსაზღვრული ფუნქციები, რათა პროგრამისტებს გაუადვილონ პროგრამების დაწერა.

გახსოვდეთ, ჩვენ ვისაუბრეთ პროგრამირების პარადიგმებზე, უფრო სწორედ სტრუქტურირებულ პროგრამირებაზე. მთავარი იდეა იყო, რომ ნებისმიერი პროგრამის დაწერა შესაძლებელია მხოლოდ სამი ძირითადი კონსტრუქტის გამოყენებით: follow, condition და loop. ახლა ჩვენ დავამატებთ კიდევ ერთს ამ სტრუქტურებს - „ქვეპროგრამებს“ - და მივიღებთ ახალ პარადიგმას პროცედურული პროგრამირება".

ერთადერთი განსხვავება ისაა, რომ ჩვენ დავწერთ ჩვენი ძირითადი პროგრამის ცალკეულ ნაწილებს (კერძოდ, განმეორებით) ცალკეული ფუნქციების სახით (ქვეპროგრამები, პროცედურები) და საჭიროებისამებრ მოვუწოდებთ მათ. არსებითად, პროგრამა ახლა აღწერს სხვადასხვა ფუნქციების ურთიერთქმედებას.

ასე რომ, ამ გაკვეთილში დეტალურად განვიხილავთ, თუ როგორ არის აგებული ფუნქციები შიგნით. ჩვენ ასევე ვისწავლით როგორ შევქმნათ ჩვენი საკუთარი ფუნქციები.

როგორ მუშაობს ფუნქციები

გავიხსენოთ ინფორმაცია პირველი გაკვეთილიდან. ყველა ფუნქცია, მათ შორის მომხმარებლის მიერ დაწერილი, მოწყობილია ანალოგიურად. მათ აქვთ ორი ძირითადი ნაწილი: ფუნქციის სათაური და ფუნქციის სხეული.

ჩამონათვალი 1.

Int main(void)( // ფუნქციის სათაური // ფუნქციის სხეული იწერება ხვეული ბრეკეტებით)

ფუნქციის სხეულში ყველაფერი ნათელია: ის აღწერს ფუნქციის ალგორითმს. მოდით შევხედოთ სათაურს. იგი შედგება სამი სავალდებულო ნაწილისგან:

  • დაბრუნების ტიპი;
  • ფუნქციის სახელი;
  • ფუნქციის არგუმენტები.

პირველ რიგში, დაბრუნების ტიპი იწერება, მაგალითად, int, როგორც მთავარ ფუნქციაში. თუ ფუნქციამ არ უნდა დააბრუნოს რაიმე მნიშვნელობა პროგრამაში, მაშინ საკვანძო სიტყვა void იწერება ამ ადგილას. როგორც ჩანს, რადგან ფუნქცია არაფერს აბრუნებს, მაშინ არაფრის დაწერა არ არის საჭირო. ადრე, სხვათა შორის, ეს კეთდებოდა C ენაზე, მაგრამ შემდეგ დაამატეს ეს ერთგვაროვნებისთვის. დღესდღეობით, თანამედროვე შემდგენელები გასცემენ გაფრთხილებებს/შეცდომებს, თუ არ მიუთითებთ დაბრუნების ტიპს.
ზოგიერთ პროგრამირების ენაში ფუნქციებს, რომლებიც არ აბრუნებენ რაიმე მნიშვნელობას, ეწოდება პროცედურები (მაგალითად, პასკალი). უფრო მეტიც, არსებობს სხვადასხვა სინტაქსი ფუნქციებისა და პროცედურების შესაქმნელად. C ენაში ასეთი დისკრიმინაცია არ არსებობს.

ფუნქციის სახელი იწერება დაბრუნების ტიპის შემდეგ. ისე, სახელის შემდეგ მითითებულია არგუმენტების ტიპები და რაოდენობა, რომლებიც გადაეცემა ფუნქციას.

მოდით გადავხედოთ უკვე ნაცნობი ფუნქციების სათაურებს.

ჩამონათვალი 2.

// ფუნქცია სახელად srand, რომელიც იღებს მთელ რიცხვს, არაფერს აბრუნებს void srand(int) // ფუნქცია სახელად sqrt, რომელიც იღებს რეალურ float-ს, აბრუნებს float float sqrt(float) // ფუნქცია სახელად rand, რომელიც არ იღებს არგუმენტებს, აბრუნებს მთელ რიცხვს int rand(void) //ფუნქცია სახელად pow, რომელიც იღებს double ტიპის ორ არგუმენტს, აბრუნებს ტიპის ნამდვილ რიცხვს double double pow(double, double)

როგორ შევქმნათ საკუთარი ფუნქცია

იმისათვის, რომ შექმნათ თქვენი საკუთარი ფუნქცია, თქვენ უნდა სრულად აღწეროთ იგი. აქ მოქმედებს ზოგადი წესი: გამოყენებამდე განაცხადეთ და აღწერეთ როგორ უნდა იმუშაოს. ამისათვის დავუბრუნდეთ პროგრამის სტრუქტურის დიაგრამას C ენაზე, რომელიც გვქონდა პირველივე გაკვეთილზე. მოდით აღვნიშნოთ მასზე ის ადგილები, სადაც ფუნქციების აღწერაა შესაძლებელი.

სურ.1 პროგრამის სტრუქტურის დაზუსტება. ფუნქციების დეკლარაცია.

როგორც ხედავთ, არის ორი ადგილი, სადაც ეს შეიძლება გაკეთდეს.

მოდით შევხედოთ მაგალითს, რომელიც ასახავს მორგებული ფუნქციის შექმნას ორი რიცხვის მაქსიმუმის გამოსათვლელად.

ჩამონათვალი 3.

#შეიცავს // გამოაცხადეთ მორგებული ფუნქცია სახელად max_num // შეყვანა: ორი მთელი პარამეტრი სახელად a და b // გამომავალი: ორი არგუმენტის მაქსიმუმი int max_num(int a, int b)( int max = b; თუ (a > b) max = a; დაბრუნება max; ) //მთავარი პროგრამა int main(void) ( int x = 0, y = 0; int m = 0; scanf("%d %d", &x, &y); m = max_num( x ,y); printf("max(%d,%d) = %d\n",x,y,m); დაბრუნება 0;)

ნება მომეცით დეტალურად აღვწერო როგორ იმუშავებს ეს პროგრამა. ძირითადი ფუნქციის სხეული შესრულებულია. იქმნება მთელი რიცხვები x, y და m. ცვლადები x და y იკითხება კლავიატურიდან. ვთქვათ, შევიყვანეთ 3 5, შემდეგ x = 3, y = 5. ეს ყველაფერი თქვენთვის გასაგები უნდა იყოს. ახლა შემდეგი ხაზი

ჩამონათვალი 4.

M = max_num (x,y);

ცვლადი m უნდა მიენიჭოს იმას, რაც არის = ნიშნის მარჯვნივ. ჩვენ გვაქვს ფუნქციის სახელი, რომელიც ჩვენ თვითონ შევქმენით. კომპიუტერი ეძებს ამ ფუნქციის დეკლარაციას და აღწერას. იგი მდებარეობს ზემოთ. ამ დეკლარაციის მიხედვით, ამ ფუნქციამ უნდა მიიღოს ორი მთელი მნიშვნელობა. ჩვენს შემთხვევაში, ეს არის x და y ცვლადებში ჩაწერილი მნიშვნელობები. იმათ. 3 და 5 ნომრები. გთხოვთ გაითვალისწინოთ, რომ ფუნქციას გადაეცემა არა თავად x და y ცვლადები, არამედ მხოლოდ მნიშვნელობები (ორი რიცხვი) ინახება მათში. ის, რაც რეალურად გადაეცემა ფუნქციას პროგრამაში გამოძახებისას, ეწოდება ფუნქციის ფაქტობრივი პარამეტრები.

ახლა max_num ფუნქცია იწყებს შესრულებას. პირველი ნაბიჯი არის ცალკე დროებითი ცვლადის შექმნა თითოეული პარამეტრისთვის, რომელიც აღწერილია ფუნქციის სათაურში. ჩვენს შემთხვევაში იქმნება ორი მთელი ცვლადი სახელწოდებით a და b. ამ ცვლადებს ენიჭებათ რეალური პარამეტრების მნიშვნელობები. თავად პარამეტრებს, რომლებიც აღწერილია ფუნქციის სათაურში, ეწოდება ფორმალურ პარამეტრებს. ასე რომ, ფორმალურ პარამეტრებს a და b ენიჭება ფაქტობრივი პარამეტრების მნიშვნელობები 3 და 5, შესაბამისად. ახლა a = 3, b = 5. ფუნქციის შიგნით ჩვენ შეგვიძლია ვიმუშაოთ ამ ცვლადებთან ისე, თითქოს ისინი ჩვეულებრივი ცვლადები იყვნენ.

იქმნება მთელი რიცხვი ცვლადი სახელად max და ენიჭება მნიშვნელობა b. შემდეგ მოწმდება a > b პირობა. თუ ეს მართალია, მაშინ მაქსიმალური ცვლადის მნიშვნელობა უნდა შეიცვალოს .

შემდეგ მოდის return განაცხადი, რომელიც გამომძახებელ პროგრამას (მთავარ ფუნქციას) უბრუნებს მაქსიმალურ ცვლადში ჩაწერილ მნიშვნელობას, ე.ი. 5 . რის შემდეგაც ცვლადები a, b და max ამოღებულია მეხსიერებიდან. და ჩვენ ვუბრუნდებით ხაზს

ჩამონათვალი 5.

M = max_num (x,y);

max_num ფუნქციამ დააბრუნა მნიშვნელობა 5, რაც ნიშნავს, რომ ახლა არის 5 დაწერილი = ნიშნის მარჯვნივ. ეს მნიშვნელობა იწერება m ცვლადზე. შემდეგ ხაზი გამოჩნდება ეკრანზე და პროგრამა მთავრდება.

კიდევ ერთხელ ყურადღებით წაიკითხეთ ბოლო 4 აბზაცი, რომ სრულად გაიგოთ როგორ მუშაობს პროგრამა.

იმავდროულად, მე გეტყვით, რატომ არის საჭირო ფუნქციების აღწერის ქვედა ბლოკი. წარმოიდგინეთ, რომ თქვენს პროგრამაში დაწერეთ 20 პატარა ფუნქცია. და ყველა მათგანი აღწერილია მთავარ ფუნქციამდე. ამდენი ხნის განმავლობაში მთავარ პროგრამაზე მოხვედრა არც ისე მოსახერხებელია. ამ პრობლემის გადასაჭრელად, ფუნქციები შეიძლება აღწერილი იყოს ქვედა ბლოკში.

მაგრამ შეუძლებელი იქნება მთელი ფუნქციის კოდის უბრალოდ გადატანა იქ, რადგან მაშინ დაირღვევა წესი: სანამ რამეს გამოიყენებ, უნდა გამოაცხადო. ამ პრობლემის თავიდან ასაცილებლად, თქვენ უნდა გამოიყენოთ ფუნქციის პროტოტიპი.

ფუნქციის პროტოტიპი მთლიანად იმეორებს ფუნქციის სათაურს, რასაც მოჰყვება; . ზედა ბლოკში პროტოტიპის მითითების შემდეგ, ქვედა ნაწილში უკვე შეგვიძლია სრულად აღვწეროთ ფუნქცია. ზემოთ მოყვანილი მაგალითისთვის შეიძლება ასე გამოიყურებოდეს:

ჩამონათვალი 6.

#შეიცავს int max_num(int, int); int main(void) ( int x =0, y = 0; int m = 0; scanf ("%d %d", &x, &y); m = max_num(x,y); printf("max(%d ,%d) = %d\n",x,y,m); დაბრუნება 0; ) int max_num(int a, int b)( int max = b; if (a > b) max = a; დაბრუნება max; )

ყველაფერი ძალიან მარტივია. გთხოვთ გაითვალისწინოთ, რომ ფუნქციის პროტოტიპში არ არის აუცილებელი ფორმალური პარამეტრების სახელების მითითება, საკმარისია უბრალოდ მიუთითოთ მათი ტიპები. ზემოთ მოყვანილ მაგალითში მე ზუსტად ასე გავაკეთე.