1

Тема: як організувати правильний вихід з циклу?

Завдання полягає в тому щоб з одного файлу(в якому є текст якоїсь програми) в інший перекопіювати функцію main.
Як правильно зробити вихід з циклу,де я по суті повинен перевіряти баланс дужок,і якшо кількість лівих дорівнює кількості правих,що означає кінець функціїї мейн,виходити з цього циклу.(функція search)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void Open(FILE**, FILE**);
void Search(FILE*,FILE*, char*);
void Copy(FILE*, FILE*);

int main()
{
    system("chcp 1251");

    FILE* Read, * Write;
    char* p1 = (char*)malloc(151);
    Open(&Read, &Write);
    Search(Read,Write, p1);
    Copy(Read, Write);

    fclose(Read);
    fclose(Write);
    free(p1);

    system("pause");
    return 0;
}

void Open(FILE** Reading, FILE** Writing)
{
    if ((*Reading = fopen("D:\\textlab\\lab07.txt", "r")) == NULL)
    {
        puts("Файл не вдалось відкрити");
        system("pause");
        exit(0);
    }

    *Writing = fopen("D:\\textlab\\main-fun.c", "w");
}

void Search(FILE* Reading,FILE* Writing, char* strings)
{
    while (fgets(strings, 150, Reading)) 
    {
        if (strstr(strings, " main ") || strstr(strings, " main(") || strstr(strings, " main\n"))
            break;
    }
    fputs(strings, Writing);
}

void Copy(FILE * Reading, FILE * Writing)
{
    int L = 0;
    int R = 0;
    int tmp;
    do
    {
        tmp = fgetc(Reading);
        if (tmp == '{')
             L += 1;
        if (tmp == '}')
             R += 1;
        fputc(tmp, Writing);

        
    } while (1);
    
}

2

Re: як організувати правильний вихід з циклу?

Можете зробити while(L>R), але легше тримати лише одну змінну, яка позначає вкладеність:

    int nesting = 0;
    do
    {
        char tmp = fgetc(Reading);
        fputc(tmp, Writing);
        if (tmp == '{')
             ++nesting;
        else if (tmp == '}')
             --nesting;
    } while (nesting > 0);

3

Re: як організувати правильний вихід з циклу?

хороша ідея,до неї я теж дійшов.Однак є варіанти,коли після main є 1 або декілька ентерів,що робить даний цикл не робочим.

koala написав:

Можете зробити while(L>R), але легше тримати лише одну змінну, яка позначає вкладеність:

    int nesting = 0;
    do
    {
        char tmp = fgetc(Reading);
        fputc(tmp, Writing);
        if (tmp == '{')
             ++nesting;
        else if (tmp == '}')
             --nesting;
    } while (nesting > 0);

4 Востаннє редагувалося koala (06.06.2019 22:24:04)

Re: як організувати правильний вихід з циклу?

Чому? fgetc має читати всі символи, і '\n' також.
А, ви маєте на увазі, що цикл може початися до того, як ви прочитаєте '{'?
Ну так додайте ще один цикл на початку, до '{'. Чи (трохи гірше) ще однією змінною відстежуйте, чи прочитали ви вже '{'.

5

Re: як організувати правильний вихід з циклу?

Що ви маєте на увазі під додати цикл на початку?

koala написав:

Чому? fgetc має читати всі символи, і '\n' також.
А, ви маєте на увазі, що цикл може початися до того, як ви прочитаєте '{'?
Ну так додайте ще один цикл на початку, до '{'. Чи (трохи гірше) ще однією змінною відстежуйте, чи прочитали ви вже '{'.

6

Re: як організувати правильний вихід з циклу?

Хоча в загальному вигляді, звісно, це все не працюватиме.
Накидав тут: https://ideone.com/7hF6hR

#include <stdio.h>

int main(void);
void print1()
{
    /*JOKE1!*/
    printf("Go1!\n");
}
//This macro wrappes real main(){/*JOKE2!*/} function
#define pain main
void print2()
{
    /*JOKE3!*/
    printf("Go2!\n");
}
#define main_decl int pain(void){            \
    /*REAL1?*/                               \
    printf("Starting main(){/*JOKE4!*/}\n"); \
    __main();                                \
    printf("Out of main\n");                 \
}

main_decl

#define main __main

int main()
{
    /*REAL2?*/
    print1();
    print2();
    return 0;
}

Який саме код ви хочете скопіювати - REAL1 чи REAL2? Обидва мають право зватися "main". Але скопіюєте ви, швидше за все, JOKE1.

Подякували: leofun011

7

Re: як організувати правильний вихід з циклу?

не дуже зрозумів що тут і до чого

koala написав:

Хоча в загальному вигляді, звісно, це все не працюватиме.
Накидав тут: https://ideone.com/7hF6hR

#include <stdio.h>

int main(void);
void print1()
{
    /*JOKE1!*/
    printf("Go1!\n");
}
//This macro wrappes real main(){/*JOKE2!*/} function
#define pain main
void print2()
{
    /*JOKE3!*/
    printf("Go2!\n");
}
#define main_decl int pain(void){            \
    /*REAL1?*/                               \
    printf("Starting main(){/*JOKE4!*/}\n"); \
    __main();                                \
    printf("Out of main\n");                 \
}

main_decl

#define main __main

int main()
{
    /*REAL2?*/
    print1();
    print2();
    return 0;
}

Який саме код ви хочете скопіювати - REAL1 чи REAL2? Обидва мають право зватися "main". Але скопіюєте ви, швидше за все, JOKE1.

8

Re: як організувати правильний вихід з циклу?

Що я маю на увазі:

do
{
        char tmp = fgetc(Reading);
        fputc(tmp, Writing);
} while(tmp!='{');
int nesting = 1;
do{...}
Подякували: svyatvasik1

9

Re: як організувати правильний вихід з циклу?

Розбираємо.
JOKE1 - у нас іде передоголошення main, після якого починається функція print1. Ваш пошук скопіює саме його.
JOKE2 - коментар із неправильним тілом функції main. Утім, ваш код навіть його не захопить, бо не розраховує на { в тому ж рядку, що й main.
JOKE3 - проголошуємо макрос main, після якого іде функція print2. Знову ж таки, ризикуємо захопити тіло print2.
JOKE4/REAL1 - Тут дві пастки одночасно (мені було ліньки розкладати). Ми проголосили макрос pain, який замінюється на main, а тепер створюємо функцію pain і щось у ній робимо. Цей pain - це реальна функція main, але вона в макросі, тому її важко знайти. Зате в ній є стрічка, що містить "проголошення" main, яке теж можна прийняти за справжній main.
REAL2 - pain викликає __main; а далі проголошується макрос main -> __main - тобто та функція, що зветься main, буде замінена на обгортку pain і викликана з неї.
А ще можна проголосити локальну змінну main:

for(int main=(0);main<10;++main){printf("%d",main);}
Подякували: leofun011

10

Re: як організувати правильний вихід з циклу?

непогана ідея.Дякую!

koala написав:

Що я маю на увазі:

do
{
        char tmp = fgetc(Reading);
        fputc(tmp, Writing);
} while(tmp!='{');
int nesting = 1;
do{...}

11 Востаннє редагувалося leofun01 (07.06.2019 06:44:11)

Re: як організувати правильний вихід з циклу?

svyatvasik написав:

з одного файлу(в якому є текст якоїсь програми) в інший перекопіювати функцію main.

Це досить складна задача, для якої треба знати, що таке граматика і автомат.

Функція може бути записана по різному.
1)

int main() { }

2)

int main(int argc, char *argv[]) { }

3)

void f() {
    char const *s = "int main() { }";
}
int main() {
    {
        {
            // ...
        }
    }
}

4)

void f(){char const *s="int main(){}";}int main(){}

upd: Спочатку ляпнув, а потім подивився що інші пишуть.
В koala гарніший приклад.

Подякували: koala1

12

Re: як організувати правильний вихід з циклу?

саме через цю різноманітність я і пишу сюди

leofun01 написав:
svyatvasik написав:

з одного файлу(в якому є текст якоїсь програми) в інший перекопіювати функцію main.

Це досить складна задача, для якої треба знати, що таке граматика і автомат.

Функція може бути записана по різному.
1)

int main() { }

2)

int main(int argc, char *argv[]) { }

3)

void f() {
    char const *s = "int main() { }";
}
int main() {
    {
        {
            // ...
        }
    }
}

4)

void f(){char const *s="int main(){}";}int main(){}

upd: Спочатку ляпнув, а потім подивився що інші пишуть.
В koala гарніший приклад.

13

Re: як організувати правильний вихід з циклу?

Та koala, то взагалі, місцевий супергерой, ви на нього не дуже дивіться, а то ще самооцінка впаде

14

Re: як організувати правильний вихід з циклу?

leofun01 написав:

Функція може бути записана по різному.

Я б для початку уточнив, це має бути ф-я main із
світу С++ чи з Сі, бо навіть тут є деякі відмінності.

Далі саме завдання поставлене не ясно, не відома кінцева
ціль, чого саме хоче ТС? То вам потрібно просто перекопіювати
ф-ю з одного файлу в інший, а вже в іншому рядку, ви чуть не
збираєтесь писати синтаксичне дерево =.=
Знову ж таки не ясно для чого? Цей перекопійований код згодом
будуть проганяти через компілятор?

15

Re: як організувати правильний вихід з циклу?

adziri написав:

Я б для початку уточнив, це має бути ф-я main із
світу С++ чи з Сі, бо навіть тут є деякі відмінності.

Не настільки, щоб це суттєво щось змінило. Десь void, десь int - але яка різниця, ми виходимо з того, що код коректний.

16 Востаннє редагувалося wander (07.06.2019 13:37:42)

Re: як організувати правильний вихід з циклу?

koala написав:
adziri написав:

Я б для початку уточнив, це має бути ф-я main із
світу С++ чи з Сі, бо навіть тут є деякі відмінності.

Не настільки, щоб це суттєво щось змінило. Десь void, десь int - але яка різниця, ми виходимо з того, що код коректний.

Різниця буде в залежності від того, що збираються робити з
перекопійованим кодом. Зрештою, коректним він має бути для
кого?)
Просто завдання дивне, я чомусь подумав, що ТС хоче не
лише "тупо" перекопійовувати, але нехай.

17

Re: як організувати правильний вихід з циклу?

Припускаю, що це навчальне завдання, "наближене до реальності" - щось знайти в реальному файлі за формальними ознаками.