Thread: Two Dimensional Array Input from Formatted Data

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    5

    Two Dimensional Array Input from Formatted Data

    Hello, all. I was assigned a new program to sort a list of stocks from a formatted data file. The data file (truncated) is as follows:
    Code:
    BBY 48.75 48.65 49.30 49.35 48.10 48.35
    
    COP 69.05 68.36 67.35 67.10 67.75 68.10
    
    DEL 23.05 23.10 23.20 23.19 23.31 23.31
    
    HPQ 40.12 40.24 40.50 41.00 41.10 41.68
    
    HD  37.12 36.65 37.38 37.63 37.90 38.00
    There are about 15 stocks in the list. The first column is the stock symbol, the second column is the average price, and the next five columns are daily prices. I am trying to read the stock symbols into a two dimensional array so that I can sort it by average prices later. My problem is with actually reading the correct stock symbol into the array. Here is the code:
    Code:
    #include <stdlib.h>
    
    #include <stdio.h>
    
    #define  MAX  20
    
    #define  MAX_NAME  3
    
    #define  MAX_DAYS  5
    
    #define  FILENAME  "Stocks07.dta"
    
    #define  EOS  '\0'
    
    
    int main (void)
    
    {
    
      FILE *ifp;
    
      char symbol[MAX][MAX_NAME];
    
      double prev_avg[MAX],
    
             daily[MAX][MAX_DAYS];
    
      int cnt,           // number of rows OR number of stocks
    
          element;       // counter for storing stock symbols and daily prices
    
    
      if((ifp = fopen(FILENAME, "r")) != NULL)
    
      {
    
         for (cnt = 0; cnt < MAX; ++cnt)
    
         {
    
            for(element = 0; element < MAX_NAME; ++element)
    
                fscanf(ifp,"%c", &symbol[cnt][element]);
    
            symbol[cnt][element] = EOS;
    
            fscanf(ifp,"%lf", &prev_avg[cnt]);
    
            for(element = 0; element < MAX_DAYS; ++element)
    
                fscanf(ifp,"%lf", &daily[cnt][element]);
    
            fscanf(ifp,"%*c");
    
         }
    
         printf("The first symbol is %s", symbol[0]);
    
         printf("\n\nPrev. avg is %5.2f", prev_avg[0]);
    
         printf("\n\nWednesday's price for %s is %5.2f", symbol[4], daily[4][2]);
    
         printf("\n\n15th Prev.avg is %5.2f\n\n", prev_avg[14]);
    
         system("pause");
    
      }
    
      else
    
         printf("\n\n\n\n %45s \n\n\n", "Missing Data File!");
    
      return 0;
    
    }
    From the sample printf statements, my output is as follows:
    Code:
    The first symbol is BBYCOPDELHPQHD IBMINTLMTLOWLUFPEPPPCTINWMTXOM
    
    Prev. avg is 48.75
    
    Wednesday's price for HD IBMINTLMTLOWLUFPEPPPCTINWMTXOM is 37.63
    
    15th prev. avg is 76.12
    Can anyone tell me what I'm doing wrong or another method that doesn't involve using a lot of standard functions. We were told to use the methods we learned in class.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > #define MAX_NAME 3
    3 characters + EOS is 4
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2007
    Posts
    5
    But if I set MAX_NAME to 2, won't it only get the first 2 letters and then the EOS? I tried removing the EOS line but I got the same thing + gibberish.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > symbol[cnt][element] = EOS;
    The problem is, you always end up doing
    symbol[cnt][MAX_NAME] = EOS;

    Which as you know, is off the end of the array.

    So basically, the EOS is going to be lost when the real owner of that memory location writes their own data.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Apr 2007
    Posts
    5
    YES! Thank you both so much. Quickest and most accurate responses I could have asked for.

  6. #6
    Registered User
    Join Date
    Apr 2007
    Posts
    5
    Actually, just one more question. I've used a for() loop to control how many stocks there are. This always ends up being 20. The problem is, how can I test for EOF without messing up my read statements?

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Well you need to check the return result of all your fscanf calls.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    You could rewrite this:
    Code:
         for (cnt = 0; cnt < MAX; ++cnt)
         {
            for(element = 0; element < MAX_NAME; ++element)
                fscanf(ifp,"&#37;c", &symbol[cnt][element]);
            symbol[cnt][element] = EOS;
            fscanf(ifp,"%lf", &prev_avg[cnt]);
            for(element = 0; element < MAX_DAYS; ++element)
                fscanf(ifp,"%lf", &daily[cnt][element]);
            fscanf(ifp,"%*c");
         }
    To this:
    Code:
         cnt = 0;
         while (fscanf(ifp,"%3s", symbol[cnt]) == 1)
         {
            fscanf(ifp,"%lf", &prev_avg[cnt]);
            for(element = 0; element < MAX_DAYS; ++element)
                fscanf(ifp,"%lf", &daily[cnt][element]);
            cnt++;
         }
    The MAX_NAME part is hardcoded as three in the first fscanf(), but you could make this format argument a string variable.

  9. #9
    Registered User
    Join Date
    Apr 2007
    Posts
    5
    Ah yes, thank you. This is much more efficient.
    Last edited by teedoff087; 04-27-2007 at 11:49 PM.

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Here's how to make the format variable:
    Code:
    	char format[10];
    .
    .
    	sprintf(format, "&#37;%%ds", MAX_NAME);
    And then the while() would be:
    Code:
         while (fscanf(ifp, format, symbol[cnt]) == 1)
    As Salem said, it's a good idea to check the return values of all fscanf()'s. The return value is how many inputs were successfully scanned.

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    or just using *.* directly as format modifiers?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >or just using *.* directly as format modifiers?
    Can you explain what you mean vart?

  13. #13
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by swoopy View Post
    >or just using *.* directly as format modifiers?
    Can you explain what you mean vart?
    Sorry misread scanf as printf... In scanf only your way is possible...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > sprintf(format, "&#37;%%ds", MAX_NAME);
    sprintf(format, "%%%ds", MAX_NAME - 1);
    The field widths are the number of characters, so you have to account for the \0 yourself.

    Or you have
    char result[ MAX_NAME + 1];

    Either way, it's a lot more fiddling than simply being able to use sizeof.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >The field widths are the number of characters, so you have to account for the \0 yourself.
    Oops, good point.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. can someone help me with these errors please code included
    By geekrockergal in forum C Programming
    Replies: 7
    Last Post: 02-10-2009, 02:20 PM
  3. Template Array Class
    By hpy_gilmore8 in forum C++ Programming
    Replies: 15
    Last Post: 04-11-2004, 11:15 PM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM