Thread: Please help: Working with Files, Struct, and manipulating data

  1. #1
    Registered User
    Join Date
    Dec 2013
    Posts
    2

    Please help: Working with Files, Struct, and manipulating data

    Hello,
    I have the following code and I am trying to do simple math calculations to the data. I need to take the car price (y) minus down payment (z) and then divide that quantity by 12 times "yearsx" That answer is then assigned to x. The problem is that x will not print the correctly! I have tried everything I can think of and no luck. Any ideas? recommendations? Please help!

    I also noticed that if I increase the "count" to amnything higher than the number on lines in the file, I get the correct value for x but only on the last set of the struct... weird right?

    my file reads as follows:

    last_name first_name car_price down_payment years
    johnson bill 10,000 2,000 3

    When I printf the struct to the screen, i need to do the following:

    x = (10,000 - 2,000)/(12*years);

    but this is the math part that wont work. I have checked and doubled checked number types and I cant get it right.

    any help is much appreciated!




    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #define FILENAME "file.txt"
    #define SIZE 100
    
    
    int main(void)
    {
    
    
    typedef struct
    {
    char last_name[15];
    char name[15];
    double car_price;
    double down_payment;
    int loan_years;
    } Sales;
    
    
    FILE *salescount;
    
    
    Sales buyer[SIZE];
    
    
    double x=0; // monthly payment
    double y=0; // car price
    double z=0; //down payment
    int yearsx=0;
    
    
    int count=0;
    
    
    salescount = fopen(FILENAME, "r");
    printf("\tLast Name \t \t Name \t \t Car Price \t Down Payment\tLoan Years\tMonthly Payment \n\n");
    while((fscanf(salescount, "%s %s %d %d %i", 
                         &buyer[count].last_name, 
                         &buyer[count].name, 
                         &buyer[count].car_price, 
                         &buyer[count].down_payment, 
                         &buyer[count].loan_years))>1) 
    {
    printf("%15s \t", buyer[count].last_name); 
    printf("%15s \t", buyer[count].name); 
    printf("%d \t \t ", buyer[count].car_price);
    printf("%d \t \t ", buyer[count].down_payment);
    printf("%i \t \t ", buyer[count].loan_years);
    
    y = buyer[count].car_price;
    z = buyer[count].down_payment;
    yearsx = buyer[count].loan_years;
    
    
    x = ((y)-(z))/(12*yearsx));
    
    printf("%f \n", x);
    
    count++;
    }
    
    
    return 0;
    }

  2. #2
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Welcome to the forum. Also, it's nice to see a good first post - clear questions, relevant data, code in code tags, and proper "main()" structure. (All too often, first posts lack most, if not all, of these things.)

    Anyway, onto the code. The first thing that would help is using consistent indentation in your code. Here's what it looks like with proper indentation (I took the liberty of moving your structure declaration above "main()") - notice how much easier it is to scan over with your eyes:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #define FILENAME "file.txt"
    #define SIZE 100
    
    
    typedef struct
    {
        char last_name[15];
        char name[15];
        double car_price;
        double down_payment;
        int loan_years;
    } Sales;
    
    
    int main(void)
    {
        FILE *salescount;
        Sales buyer[SIZE];
        double x=0; // monthly payment
        double y=0; // car price
        double z=0; //down payment
        int yearsx=0;
        int count=0;
    
        salescount = fopen(FILENAME, "r");
        printf("\tLast Name \t \t Name \t \t Car Price \t Down Payment\tLoan Years\tMonthly Payment \n\n");
        while((fscanf(salescount, "%s %s %d %d %i",
            &buyer[count].last_name,
            &buyer[count].name,
            &buyer[count].car_price,
            &buyer[count].down_payment,
            &buyer[count].loan_years))>1)
        {
            printf("%15s \t", buyer[count].last_name);
            printf("%15s \t", buyer[count].name);
            printf("%d \t \t ", buyer[count].car_price);
            printf("%d \t \t ", buyer[count].down_payment);
            printf("%i \t \t ", buyer[count].loan_years);
    
            y = buyer[count].car_price;
            z = buyer[count].down_payment;
            yearsx = buyer[count].loan_years;
    
            x = ((y)-(z))/(12*yearsx));
    
            printf("%f \n", x);
    
            count++;
        }
    
        return 0;
    }
    Secondly, you should be compiling with warnings set to maximum (how to do so depends on your compiler/IDE). All warnings and errors should be fixed as they are found.

    Code:
    main.c||In function 'main':|
    main.c|34|warning: format '%s' expects type 'char *', but argument 3 has type 'char (*)[15]'|
    main.c|34|warning: format '%s' expects type 'char *', but argument 4 has type 'char (*)[15]'|
    main.c|34|warning: format '%d' expects type 'int *', but argument 5 has type 'double *'|
    main.c|34|warning: format '%d' expects type 'int *', but argument 6 has type 'double *'|
    main.c|38|warning: format '%d' expects type 'int', but argument 2 has type 'double'|
    main.c|39|warning: format '%d' expects type 'int', but argument 2 has type 'double'|
    main.c|46|error: expected ';' before ')' token|
    main.c|46|error: expected statement before ')' token|
    ||=== Build finished: 2 errors, 6 warnings ===|
    A few warnings, and one error. This should not have compiled for you. As indicated, you have an error on line 46 (referenced to the code above in my post). Counting parenthesis, you have an extra closing ')' at the end.

    If you look at the line numbers of the warnings, and the corresponding code, you should see several mis-matches in your "fscanf()" arguments versus format string.

    >> warning: format '%s' expects type 'char *', but argument 3 has type 'char (*)[15]'

    When reading a string this way, you don't need the '&' in front of the array name where that string is to be stored. This is because the "scanf()" family needs a pointer to the variable of interest, and the name of the array without the element notation acts as a pointer to that array.

    >> warning: format '%d' expects type 'int *', but argument 5 has type 'double *'

    This is straight-forward. You use "%d" (for integer) in your format string, but are trying to store the value into a variable of data type double. Instead of "%d", you should be using "%lf".

    >> warning: format '%d' expects type 'int', but argument 2 has type 'double'

    Looking at the line numbers, this warning corresponds to a "printf()" statement. Similar issue as above - you're trying to use "%d" (for integer) to print a double. Ditto on the next line.




    A couple of other things to note:

    - You should check that the file has opened successfully before trying to access it (you can do this by making sure the FILE pointer returned is not NULL)
    - You should close the file before exiting the program
    - The first line of your data file is a header, which does not contain useful data - this should be handled accordingly in your code
    - Don't use "magic numbers" for the array sizes of your strings in the struct. You used #define for the size of the Sales array - you should do something similar for the length of strings in your struct.
    - Kudos for checking the return value of "fscanf()". It might be better to check explicitly that it read all five data items (!= 5) instead of just more than one (>1).

    Give some of these corrections a shot and see if you can work towards a working program on your own. If you still can't get it to work, post your updated code along with the issues you are facing. Feel free to ask if you need clarification on any of the points I have made.

  3. #3
    Registered User
    Join Date
    Dec 2013
    Posts
    2
    Hey Matticus,

    I am a bit new to C but I think I can follow everything you explained and make changes. I am using jGrasp 2.0.0.0_7 so I will look into turning on the warnings. I didnt know there was such a thing.

    Quote Originally Posted by Matticus View Post

    A couple of other things to note:

    - You should check that the file has opened successfully before trying to access it (you can do this by making sure the FILE pointer returned is not NULL)
    - You should close the file before exiting the program
    - The first line of your data file is a header, which does not contain useful data - this should be handled accordingly in your code
    - Don't use "magic numbers" for the array sizes of your strings in the struct. You used #define for the size of the Sales array - you should do something similar for the length of strings in your struct.
    - Kudos for checking the return value of "fscanf()". It might be better to check explicitly that it read all five data items (!= 5) instead of just more than one (>1).
    About magic numbers, i gave the string a size of 15. do you mean the car price, down payment, and years should also have a string size? like this:


    char last_name[15];
    char name[15];
    double car_price[10];
    double down_payment[10];
    intloan_years[10];

    Also, I am not sure what the first line of my file will be. I believe it will be actual data to be used so I wasnt sure if I needed to modify anything on that issue.

    Another length issue is, I do not know how many lines of data my file will have. Which is why I used SIZE 100 because I know it will be less than that. But I know thats not the most correct or efficient way.

    I will work on all these corrections and repost later with updates.

    Thank you for the warm welcome and all your suggestions

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    About magic numbers, i gave the string a size of 15. do you mean the car price, down payment, and years should also have a string size? like this:
    No! Definitely do not do that. What I mean is something like:

    Code:
    #define STR_LEN 15
    
    // ...
    
    typedef struct
    {
        char last_name[STR_LEN];
        char name[STR_LEN];
        double car_price;
        double down_payment;
        int loan_years;
    } Sales;
    "Magic Numbers" refer to numbers hard-coded into your source code (such as in array declarations). For instance, you have "15" as the size of your arrays. You might also use that value elsewhere (say, to run through those strings in loops). In this instance, if you wanted to change the size of the array to, say 20, you'd have to hunt down all references to it and change the number to 20.

    By using a #define, you only have to change the value on that one line of code, and all references to that value will automatically refer to the new number.

    Also, I am not sure what the first line of my file will be. I believe it will be actual data to be used so I wasnt sure if I needed to modify anything on that issue.
    If the first line is actual data, you don't have to worry about the issue I described. This can be discussed more when you have your requirements solidified.

    Another length issue is, I do not know how many lines of data my file will have. Which is why I used SIZE 100 because I know it will be less than that. But I know thats not the most correct or efficient way.
    If you know the file will never grow larger than 100, that is fine for now. Especially if this is only for practice. There are other methods for handling an unknown number of inputs, but if you're new to C, I wouldn't worry about that for now.

    I will work on all these corrections and repost later with updates.
    Very good!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I/O files: reading, manipulating and outputting data
    By Mwepak in forum C++ Programming
    Replies: 17
    Last Post: 12-12-2012, 07:50 AM
  2. Passing struct data between files
    By SuperMiguel in forum C Programming
    Replies: 7
    Last Post: 03-28-2012, 05:00 PM
  3. Help Manipulating String of Struct Array in Functions
    By seannabeast in forum C Programming
    Replies: 5
    Last Post: 11-16-2011, 08:34 PM
  4. working with numeric data in files
    By bored_guy in forum C Programming
    Replies: 1
    Last Post: 11-14-2008, 12:58 AM
  5. working with data files
    By sprint108 in forum C++ Programming
    Replies: 1
    Last Post: 03-31-2005, 10:41 PM

Tags for this Thread