Программа работает только в режиме отладки, но не в обычном exe (используя c lion)?

Итак, я создал программу, которая преобразует инфикс в пост-фикс и префикс, который отлично работает. Дело в том, что я использую C-LION у которого есть свой отладчик, который позволяет мне идти шаг за шагом, и я делаю, что программа работает нормально и выводит ожидаемые результаты, НО затем, когда я запускаю ее нормально, ОНА НЕ РАБОТАЕТ И ДАЕТ МНЕ ОШИБКА "main.c не работает".

Это основная функция, которая имеет меню:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <tgmath.h>

char*infixToPostfix(char *infinx);
char* postixToinfix(char *infinx);
char* postixToprefix(char *infinx);
char* prefixToinfix(char *infinx);
char* prefixTopostfix(char *infinx);
char* infixToPrefix(char *infinx);
char*evaluate(char *infinx );
int exp_det(char*exp);
typedef struct node
{
    char *op;
    int  p;
    struct node *next; /* Pointer to the next node. Notice that the
    existence of the structure tag enables us to declare its type. */
} node;
node *head=NULL; /* Global pointer that always points to the head of the
    stack. */
int precedence(char symbol);
void add_stack(const node *p);
void pop(void);
int main(void)
{
    char postfix[100];
    int choice;
    //converting from ininfinx to postfix
    printf("\t\t***** Conversion Calculator 1.0 ******\t\t\n");
    printf("\t\t1.Convert\n\t\t2.Evaluate\n\t\t3.Exit\nEnter Choice : ");
    scanf("%d",&choice);
    //switch (choice){
        if (choice==1) {
            printf("\n\t\t1.Input from File\n\t\t2.standered  input\nEnter Choice :");
            int ch2;
            scanf("%d", &ch2);
            switch (ch2) {
                case 1:
                    printf("FILE MANGAMENT STILL NOT DONE !!!");
                    break;
                case 2:
                    printf("Enter Expression : ");
                    char line[256];


                    scanf(" %[^\n]s", postfix);
                    char in2[100] = {'\0'};
                    char in3[100] = {'\0'};
                    char *conv;
                    char *conv2;

                    strcpy(in2, postfix);
                    strcpy(in3, postfix);
                    int exp = exp_det(in2);

                    if (exp == 1) {
                        printf("\nThis is a Prefix expression do you want to\n\t\t1.Infix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
                        int ch3;
                        scanf("%d", &ch3);
                        switch (ch3) {
                            case 1:
                                conv = prefixToinfix(in3);
                                printf("Expression in Infix form: %s \n", in3);
                                break;
                            case 2:
                                conv = prefixTopostfix(in3);
                                printf("Expression in Postfix form: %s \n", in3);
                                break;
                            case 3:
                                conv = prefixToinfix(in3);
                                conv2 = prefixTopostfix(postfix);
                                printf("Expression in Infix form: %s \n", conv);
                                printf("Expression in Postfix form: %s \n", conv2);
                                break;
                            default:
                                printf("ERROROR WHEN EXPRESSION IN PREFIX ");

                                break;
                        }
                    } else if (exp == 2) {
                        printf("\nThis is a Infix expression do you want to\n\t\t1.Prefix\n\t\t2.Postfix\n\t\t3.Both\nEnter Choice :");
                        int ch3;
                        scanf("%d", &ch3);
                        switch (ch3) {
                            case 1:
                                printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
                                break;
                            case 2:
                                printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
                                break;
                            case 3:
                                printf("Expression in prefix form: %s \n", infixToPrefix(postfix));
                                printf("Expression in Postfix form: %s \n", infixToPostfix(postfix));
                                break;
                            default:
                                printf("ERROROR R");

                                break;
                        }
                    } else if (exp == 3) {
                        printf("This is a Postfix expression do you want to\n\t\t1.Infix\n\t\t2.Prefix\n\t\t3.Both\nEnter Choice :");
                        int ch3;
                        scanf("%d", &ch3);
                        switch (ch3) {
                            case 1:
                                printf("Expression in Infix form: %s \n", postixToinfix(postfix));
                                break;
                            case 2:
                                printf("Expression in prefix form: %s \n", postixToprefix(postfix));
                                break;
                            case 3:
                                printf("Expression in Infix form: %s \n", postixToinfix(postfix));
                                printf("Expression in Prefix form: %s \n", postixToprefix(postfix));
                                break;
                            default:
                                printf("ERROR... 3:(\n");
                                break;
                        }
                    }
                    break;//for the switch with ch2 case 1
                default:
                    printf("ERROR... 2:(\n");
                    break;
            }
            //break;
        }if(choice==2) {
        printf("Enter Expression : ");

        scanf(" %[^\n]s", postfix);
        char in2[100] = {'\0'};
        char in3[100] = {'\0'};
        char *conv;
        char *conv2;

        strcpy(in2, postfix);
        conv = evaluate(in2);
        printf("\nExpression evaluated = %s \n", conv);
        //break;
    }if(choice==3) {
        printf("BYE...... :D\n");


    }

    system("PAUSE");
}

OK Теперь, после долгих испытаний, я начинаю думать, что проблема в самой конвертации. Это одна из функций, которые я использую, для меня это выглядит нормально. Если у кого-то есть другое мнение, помощь очень приветствуется.

char* infixToPostfix(char *infinx){
char* token;

char * infinx1=malloc(sizeof(infinx)+1);

infinx1=strcpy(infinx1,infinx);

token = strtok(infinx1," ");

char* res;
res=malloc(sizeof(infinx)+sizeof(head->op)*strlen(infinx));

strcpy(res," ");

if(*token=='\n' ){token=strtok(NULL," ");}

while( token != NULL ) {

    node n;
    n.op=token;
    n.p=precedence(*token);
    if(isalpha(*token) || isdigit(*token)){
        // strcat(result,infinx[i]);
        //printf("%c",infinx[i]);

        res=strcat(res,token);
        res=strcat(res," ");
    }
        //case when encounter a left paranthessisis
    else if(*token=='(' || *token==')'){
        if (*token=='('){
            add_stack(&n);
        }else if(*token==')') {

            while (*head->op != '(') {
                // strcat(result, n.op);
                //printf("%c",(char)head->op);
                res=strcat(res,head->op);
                res=strcat(res," ");
                pop();
            }
            pop();
        }
    }
        //if head if null meaning the stack is empty or if the presendance of the head is less thatn or equal to new character
    else if(head==NULL || head->p < n.p ){
        if (head->p == n.p){}
        add_stack(&n);
    }
        //in case the head has higher presendance he we pop and print untill we reach the same presedance
    else  {
        while( head!=NULL && head->p >= n.p){
            //strcat(result,n.op);
            //printf("%c",(char)head->op);
            res=strcat(res,head->op);
            res=strcat(res," ");
            pop();
        }
        add_stack(&n);
    }
    token=strtok(NULL," ");
}
while(head!=NULL){
    //strcat(result,head->op);
    //printf("%c",(char)head->op);
    res=strcat(res,head->op);
    res=strcat(res," ");
    pop();
}
return res;

}


person usama zidan    schedule 19.12.2017    source источник
comment
Как ты его нормально запускаешь? Похоже, вы пытаетесь запустить main.c, а не исполняемый файл   -  person Chris Turner    schedule 19.12.2017
comment
обычно вы имеете в виду нажатие значка запуска в среде IDE или запуск созданного выходного файла через ваш каталог или терминал?   -  person Angen    schedule 19.12.2017
comment
Да, я имею в виду запуск с помощью значка запуска в среде IDE.   -  person usama zidan    schedule 19.12.2017
comment
У вас очень странный способ объявления переменных во вложенных операторах case. Мой компилятор не может понять, используются они или нет. Или если они объявлены когда используются. Например, если ch2 == 2 какие-то переменные объявлены, а если exp == 1 и ch3 == 3 они могут быть использованы? И у вас есть несколько переменных ch3, чтобы полностью запутать нас. Я не удивлюсь, если ваш компилятор тоже запутается.   -  person Bo Persson    schedule 19.12.2017
comment
Итак, вы говорите, что я должен определить их вне оператора switch? @БоПерссон   -  person usama zidan    schedule 19.12.2017
comment
"main.c not working " - возможно, main.c бастует? или праздник?   -  person 0___________    schedule 19.12.2017
comment
@PeterJ_01, возможно, тебе тоже стоит отдохнуть от Интернета   -  person usama zidan    schedule 19.12.2017
comment
Работа в режиме отладки, но не без нее — классический симптом UB. Неинициализированные vars, доступ к массиву за пределами границ, отсутствующие NUL-терминаторы и тому подобное.   -  person Martin James    schedule 19.12.2017
comment
по поводу: scanf(" %[^\n]s", postfix); это не сработает. Поскольку ввод не будет иметь «буквального» s в качестве первого символа в следующей строке ввода, И новая строка еще не используется. Также обратите внимание, что %[...] не ограничивает количество вводимых символов, поэтому может переполнить входной буфер. Всегда используйте модификатор MAX CHARACTERS, который на единицу меньше длины входного буфера. На один меньше, потому что этот спецификатор входного формата всегда добавляет к буферу байт NUL. Предложите использовать: scanf(" %99[^\n]", postfix);   -  person user3629249    schedule 19.12.2017
comment
при вызове любой из функций семейства scanf() всегда проверяйте возвращаемое значение (а не значения параметров), чтобы убедиться, что операция прошла успешно.   -  person user3629249    schedule 19.12.2017
comment
относительно: system("PAUSE"); Эта команда оболочки «ПАУЗА» не является переносимой, поскольку она не реализована в ОС *unx.   -  person user3629249    schedule 19.12.2017
comment
для простоты чтения и понимания: 1) последовательно делайте отступы в коде. Отступ после каждой открывающей скобки '{'. Убрать отступ перед каждой закрывающей фигурной скобкой '}'. Предлагайте каждый уровень отступа быть 4 пробела. 2) следуйте аксиоме: только один оператор в строке и (максимум) одно объявление переменной на оператор. Рассматривайте закрывающую фигурную скобку '}' как отдельный оператор. 3) отдельные блоки кода (for, if, else, while, do...while, switch, case, default) через одну пустую строку.   -  person user3629249    schedule 19.12.2017
comment
размещенный код содержит некоторые «магические» числа. «магические» числа — это числа без основы. т.е. 100 (и закодированные значения для ответов меню) «магические» числа значительно усложняют понимание кода, отладку и т. д. Предложите использовать операторы enum для значений ответов меню Предложите использовать оператор #define для 100   -  person user3629249    schedule 19.12.2017
comment
хорошей практикой программирования является отделение определения структуры от любого typedef для этой структуры. Довольно грязно объявлять глобальные данные в середине освещенных прототипов. Предлагайте определение структуры, typedef для этой структуры и объявление экземпляра структуры перед списком прототипов.   -  person user3629249    schedule 19.12.2017
comment
для удобства чтения и понимания: вставьте соответствующий горизонтальный интервал: внутри скобок, после запятых, после точки с запятой, вокруг операторов C   -  person user3629249    schedule 19.12.2017
comment
относительно: system("PAUSE");: Это может быть гораздо более переносимо записано как: int ch; while( (ch = getchar()) != EOF && '\n' != ch ); getchar();   -  person user3629249    schedule 19.12.2017
comment
Ваша строка malloc(sizeof(infinx)+sizeof(head->op)*strlen(infinx)); странная. Я не понимаю, почему вы делаете первое sizeof, второе верно, но я думаю, что это скорее счастливая случайность. Что именно вы пытаетесь сделать здесь?   -  person Pablo    schedule 13.01.2018


Ответы (1)


Это ответ на ваш вопрос "Значит, вы говорите, что я должен определить их вне оператора switch?", который правильно отражает одну из проблем в вашем коде.

Либо: вы можете определить их снаружи, чтобы решить проблему.

Или: вы можете ввести соответствующие области блоков для решения проблемы.

Поскольку первое тривиально, я уточню второе:

1. Область действия и переменные

Время жизни локальной переменной начинается с ее объявления и заканчивается областью действия окружающего блока.

Пример:

int main()
{
  int a = 0; /* a starts to live. */
  { /* new scope */
    int b = 1; /* b starts to live */
    int a = 2; /* a new a starts to live. (The one of out scope is eclipsed.) */
  } /* Life of b and the inner a ends. The eclipsed outer a becomes visible again. */
  return 0;
}

2. switch и case

В отличие от других языков (например, Pascal), оператор C switch скорее представляет собой «goto в зависимости от выражения», чем многоходовое ветвление с несколькими альтернативами. (Это не означает, что switch нельзя использовать для последнего, но его можно использовать по-другому.) (Пожалуйста, см. Wikipedia: Control Flow: 5.2 Операторы case и switch, чтобы понять, что я имею в виду.)

Представьте себе следующий (неправильный) код:

#include <stdio.h>

int main()
{
  goto L1;
  int i = 1;
L1:
  printf("%d\n", i);
  return 0;
}

goto L1; пропускает объявление int i = 1;, но после L1: используется в printf() ой!

Из любопытства я попробовал его на ideone.com, он скомпилировался и работал без нареканий. . Результатом было 0, хотя это также могло быть 1, 2 или любое другое число, которое можно сохранить как int.

То же самое и в следующем (неправильном) образце:

#include <stdio.h>

int main()
{
  int cond = 2;
  switch (cond) {
    case 1:
      printf("case 1\n");
      int i = 1;
    case 2:
      printf("case 2: %d\n", i);
  } /* Here ends the life-time of i */
  return 0;
}

Опять же, я скомпилировал и протестировал на ideone.com. Выход был case 2: 0. Ой снова!

Решение

Для правильной имитации многоветвления необходимы следующие вещи:

  1. Конец каждого case с break.

  2. Запускайте область после каждого двоеточия case.

  3. Завершите эту область до соответствующего break.

Пример еще раз:

#include <stdio.h>

int main()
{
  int cond = 2;
  switch (cond) {
    case 0: case 1: { /* <- start scope */
      int i = 1;
      printf("case 1: %d\n", i);
    } break; /* <- end scope and jump to end of switch */
    case 2:
      printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
  }
  return 0;
}

Скомпилировано в ideone:

prog.c: In function ‘main’:
prog.c:12:34: error: ‘i’ undeclared (first use in this function)
           printf("case 2: %d\n", i); /* i is recognized as unknown identifier */
                                  ^

Поскольку область действия переменной i ограничена диапазоном от возможного входа (case 0: case 1:) до возможного выхода (break), никакой другой возможный путь кода не может получить к ней доступ.

person Scheff's Cat    schedule 19.12.2017