Below is a program in C that I am trying to use to read in a spreadsheet (in CSV form), which I will eventually be doing calculations on and then writing out to a new file. I'm currently trying to figure out the following three things:

1) How to make it so that the matrix is dynamically allocated memory. Right now it's set to be 10 x 10, but I want it to read the number of items between comma's as the width and the number of rows as the height. Can I just add the number of occurences of commas and add 1 to the total to get the width?

2) Right now it just writes out the data that it's reading in from the file, but could someone point me in the right direction for writing to a new CSV file with the - eventually modified - data?

3) I want to work with floating point numbers to two spaces (i.e. 10.14), where should I be defining that? I tried "float array[10][10] and a few other things, but wasn't too successful.

I'm pretty new to C, and these forums have been a huge help so far, thanks to everyone who's contributed to any of the threads.

#include <stdio.h>
#include <stdlib.h>

#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))

int main(void)
{
    
    const char filename[] = "file.csv";
    
    /* Open the file  */
    FILE *file = fopen(filename, "r");
    
    if (file)
    {
        /* Need dynamic allocation here */
        float array[10][10];
        size_t i, j, k;
        char buffer[BUFSIZ], *ptr;
        
        /* Read each line from the file */
        for(i=0; fgets(buffer, sizeof buffer, file); i++)
        {
               /* Parse the comma-seperated values from each line into 'array' */
                for(j=0, ptr=buffer; j < ARRAYSIZE(*array); ++j, ++ptr)
                {
                    array[i][j] = (int)strtol(ptr, &ptr, 10);
                }    
        }
        
        fclose(file);
        
        /* Print the data in 'array' */
        for(j = 0; j < i; ++j)
        {
            printf("array[%lu]:", (long unsigned)j);
            
            for(k = 0; k < ARRAYSIZE(*array); ++k)
            {
                printf("%4d", array[j][k]);
            }            
            
            putchar('\n');
        }        
    } 
    
    else
    {
        perror(filename);
    }      
    
    system("pause");
    
    return 0;
}

Sample data I'm using:

2018,015,110.87,110.9,110.87,110.9,9,9,9,9
2018,020,110.9,110.9,110.86,110.88,5,5,5,5
20,025,110.87,110.88,110.85,110.88,7,7,7,7
2018,030,110.88,110.95,110.87,110.93,10,10,10,10
18,035,110.93,110.94,110.91,110.92,9,9,9,9
20,040,110.92,110.93,110.9,110.91,11,11,11,11
218,045,110.91,110.93,110.91,110.91,6,6,6,6
20218,050,110.91,110.93,110.9,110.9,10,10,10,10
218,055,110.9,110.93,110.9,110.92,11,11,11,11
20218,100,110.89,110.93,110.9,110.94,12,12,12,12

Thanks for any help!

Nolan

Say, that code looks quite familiar. How much have you tried doing yourself?

As I said, I am quite new to C programming, that code is someone else's instructions on how to read a CSV file. It took me a half hour just to look through it and understand what was going on (and I still don't understand it all).

I'm trying to understand a process...I searched around for code on how to read in CSV files, found what I posted, attempted to change what I needed to to make floating point numbers, was unsuccessful, signed up for a message board, asked how to work with floating point numbers and then I realized I would need to output to CSV, so I asked about how to do that.

So basically...from the beginning I knew nothing about working with CSV files, so instead of asking how to do the above, I researched sites to find it. If you'd rather me waste more of your time by asking how to do the above, I'd be glad to. I've been working on the code today and still to no avail. It's a lot more efficient and effective to learn from others than screw up code for 2 weeks straight before giving up on a program. At least that's how I see it.

I'm not looking for you to write my code, I'm looking for someone who can point me in a right direction.

Thanks for anyone who can offer some help

though I did just see that you offered advice on the other forum, so thank you.

I didn't realize that people would take such offense to asking advice on pre-written code on multiple boards and will point out sources in the future.

I made the basic assumption that the more people who saw the code, the more advice I'd get.

>though I did just see that you offered advice on the other forum, so thank you.

Now you yourself have tasted the confusion of cross posting.

>I didn't realize that people would take such offense to asking advice on pre-written code on multiple boards and will point out sources in the future.

Perhaps I was too jumpy as well. But discovering code I wrote being posted here after it was made incorrect, and then seeing an identical thread elsewhere...

I find cross-posting to be rude. And at first I thought you just grabbed the code and didn't acknowledge that it wasn't yours (I read code before the text, usually). I've seen folks copy my code and say, "Hey, look, I wrote this but I need help making a little change..."

>I made the basic assumption that the more people who saw the code, the more advice I'd get.

Perhaps. Not all the advice you get may be in regard to the code, no?

If you cross-post, that's your choice. I suggest at least updating each cross-post with links to where it is cross-posted. Otherwise someone might spend a fair amount of time trying to help, only to be handed one of those "thanks, but I got it working" [with the help from one of the cross posts].


But back to the original issue. What is the big picture?

Do you even need an array, or could you simply read, modify and write each value?

Is the matrix rectangular? Is the size fixed or could it vary?

>Perhaps I was too jumpy as well. But discovering code I wrote being posted here after it was made incorrect, and then seeing an identical thread elsewhere...

My apologies, I didn't even see that you were the one who wrote that code. Now that I step back, it seems like everywhere I've looked or posted, it had something to do with you. Strange.

>If you cross-post, that's your choice. I suggest at least updating each cross-post with links to where it is cross-posted. Otherwise someone might spend a fair amount of time trying to help, only to be handed one of those "thanks, but I got it working" [with the help from one of the cross posts].

Will do.

>But back to the original issue. What is the big picture?

Do you even need an array, or could you simply read, modify and write each value?

Is the matrix rectangular? Is the size fixed or could it vary?

Well each value will have something different applied to it. The basic formats of each row go as follows:

date, time, price, price, price, price, volume,

So it will always be 7 columns, but the number of rows will always vary.

The reason I thought I would need an array is to go about sorting the columns by date and time, though I could also do that in excel before saving the .csv file. A problem I'm dealing with is that there is more than 65,000 rows of data, so I have to use rows A-G, then move to H-N for the rest, and so on.

At that point I have to format the date from mm/dd/yyyy to yyyymmdd and the time from standard to military (which I assume won't be hard to just have done in the program as well). I then copy all of the rows into notepad where the file is then complete for my purposes and moved on to someone else.

Also, I guess there's no real reason why this couldn't be done in C++. Do you see some specific advantages to going that route?

Well each value will have something different applied to it. The basic formats of each row go as follows:

date, time, price, price, price, price, volume,

So it will always be 7 columns, but the number of rows will always vary.

Sounds like you might want an array of structs.

A problem I'm dealing with is that there is more than 65,000 rows of data, so I have to use rows A-G, then move to H-N for the rest, and so on.

Gotcha. Is the number of rows fixed?

At that point I have to format the date from mm/dd/yyyy to yyyymmdd and the time from standard to military (which I assume won't be hard to just have done in the program as well). I then copy all of the rows into notepad where the file is then complete for my purposes and moved on to someone else.

M'kay.

Then vectors may be more suitable. But this is how I might have adapted things if I would have chosen C.

#include <stdio.h>
#include <stdlib.h>

struct sRecord
{
   int    date, time;
   double price[4], volume;
};

int main(void)
{
   static const char filename[] = "file.csv";
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      size_t i = 0, size = 100000;
      struct sRecord *array = malloc(size * sizeof *array);
      if ( array )
      {
         char line[128];
         while ( i < size && fgets(line, sizeof line, file) )
         {
            if ( sscanf(line, "%d,%d,%lf,%lf,%lf,%lf,%lf",
                        &array[i].date, &array[i].time,
                        &array[i].price[0], &array[i].price[1],
                        &array[i].price[2], &array[i].price[3],
                        &array[i].volume) == 7 )
            {
               ++i;
            }
         }
         fclose(file);
         /*
          * [Modify contents]
          */
         for ( size = i, i = 0; i < size; ++i )
         {
            printf("%d,%d,%g,%g,%g,%g,%g\n", array[i].date, array[i].time,
                   array[i].price[0], array[i].price[1], array[i].price[2],
                   array[i].price[3], array[i].volume);
         }
         free(array);
      }
   }
   else
   {
      perror(filename);
   }
   return 0;
}

I'll try to enter gently (into the conversation of others), but I believe the process could be demonstrated something like this using C++:

//variables to write to file
int date = 10;
char month[12] = "June";
float first = 1.011;
float second = 2005.2;

//using C++ style file I/O
ofstream fout("sample.txt");
fout << date << ',' << month << ',' << first << ',' << second;

sample.txt should now be in CSV format.

To read in from file would be:

ifstream fin("sample.txt");
//use different variables to confirm that things read back in correctly.
int date_;
char month_[12];
float first_;
float second_;
char dummy;

fin >> date_ >> dummy >> month_ >> dummy >> first_ >> dummy >> second_;

I agree with Dave Sinkula, that this sounds like a good project to use struct/class with and overload the << for the struct if you have that option available.

I don't have access to a compiler to confirm my code sample, sorry.

In C++ I might write it something like this (for starters).

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdio>

struct sRecord
{
   int    date, time;
   double price[4], volume;
};

bool operator< (const struct sRecord &a, const struct sRecord &b)
{
   return a.date < b.date;
}

std::ostream& operator<< (std::ostream &o, struct sRecord &r)
{
   o << r.date << "," << r.time << "," << r.price[0] << "," << r.price[1] << ","
     << r.price[2] << "," << r.price[3] << "," << r.volume;
   return o;
}

int main(void)
{
   std::vector<sRecord> record;
   const std::string filename("file.csv");
   std::ifstream file(filename.c_str());
   if ( file )
   {
      std::string line;
      while ( file >> line )
      {
         sRecord data;
         if ( std::sscanf(line.c_str(), "%d,%d,%lf,%lf,%lf,%lf,%lf",
                          &data.date, &data.time, &data.price[0], &data.price[1],
                          &data.price[2], &data.price[3], &data.volume) == 7 )
         {
            record.push_back(data);
         }
      }
   }
   /*
    * [Modify contents]
    */
   std::sort(record.begin(), record.end());
   std::copy(record.begin(), record.end(),
             std::ostream_iterator<sRecord>(std::cout, "\n"));
   return 0;
}

[D'oh. Pokey on the C++ conversion.]

Alright, just so you get an idea of where I'm at...I'm putting in red any of the lines that I don't understand. At this point I'm going to just sit here and study this code and try and get to the point where I can walk through it.

One question, the program isn't outputting anything? Is there something missing?

Then vectors may be more suitable. But this is how I might have adapted things if I would have chosen C.

#include <stdio.h>
#include <stdlib.h>

struct sRecord
{
   int    date, time;
   double price[4], volume;
};

int main(void)
{
   static const char filename[] = "file.csv";
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      size_t i = 0, size = 100000;
      struct sRecord *array = malloc(size * sizeof *array);  
      if ( array )
      {
         char line[128];
         while ( i < size && fgets(line, sizeof line, file) )
         {
            if ( sscanf(line, "%d,%d,%lf,%lf,%lf,%lf,%lf",
                        &array[i].date, &array[i].time,
                        &array[i].price[0], &array[i].price[1],
                        &array[i].price[2], &array[i].price[3],
                        &array[i].volume) == 7 )
            {
               ++i;
            }
         }
         fclose(file);
         /*
          * [Modify contents]
          */
         for ( size = i, i = 0; i < size; ++i )
         {
            printf("%d,%d,%g,%g,%g,%g,%g\n", array[i].date, array[i].time,
                   array[i].price[0], array[i].price[1], array[i].price[2],
                   array[i].price[3], array[i].volume);
         }
         free(array);
      }
   }
   else
   {
      perror(filename);
   }
   return 0;
}

Declare a pointer and attempt to allocate memory to contain an array of these structures, assigning the result of the attempt to the pointer:

struct sRecord *array = malloc(size * sizeof *array);

A buffer into which to read a line of data:

char line[128];

Read a line of data:

while ( i < size && fgets(line, sizeof line, file) )

One question, the program isn't outputting anything? Is there something missing?

Sprinkle some debugging printfs around.

Darn it, reading CSV files directly into numerical values using C++ is going to take more using >> directly. Using >> to read from a CSV will consider the comma to be part of a string, not a delimiter; and for numerical value it will fill the initial variable, but since commas are not valid in int/float/double variables, the input will stop and the fail bit of the input stream is likely to be flipped when the delimiting comma is found. This in turn will invalidate the input stream until it is cleared, which would be very cumbersome to do after each input into a numerical value. I should have realized that initially, sorry.

Instead I think it would be best to read each piece of information between delimiting commas into strings using get() or getline() using ',' as the terminating char (I'd probably use getline() so it would remove the terminating comma from the input buffer when it was encountered without an additional step like using get() would require). Then since the fields would be known in advance, I'd convert the necessary strings to int/double/float whatever after the read in. Messy, but doable.

Seems like the OP is leaning toward C style rather than C++ so it's probably moot, except as (imperfect initial) demonstration.

EDIT:
Are comma separated files routinely divided into lines or is everything data comma data comma data comma until EOF without newline separation, or is either way appropriate?

I don't use C style I/O routinely, so how will sscanf() handle the comma delimiters--remove them from the string so they don't muddle up things automatically or do users have to account for them?

Okay...so here's where it's at:

#include <stdio.h>
#include <stdlib.h>

struct sRecord
{
   int    date, volume;
   char time;
   double price[4];
};

int main(void)
{
   static const char filename[] = "file.csv";
   FILE *file = fopen(filename, "r");
   
   printf("file opened\n");
   system("pause");  
    
   if ( file )
   {
      size_t i = 0, size = 30;
      struct sRecord *array = malloc(size * sizeof *array);
      
      printf("assigned memory to array address\n");
      system("pause");  
   
      if ( array )
      {
         char line[128];
         
         printf("entering While loop\n");
         system("pause");  
      
         while ( i < size && fgets(line, sizeof line, file) )
         {
            if ( sscanf(line, "%d,%c,%lf,%lf,%lf,%lf,%ld",
                        &array[i].date, &array[i].time,
                        &array[i].price[0], &array[i].price[1],
                        &array[i].price[2], &array[i].price[3],
                        &array[i].volume) == 7 )
            {
               ++i;
            }
          
         }
         
         printf("leaving While loop\n");
         system("pause"); 
         
         fclose(file);
         
         printf("Closed File\n");
         system("pause"); 
         
                   /* Test first three rows of Array */
         
                   printf("%d,%c,%lf,%lf,%lf,%lf,%ld\n", array[0].date, array[0].time,
                   array[0].price[0], array[0].price[1], array[0].price[2],
                   array[0].price[3], array[0].volume);
                   
                   printf("\n");
                   
                   printf("%d,%c,%lf,%lf,%lf,%lf,%ld\n", array[1].date, array[1].time,
                   array[1].price[0], array[1].price[1], array[1].price[2],
                   array[1].price[3], array[1].volume);
                   
                   printf("\n");
                   
                   printf("%d,%c,%lf,%lf,%lf,%lf,%ld\n", array[2].date, array[2].time,
                   array[2].price[0], array[2].price[1], array[2].price[2],
                   array[2].price[3], array[2].volume);
         
         printf("Test Row\n");
         system("pause"); 
         
         /*
          * [Modify contents]
          */
                  
         for ( i = 0; i < size; ++i )
         {
            printf("%d,%c,%lf,%lf,%lf,%lf,%ld\n", array[i].date, array[i].time,
                   array[i].price[0], array[i].price[1], array[i].price[2],
                   array[i].price[3], array[i].volume);
         }
         
         printf("File printed\n");
         system("pause"); 
         
         free(array);
      }
   }
   else
   {
      perror(filename);
   }
   
   system("pause");

   return 0;
     
}

Here's the test data:

20041201,0:00,102.74,102.77,102.74,102.76,5
20041201,0:05,102.78,102.78,102.75,102.75,3
20041201,0:10,102.75,102.75,102.7,102.7,7
20041201,0:15,102.7,102.72,102.7,102.72,8
20041201,0:20,102.73,102.74,102.73,102.74,2
20041201,0:25,102.73,102.73,102.7,102.7,4
20041201,0:30,102.71,102.71,102.68,102.7,10
20041201,0:35,102.71,102.73,102.68,102.69,15
20041201,0:40,102.7,102.71,102.69,102.71,12
20041201,0:45,102.71,102.73,102.71,102.73,2
20041201,0:50,102.74,102.78,102.74,102.77,12
20041201,0:55,102.77,102.8,102.77,102.79,17


Here's the output:

file opened
Press any key to continue . . .
assigned memory to array address
Press any key to continue . . .
entering While loop
Press any key to continue . . .
leaving While loop
Press any key to continue . . .
Closed File
Press any key to continue . . .
20041201,0,0.000000,0.000000,0.000000,0.000000,3998072

0, ,0.000000,0.000000,0.000000,0.000000,0

0, ,0.000000,0.000000,0.000000,0.000000,0
Test Row
Press any key to continue . . .
20041201,0,0.000000,0.000000,0.000000,0.000000,3998072
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
0, ,0.000000,0.000000,0.000000,0.000000,0
File printed
Press any key to continue . . .

My Questions:

1) How is malloc supposed to provide the correct amount of memory if it doesn't even know what's stored in array[] yet? Doesn't array[] get filled in the loop below the allocation statement? So it won't know the size until then?

2) The program is only printing the correct first date in the list and then prints 0's for everything else...anyone see a reason?

Thanks for the help,

Nolan

1) How is malloc supposed to provide the correct amount of memory if it doesn't even know what's stored in array[] yet?

This is one of the reasons I chose a vector instead.

2) The program is only printing the correct first date in the list and then prints 0's for everything else...anyone see a reason?

You're really not checking to see if data was successfully read. For example, "0:00" is not a single character.

[edit]Maybe I'll edit again to highlight some of the differences.

#include <stdio.h>
#include <stdlib.h>

struct sRecord
{
   int    date, volume;
   char   time[8];
   double price[4];
};

int main(void)
{
   static const char filename[] = "file.csv";
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      size_t i = 0, count, size = 30;
      struct sRecord *array = malloc(size * sizeof *array);
      if ( array )
      {
         char line[128];
         while ( i < size && fgets(line, sizeof line, file) )
         {
            if ( sscanf(line, "%d,%7[^,],%lf,%lf,%lf,%lf,%d",
                        &array[i].date, array[i].time,
                        &array[i].price[0], &array[i].price[1],
                        &array[i].price[2], &array[i].price[3],
                        &array[i].volume) == 7 )
            {
               ++i;
            }
         }
         fclose(file);
         /*
          * [Modify contents]
          */
         for ( count = i, i = 0; i < count; ++i )
         {
            printf("%d,%s,%f,%f,%f,%f,%d\n", array[i].date, array[i].time,
                   array[i].price[0], array[i].price[1], array[i].price[2],
                   array[i].price[3], array[i].volume);
         }
         free(array);
      }
   }
   else
   {
      perror(filename);
   }
   return 0;
}

/* file.csv
20041201,0:00,102.74,102.77,102.74,102.76,5
20041201,0:05,102.78,102.78,102.75,102.75,3
20041201,0:10,102.75,102.75,102.7,102.7,7
20041201,0:15,102.7,102.72,102.7,102.72,8
20041201,0:20,102.73,102.74,102.73,102.74,2
20041201,0:25,102.73,102.73,102.7,102.7,4
20041201,0:30,102.71,102.71,102.68,102.7,10
20041201,0:35,102.71,102.73,102.68,102.69,15
20041201,0:40,102.7,102.71,102.69,102.71,12
20041201,0:45,102.71,102.73,102.71,102.73,2
20041201,0:50,102.74,102.78,102.74,102.77,12
20041201,0:55,102.77,102.8,102.77,102.79,17
*/

/* my output
20041201,0:00,102.740000,102.770000,102.740000,102.760000,5
20041201,0:05,102.780000,102.780000,102.750000,102.750000,3
20041201,0:10,102.750000,102.750000,102.700000,102.700000,7
20041201,0:15,102.700000,102.720000,102.700000,102.720000,8
20041201,0:20,102.730000,102.740000,102.730000,102.740000,2
20041201,0:25,102.730000,102.730000,102.700000,102.700000,4
20041201,0:30,102.710000,102.710000,102.680000,102.700000,10
20041201,0:35,102.710000,102.730000,102.680000,102.690000,15
20041201,0:40,102.700000,102.710000,102.690000,102.710000,12
20041201,0:45,102.710000,102.730000,102.710000,102.730000,2
20041201,0:50,102.740000,102.780000,102.740000,102.770000,12
20041201,0:55,102.770000,102.800000,102.770000,102.790000,17
*/

[/edit]

C doesn't explicitly support vectors, right? Otherwise, why bother using malloc at all?

No, C doesn't have vectors, which can make this problem a little easier. That's why I asked up front in regard to the design.

[edit]So sticking with that...

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdio>

struct sRecord
{
   int    date, volume;
   char   time[8];
   double price[4];
};

bool operator< (const struct sRecord &a, const struct sRecord &b)
{
   return a.volume < b.volume;
}

std::ostream& operator<< (std::ostream &o, struct sRecord &r)
{
   return o << r.date     << ","
            << r.time     << ","
            << r.price[0] << ","
            << r.price[1] << ","
            << r.price[2] << ","
            << r.price[3] << ","
            << r.volume;
}

int main(void)
{
   std::vector<sRecord> record;
   const std::string filename("file.csv");
   std::ifstream file(filename.c_str());
   if ( file )
   {
      std::string line;
      while ( file >> line )
      {
         sRecord data;
         if ( std::sscanf(line.c_str(), "%d,%7[^,],%lf,%lf,%lf,%lf,%d",
                          &data.date, &data.time, &data.price[0], &data.price[1],
                          &data.price[2], &data.price[3], &data.volume) == 7 )
         {
            record.push_back(data);
         }
      }
   }
   /*
    * [Modify contents]
    */
   std::sort(record.begin(), record.end());
   std::copy(record.begin(), record.end(),
             std::ostream_iterator<sRecord>(std::cout, "\n"));
   return 0;
}

/* file.csv
20041201,0:00,102.74,102.77,102.74,102.76,5
20041201,0:05,102.78,102.78,102.75,102.75,3
20041201,0:10,102.75,102.75,102.7,102.7,7
20041201,0:15,102.7,102.72,102.7,102.72,8
20041201,0:20,102.73,102.74,102.73,102.74,2
20041201,0:25,102.73,102.73,102.7,102.7,4
20041201,0:30,102.71,102.71,102.68,102.7,10
20041201,0:35,102.71,102.73,102.68,102.69,15
20041201,0:40,102.7,102.71,102.69,102.71,12
20041201,0:45,102.71,102.73,102.71,102.73,2
20041201,0:50,102.74,102.78,102.74,102.77,12
20041201,0:55,102.77,102.8,102.77,102.79,17
*/

/* my output
20041201,0:20,102.73,102.74,102.73,102.74,2
20041201,0:45,102.71,102.73,102.71,102.73,2
20041201,0:05,102.78,102.78,102.75,102.75,3
20041201,0:25,102.73,102.73,102.7,102.7,4
20041201,0:00,102.74,102.77,102.74,102.76,5
20041201,0:10,102.75,102.75,102.7,102.7,7
20041201,0:15,102.7,102.72,102.7,102.72,8
20041201,0:30,102.71,102.71,102.68,102.7,10
20041201,0:40,102.7,102.71,102.69,102.71,12
20041201,0:50,102.74,102.78,102.74,102.77,12
20041201,0:35,102.71,102.73,102.68,102.69,15
20041201,0:55,102.77,102.8,102.77,102.79,17
*/

I didn't know what to sort by, so I chose volume.

This article has been dead for over six months. Start a new discussion instead.