2016-03-30 1 views
0

Я сделал код для чтения выражений из файла в постфиксной нотации (RPN) и вывода значения. Хотя он правильно считывает значения и отображает выходные данные для выражений без каких-либо чисел, которые используют десятичные знаки, по умолчанию используется ошибка для любого выражения, содержащего значение float.Ошибка при использовании atof() и strtod() при попытке преобразования числовой строки в float

В принципе, если цифра найдена в строке, считанной из файла, ее необходимо преобразовать в поплавок.

Я безуспешно пытался установить значение данных, равное atof (str) и strtod (const char * str, char ** endptr), но я все еще получаю ошибку.

Вот мой код:

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

int top = -1; 
float stack[500]; 

/* push the given data into the stack */ 
void push (int data) { 
stack[++top] = data; 
} 

/* Pop the top element from the stack */ 
float pop() { 
float data; 
if (top == -1) 
    return -1; 
data = stack[top]; 
stack[top] = 0; 
top--; 
return (data); 
} 

int main() { 

char str[500]; 
FILE *p; 
if((p=fopen("testfile1.txt","r"))==NULL){ 
    printf("\n Unable to open file string.txt"); 
    return 1; 
} 

while(fgets(str,500,p)!='\0'){ 

    float data = -1, operand1, operand2, result; 

    for (int i = 0; i < strlen(str); i++) { 
     if (isdigit(str[i])) { 
      /* 
      * if the i/p char is digit, parse 
      * character by character to get 
      * complete operand 
      */ 
      data = (data == -1) ? 0 : data; 
      data = (data * 10) + (str[i] - 48); 
      continue; 
     } 

     if (data != -1) { 
      /* if the i/p is operand, push it into the stack */ 
      push(data); 
     } 

     if (str[i] == '+' || str[i] == '-' 
       || str[i] == '*' || str[i] == '/') { 
      /* 
      * if the i/p is an operator, pop 2 elements 
      * from the stack and apply the operator 
      */ 
      operand2 = pop(); 
      operand1 = pop(); 
      if (operand1 == -1 || operand2 == -1) 
       break; 
      switch (str[i]) { 
       case '+': 
        result = operand1 + operand2; 
        /* push the result into the stack */ 
        push(result); 
        break; 
       case '-': 
        result = operand1 - operand2; 
        push(result); 
        break; 
       case '*': 
        result = operand1 * operand2; 
        push(result); 
        break; 
       case '/': 
        result = operand1/operand2; 
        push(result); 
        break; 
      } 
     } 
     data = -1; 
    } 
    if (top == 0) 
     printf("Output:%3.2f\n", stack[top]); 
    else 
     printf("have given wrong postfix expression\n"); 
    return 1; 
} 
} 

Есть 5 Постфиксные выражения в файле, и они заключаются в следующем:

13 1 - 2/3 155 + * 
100 100 100 100 + + + 
10.33 2 2 2 2 2 * * * * * 
30 10 - 10 - 10 - 2 * 
300 13.25 - 11 3 -/4 5 - * 3/

Но выход программы отрицает третье выражение, потому что он содержит 10.33, который не является целым числом.

Выход:

Output: 948.00 
Output: 400.00 
have given wrong postfix expression 
Output: 0.00 
Output: 300.00 

Кто-нибудь знает, как изменить этот код для обработки поплавков?

Cheers.

+0

относительно этой линии: '' в то время как {функция (fgets (ул, 500, р) = '\ 0'!): 'fgets()' никогда не возвращает символ NUL. На странице man: 'fgets() возвращает s при успехе, а NULL - при ошибке или когда конец файла происходит, когда символы не были прочитаны.' Where 's' - это указатель, который был передан в качестве первого параметра. Предложите проверку для 'NULL', а не' '\ 0'' – user3629249

+0

относительно этой строки:' if (isdigit (str [i])) {'это не может ввести значение float, потому что' .' не является цифрой и не имеет '.' это не значение с плавающей запятой. – user3629249

+0

Функция: 'strtod()' работает с 'doubleles', а не' floats' предлагает использовать: 'strtof()' – user3629249

ответ

0

Вы можете попробовать вручную обрабатывать десятичные значения почти такой же обработке целых чисел, но в C было бы проще напрямую итерацию номер один проход:

while(fgets(str, sizeof(str), stdin) != NULL) { 
    unsigned int i; 
    for (i=0; i<strlen(str); i++) { 
     if (isdigit(str[i])) { 
      data = str[i++] - '0'; // initialize data with first digit 
      while(isdigit(str[i])) { 
       data = data * 10 + (str[i++] - '0'); // increment with other digits 
      } 
      if (str[i] == '.') { // decimal part 
       double mult = .1; 
       i++; 
       while(isdigit(str[i])) { 
        data = data + mult * (str[i++] - '0'); // increment with decimal part 
        mult *= .1; 
       } 
      } 
      push(data); 
     } 
     ... 

Но на самом деле strtod делает это для вы ...:

while(fgets(str, sizeof(str), stdin) != NULL) { 
    unsigned int i; 
    for (i=0; i<strlen(str); i++) { 
     if (isdigit(str[i])) { 
      char *end; 
      data = ::strtod(str+i, &end); 
      i = end - str; // that's all we are past the number... 
      push(data); 
     } 
     ...