2017-02-17 32 views
-1

Я пишу код, который позволяет пользователю добавлять сотрудников по ID, возрасту и зарплате, однако для зарплаты я не уверен, какое значение использовать для сканирования и печати таких как 78950,86. Я использовал double для SALARY, потому что есть больше значений для хранения, и я попытался сыграть с printf и scanf для этой переменной, но я либо получаю ошибки сегментации, либо случайные числа. Вот мой код:Принимать большие числа с десятичными значениями в C

#include <stdio.h> 

#define SIZE 2 
// Define Number of Employees "SIZE" to be 2 

struct Employee{ 
    int ID; 
    int AGE; 
    double SALARY; 
}; 
//Declare Struct Employee 


/* main program */ 
int main(void) { 

    int option = 0; 
    int i; 
    struct Employee emp[SIZE]; 

    printf("---=== EMPLOYEE DATA ===---\n\n"); 

    // Declare a struct Employee array "emp" with SIZE elements 
    // and initialize all elements to zero 

    do { 
      // Print the option list 
      printf("1. Display Employee Information\n"); 
      printf("2. Add Employee\n"); 
      printf("0. Exit\n\n"); 
      printf("Please select from the above options: "); 

      // Capture input to option variable 
      scanf("%d",&option); 
      printf("\n"); 

      switch (option) { 
        case 0: // Exit the program 

          break; 
        case 1: // Display Employee Data 
          // @IN-LAB 

          printf("EMP ID EMP AGE EMP SALARY\n"); 
          printf("====== ======= ==========\n"); 

          //Use "%6d%9d%11.21f" formatting in a 
          //printf statement to display 
          //employee id, age and salary of 
          //all employees using a loop construct 

       for(i=0; i<SIZE; i++) { 
            printf("%d %d  %11.2lf", emp[i].ID, emp[i].AGE, emp[i].SALARY); 
          } 

          //The loop construct will be run for SIZE times 
          //and will only display Employee data 
          //where the EmployeeID is > 0 

          break; 
        case 2: //Adding Employee 
            // @IN-LAB 

          printf("Adding Employee\n"); 
          printf("===============\n"); 

          for(i=0;i<SIZE;i++) { 

          printf("\nEnter employee ID: "); 
          scanf ("%d", &emp[i].ID); 

          printf("\nEnter employee Age: "); 
          scanf ("%d", &emp[i].AGE); 

          printf("\nEnter employee Salary: "); 
          scanf ("%11lf", &emp[i].SALARY); 
            } 


          //Check for limits on the array and add employee 
          //data accordingly 

          break; 

        default: 

          printf("ERROR: Incorrect Option: Try Again\n\n"); 

      } 

    } while (option!= 0); 

    return 0; 

} 
+1

'scanf ("% ld.% 02d \ n ", & emp [i] .SALARY);' регулярно генерирует предупреждение для многих компиляторов. Убедитесь, что предупреждения вашего компилятора полностью включены. – chux

+0

Фундаментальное свойство переменных с плавающей запятой с бинарной мантиссой (которая является всеми существующими представлениями с плавающей запятой) заключается в том, что они не могут точно представлять значения, такие как «0,1» или «0,01», что означает, что использование их для представления валюты всегда включает в себя ошибку, которая имеет тенденцию распространяться посредством расчетов. Вы можете попробовать использовать структуру, представляющую основные и младшие единицы (например, доллары и центы), используя два целых числа. Чтение двух целых чисел, разделенных символом '.. ', Тривиально - просто убедитесь, что выбранные вами типы интегралов имеют достаточный диапазон для вашего приложения. – Peter

ответ

1

Ваши строки формата используют %ld.%02d при работе с double, в котором говорится, чтобы рассматривать его как 2 целых чисел, разделенных точкой (которые должны были генерируемой предупреждения). Исправьте строку, чтобы правильно указать один double, или если (как предлагает @MalcomMcLean) вы хотите сохранить доллары и центы отдельно, используйте другое поле/переменную для каждого.

+1

Если вы храните денежные суммы, храните количество центов, даже если вы используете двойной тип. Бухгалтеры заботятся о нечетных пенни, потому что это проверка мошенничества. –

+0

Обновлен, чтобы показать ответ, который я искал. Проблема, с которой я столкнулась, заключалась в том, что scanf не может зарегистрировать десятичное значение, которое приводит к ошибкам. Кроме того, мне нужно было округлить до двух десятичных знаков, но предложение хранить доллары и центы в виде двух отдельных переменных полезно знать. – Jinto

0

«Я не уверен, какую ценность использовать для сканирования и печати на таком количестве, как 78950,86».

Вообще говоря, зарплаты на самом деле не являются «большими числами», в мире кодирования (или типами данных С, если быть точным). Для примера, который вы указали, достаточно даже одного типа данных с плавающей точкой. (Искать «максимальное конечное положительное значение в одинарной точности» в странице https: //en.m.wikipedia.org/wiki/Single-precision_floating-point_format)

Таким образом, двойной тип данных, который вы использовали, более чем достаточен для указанной цели. Как справедливо указал Скотт, ошибки сегментации вызываются, потому что ваша строка формата предлагает два параметра данных, когда имеется только одна переменная типа double.

Мое мнение было бы не хранить данные о заработной плате в виде отдельных долларов и центов. С точки зрения работодателя эти центы собираются добавить к доллару, и в конечном итоге они будут объединены с долларовыми данными, что затруднит ваш алгоритм суммирования.

В заключение вы можете использовать двойной тип данных для переменной зарплаты. При печати оклада вы можете использовать «% .2f» в строке формата. При использовании scanf для получения зарплаты в стандартной нотации с фиксированной точкой вы можете использовать «% lf» в строке формата.