Re: Conversion functions.




yeti>> I have tested your minimal testprogram with the whole
test-file. Unfortunately the program doesn't print anything to
stdout. It doesn't seem to be any data stored in the GSList
or in the datastructure, Data *data. (I tried to print a field
every time a new line was about to be read in the while-loop).
Furthermore, I wonder if the test,
 if(end == start)
   failfield = "Latitude";,
can conclude that the string was converted correctly with
g_ascii_strtod(). If g_ascii_strtod() converts only a fraction 
of the string, it will result in (end != start) and failfield
won't be set which results in no output to stderr.

Magnus
  

 On Thu, 6 Sep 2007 21:13:44 +0200
David Nečas (Yeti) <yeti physics muni cz> wrote:

On Thu, Sep 06, 2007 at 11:00:11AM -0300, Matí­as Alejandro Torres
wrote:
Here's the minimal program to read that. The reading part is kind
of crappy but it works with that example.

The trouble with the reading part is not that it's kind of
crappy (well, it is IMO, reading by character makes no sense
when g_ascii_strtod() and strtol() can perfectly iterate
themselves *and* have error-reporting, g_slist_append() is
O(N) making the reading O(N^2), it is a waste of time to
construct a big GSList just to fill a GtkListStore from it
instead of filling the store directly -- and if Data is
a data structure used elsewhere in the program it makes
little sense to break it into columns instead of storing it
directly in a G_TYPE_BOXED/G_TYPE_POINTER column), but that:
- it assigns the fgetc() return value to a gchar, breaking
  EOF testing
- it uses a fixed unchecked buffer of size 50 we do now know
  whether overflows or not on your data
- it takes any sequence of non-[ \t] as a field and reads
  it without checking so we do not know what actually
  happens on your data
- it uses g_strtod() (NOT g_ascii_strtod() you've been
  talking about) which tries to accept both C and your
  current locale formats and therefore is not predictable
  (and won't help reading data that someone with
  a *different* local wrote in the locale-specific manner
  anyway)

If the attached program reads the complete file and prints
back its contents correctly, then I dare to say your problem
is not broken g_ascii_strtod().  As a bonus, the attached
program prints a detailed error to stderr if there are
malformed data rows in the file.

Yeti

--
http://gwyddion.net/


=========================================================================
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>

typedef struct _Data {
    gchar   *log;
    gdouble latitude;
    gint    altitude;
    gint    interval;
    gint    heartbeat;
    gdouble speed;
} Data;


int
main(int argc,
     char *argv[])
{
    const gchar *filename, *failfield;
    gchar *buf = NULL;
    size_t buf_size = 0, lineno;
    ssize_t line_len;
    FILE *fh;
    GSList *l, *stuff = NULL;
    Data *data;

    if (argc != 2) {
        g_printerr("readstuff FILE\n");
        return 1;
    }

    filename = argv[1];
    if (!(fh = fopen(filename, "r"))) {
        g_printerr("Cannot open %s: %s\n", filename,
g_strerror(errno)); return 1;
    }

    lineno = 0;
    failfield = NULL;
    while ((line_len = getline(&buf, &buf_size, fh)) != -1) {
        gchar *start, *end;
        guint len;

        lineno++;
        start = g_strstrip(buf);
        /* Skip non-data lines */
        if (!buf[0] || !g_ascii_isdigit(buf[0]))
            continue;

        data = g_new(Data, 1);
        len = strcspn(start, " \t");
        data->log = g_strndup(start, len);
        start += len;

        data->latitude = g_ascii_strtod(start, &end);
        if (end == start) {
            failfield = "Latitude";
            break;
        }
        start = end;

        data->altitude = strtol(start, &end, 10);
        if (end == start) {
            failfield = "Altitude";
            break;
        }
        start = end;

        data->interval = strtol(start, &end, 10);
        if (end == start) {
            failfield = "IntervalTime";
            break;
        }
        start = end;

        data->heartbeat = strtol(start, &end, 10);
        if (end == start) {
            failfield = "HeartRate";
            break;
        }
        start = end;

        data->speed = g_ascii_strtod(start, &end);
        if (end == start) {
            failfield = "Speed";
            break;
        }

        stuff = g_slist_prepend(stuff, data);

        if (*end)
            fprintf(stderr, "Warning: trailing garbage at line %lu of
%s: %s\n", (unsigned long int)lineno, filename, buf);
    }

    fclose(fh);
    free(buf);

    if (failfield) {
        fprintf(stderr, "Cannot parse %s at line %lu of %s: %s\n",
                failfield, (unsigned long int)lineno, filename, buf);
        g_free(data->log);
        g_free(data);
    }
    else {
        stuff = g_slist_reverse(stuff);
        for (l = stuff; l; l = l->next) {
            data = (Data*)l->data;
            printf("%s %.5f %d %d %d %.2f\n",
                   data->log, data->latitude, data->altitude,
                   data->interval, data->heartbeat, data->speed);
        }
    }

    for (l = stuff; l; l = l->next) {
        data = (Data*)l->data;
        g_free(data->log);
        g_free(data);
    }
    g_slist_free(stuff);

    return !!failfield;
}
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]