473,287 Members | 1,555 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

Reading a table

Hello,

My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is

00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.

Any suggestions would be great!

Thanks.
Nov 26 '07 #1
21 2998
On Nov 26, 11:04 am, Stephen.Schoenber...@gmail.com wrote:
Hello,

My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is

00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.

Any suggestions would be great!
fopen() to open the file.
fgets() to read in one line at a time.
write your own function to parse it, because only you know the format.

HTH
Nov 26 '07 #2
On Nov 26, 2:10 pm, user923005 <dcor...@connx.comwrote:
On Nov 26, 11:04 am, Stephen.Schoenber...@gmail.com wrote:
Hello,
My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is
00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000
I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.
Any suggestions would be great!

fopen() to open the file.
fgets() to read in one line at a time.
write your own function to parse it, because only you know the format.

HTH
Thanks!
Nov 26 '07 #3
St******************@gmail.com wrote:
Hello,

My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is

00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.

Any suggestions would be great!
Arrays in C are indexed from 0. You can leave the first one empty if
you're determined to have 1-based indexing, but it's not an overly good
idea.

I'd also suggest a two-dimensional array, rather than separate ones
named "array1" etc. That makes for easier handling, as the entire table
OR individual rows can be passed to functions or whatever. So the first
row would be table[0], and the first element would be table[0][0].

It's especially easy if you happen to know the number of rows and
columns going in, otherwise you'll probably need a dynamic array. Of
course, you still need to come up with a data type for the elements
themselves, presumably char*, but it's not clear what the parsing
actually consists of. We'd need more information.


Brian
Nov 26 '07 #4

<St******************@gmail.comwrote in message
news:91**********************************@w34g2000 hsg.googlegroups.com...
On Nov 26, 2:10 pm, user923005 <dcor...@connx.comwrote:
On Nov 26, 11:04 am, Stephen.Schoenber...@gmail.com wrote:
Hello,
My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is
00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000
I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.
Any suggestions would be great!
fopen() to open the file.
fgets() to read in one line at a time.
write your own function to parse it, because only you know the format.

HTH

Thanks!
He forgot to tell you about fclose()!

Anyway...

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

#define LINEMAX 512

extern unsigned
assign_text_file_line_fields
(char *,unsigned (*)(unsigned,char *,void *),void *);

static FILE *text_file;

static char text_line[LINEMAX];

/* assigns field values from text file lines using callback function */
unsigned assign_text_file_line_fields
(char *text_file_path,
unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
unsigned line_num=0;
ret_val=FALSE;

/* try to open text file, return if failure */
if((text_file=fopen(text_file_path,"rt"))==NULL) {
printf("\nERROR: Could not open text file\n%s",
text_file_path);
goto EXIT_FUNCTION;
}

/* get every line in file, pass to callback function */
while((fgets(text_line,LINEMAX,text_file))!=NULL) {

if(!assign_func(line_num,text_line,assign_ptr)) {
printf("ERROR: Could not assign line %d fields);
goto CLOSE_TEXT_FILE;
}

line_num++;
}

/* OK, looks like we've succeeded */
ret_val=TRUE;

/* try to close file, warn if failure */
CLOSE_TEXT_FILE :
if((fclose(db_init_file))==EOF)
printf("\nWARNING: Problem closing text file\n%s",
text_file_path);

/* buh-bye */
EXIT_FUNCTION :
return ret_val;
}

If you set up the above in its own little object file/library or
whatever, you can link it into any program when you need to
parse any type of text file with regularly-formatted lines of
column-data, by writing a specific assign_func for each type
of file, and declaring a suitable multi-dimensional array (or
array of structs) to hold the data:

typedef struct My_Data {
double field_1;
unsigned field_2;
int field_3;
} My_Data;

My_Data my_data_array[100];

My_Data *my_data_array_ptr=&my_data_array;

static unsigned
assign_my_file_fields
(unsigned line_num,char *text_line,void *data_ptr) {
My_Data *my_data_ptr=data_ptr;
my_data_ptr+=line_num;

/* line parsing and assigning goes here */

}

assign_text_file_line_fields
(text_file_path,assign_my_file_fields,(void *)(my_data_array_ptr));

And you'll never have to write the file opening, reading, and closing
code ever again...the only reason I bring this up is because, of course,
I have literally hundreds of different text file formats to read in my
own code...

---
William Ernest Reid

Nov 27 '07 #5
St******************@gmail.com wrote:
>
Hello,

My C is a bit rusty (.NET programmer normally but need to do this in
C) and I need to read in a text file that is setup as a table. The
general form of the file is

00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.
/* BEGIN file_parse.c output */

Input file:
0000000000 USNIST00Z 00000000_00 8 318 318 068 9318 068
0000000001 USNIST00Z 00000000_00 9 619 119 119 7619 119
0000000002 USNIST00Z 00000000_00 2 252 252 002 6252 002

Resulting array:
array[0][0] 0000000000
array[0][1] USNIST00Z
array[0][2] 00000000_00
array[0][3] 8
array[0][4] 318
array[0][5] 318
array[0][6] 068
array[0][7] 9318
array[0][8] 068
array[1][0] 0000000001
array[1][1] USNIST00Z
array[1][2] 00000000_00
array[1][3] 9
array[1][4] 619
array[1][5] 119
array[1][6] 119
array[1][7] 7619
array[1][8] 119
array[2][0] 0000000002
array[2][1] USNIST00Z
array[2][2] 00000000_00
array[2][3] 2
array[2][4] 252
array[2][5] 252
array[2][6] 002
array[2][7] 6252
array[2][8] 002
/* END file_parse.c output */
/* BEGIN file_parse.c */
/*
My C is a bit rusty
(.NET programmer normally but need to do this in C)
and I need to read in a text file that is setup as a table.
The general form of the file is

00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

I need to read the file line by line and eventually parse out each
piece of the file and store in arrays that correspond to the specific
line. array1[1] would be the first entry in the first line and so on
and so forth.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

#define LINES_PER_FILE 3
#define LU_RAND_SEED 123456789LU
#define LU_RAND(S) ((S) * 69069 + 362437 & 0XFFFFFFFFLU)
#define NMEMB(A) (sizeof (A) / sizeof *(A))

struct list_node {
struct list_node *next;
void *data;
};

typedef struct list_node list_type;

int get_line(char **lineptr, size_t *n, FILE *stream);
int list_fputs(list_type *node, FILE *stream);
list_type *list_append(list_type **head,
list_type *tail,
void *data,
size_t size);
void list_free(list_type *node, void (*free_data)(void *));
void no_free(void *data);
void free_ptrs(char ***p, size_t nmemb);
void display_array(char ***p, size_t nmemb, size_t n_fields);

int main(void)
{
long unsigned lu_seed, line, n_fields, field;
int rc;
char *buff, *ptr;
size_t size;
list_type *tail, *head;
char fn[L_tmpnam];
FILE *fp;
char ***f;

puts("/* BEGIN file_parse.c output */");
/*
** Open temporary input text file for writing.
*/
lu_seed = LU_RAND_SEED;
tmpnam(fn);
fp = fopen(fn, "w");
if (fp == NULL) {
fputs("fopen(fn), \"w\") == NULL\n", stderr);
exit(EXIT_FAILURE);
}
for (line = 0; line != LINES_PER_FILE; ++line) {
lu_seed = LU_RAND(lu_seed);
fprintf(fp,
"%.10lu %s %.1lu %.3lu %.3lu %.3lu %.4lu %.3lu\n",
line, "USNIST00Z 00000000_00",
lu_seed % 10, lu_seed % 1000,
lu_seed % 500, lu_seed % 250,
lu_seed % 10000, lu_seed % 125);
}
/*
** Close file.
*/
fclose(fp);
/*
** Open input text file for reading.
** Represent each line of the input text file
** as a string in a node of a linked list.
** Close temp input file after reading.
*/
size = 0;
buff = NULL;
head = tail = NULL;
fp = fopen(fn, "r");
if (fp == NULL) {
remove(fn);
fputs("fopen(fn), \"r\") == NULL\n", stderr);
exit(EXIT_FAILURE);
}
while ((rc = get_line(&buff, &size, fp)) 0) {
tail = list_append(&head, tail, buff, strlen(buff) + 1);
if (tail == NULL) {
fputs("tail == NULL\n", stderr);
break;
}
}
fclose(fp);
/*
** Free allocated buffer used by get_line function.
** Remove temporary input file.
*/
free(buff);
remove(fn);
if (rc != EOF) {
list_free(head, free);
fprintf(stderr, "rc == %d\n", rc);
exit(EXIT_FAILURE);
}
/*
** Display linked list.
*/
puts("\nInput file:");
list_fputs(head, stdout);
/*
** Create array.
*/
n_fields = 1;
for (ptr = head -data; *ptr != '\0'; ++ptr) {
if (*ptr == ' ') {
++n_fields;
}
}
f = malloc(line * sizeof *f);
if (f == NULL) {
list_free(head, free);
fputs("f == NULL\n", stderr);
exit(EXIT_FAILURE);
}
for (line = 0; line != LINES_PER_FILE; ++line) {
f[line] = malloc(n_fields * sizeof *f[line]);
if (f[line] == NULL) {
puts("f[line] == NULL");
exit(EXIT_FAILURE);
}
}
/*
** Tokenise list data and
** assign string addresses to pointers in array.
*/
line = 0;
for (tail = head; tail != NULL; tail = tail -next) {
f[line][0] = tail -data;
for (field = 1; field != n_fields; ++field) {
f[line][field] = strchr(f[line][field - 1], ' ');
if (f[line][field] == NULL) {
puts("f[line][field] == NULL");
exit(EXIT_FAILURE);
}
*f[line][field]++ = '\0';
}
++line;
}
/*
** Free list nodes but not node->data.
*/
list_free(head, no_free);
/*
** Display resulting array.
*/
puts("\nResulting array:");
display_array(f, LINES_PER_FILE, n_fields);
/*
** Free array.
*/
free_ptrs(f, LINES_PER_FILE);
free(f);
puts("/* END file_parse.c output */");
return 0;
}

void display_array(char ***p, size_t nmemb, size_t n_fields)
{
long unsigned line, field;

for (line = 0; line != nmemb; ++line) {
for (field = 0; field != n_fields; ++field) {
printf("array[%lu][%lu] %s\n",
line, field, p[line][field]);
}
puts("\n");
}
}

void free_ptrs(char ***p, size_t nmemb)
{
while (nmemb-- != 0) {
free(p[nmemb]);
}
}

int get_line(char **lineptr, size_t *n, FILE *stream)
{
int rc;
void *p;
size_t count;

count = 0;
while ((rc = getc(stream)) != EOF) {
if (count != (size_t)-2) {
++count;
}
if ((size_t)(count + 2u) *n) {
p = realloc(*lineptr, count + 2);
if (p == NULL) {
if (*n count) {
if (rc != '\n') {
(*lineptr)[count] = '\0';
(*lineptr)[count - 1] = (char)rc;
} else {
(*lineptr)[count - 1] = '\0';
}
} else {
if (*n != 0) {
**lineptr = '\0';
}
ungetc(rc, stream);
}
count = 0;
break;
}
*lineptr = p;
*n = count + 2;
}
if (rc == '\n') {
(*lineptr)[count - 1] = '\0';
break;
}
(*lineptr)[count - 1] = (char)rc;
}
if (rc != EOF) {
rc = INT_MAX count ? count : INT_MAX;
} else {
if (*n count) {
(*lineptr)[count] = '\0';
}
}
return rc;
}

int list_fputs(list_type *node, FILE *stream)
{
while (node != NULL) {
if (fputs(node -data, stream) == EOF) {
return EOF;
}
if (putc('\n', stream) == EOF) {
return EOF;
}
node = node -next;
}
return '\n';
}

list_type *list_append(list_type **head,
list_type *tail,
void *data,
size_t size)
{
list_type *node;

node = malloc(sizeof *node);
if (node != NULL) {
node -next = NULL;
node -data = malloc(size);
if (node -data != NULL) {
memcpy(node -data, data, size);
if (*head != NULL) {
tail -next = node;
} else {
*head = node;
}
} else {
free(node);
node = NULL;
}
}
return node;
}

void list_free(list_type *node, void (*free_data)(void *))
{
list_type *next_node;

while (node != NULL) {
next_node = node -next;
free_data(node -data);
free(node);
node = next_node;
}
}

void no_free(void *data)
{
data;
}

/* END file_parse.c */
--
pete
Nov 29 '07 #6
pete wrote:
/* BEGIN file_parse.c */
I rewrote some of the code.
long unsigned lu_seed, line, n_fields, field;
Could use another variable to count file lines.

long unsigned lu_seed, line, n_lines, n_fields, field;
for (line = 0; line != LINES_PER_FILE; ++line) {
f[line] = malloc(n_fields * sizeof *f[line]);
if (f[line] == NULL) {
puts("f[line] == NULL");
exit(EXIT_FAILURE);
}
}
Some of the cleanup could be better.

for (line = 0; line != n_lines; ++line) {
f[line] = malloc(n_fields * sizeof *f[line]);
if (f[line] == NULL) {
free_ptrs(f, line);
list_free(head, free);
puts("f[line] == NULL");
exit(EXIT_FAILURE);
}
f[line][0] = NULL;
}
if (f[line][field] == NULL) {
puts("f[line][field] == NULL");
exit(EXIT_FAILURE);
}
if (f[line][field] == NULL) {
free_ptrs(f, n_lines);
list_free(head, free);
puts("f[line][field] == NULL");
exit(EXIT_FAILURE);

free_ptrs(f, LINES_PER_FILE);
free(f);
Instead of the above two lines, just this one:

free_ptrs(f, n_lines);
void free_ptrs(char ***p, size_t nmemb)
{
while (nmemb-- != 0) {
free(p[nmemb]);
}
}
This version of free_ptrs, frees the list data,
which I had neglected to do before.

void free_ptrs(char ***p, size_t nmemb)
{
while (nmemb-- != 0) {
free(p[nmemb][0]);
free(p[nmemb]);
}
free(p);
}

--
pete
Nov 29 '07 #7
On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
>Anyway...

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

#define LINEMAX 512

extern unsigned
assign_text_file_line_fields
(char *,unsigned (*)(unsigned,char *,void *),void *);

static FILE *text_file;

static char text_line[LINEMAX];

/* assigns field values from text file lines using callback function */
unsigned assign_text_file_line_fields
(char *text_file_path,
unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
unsigned line_num=0;
ret_val=FALSE;

/* try to open text file, return if failure */
if((text_file=fopen(text_file_path,"rt"))==NULL) {
printf("\nERROR: Could not open text file\n%s",
text_file_path);
goto EXIT_FUNCTION;
}

/* get every line in file, pass to callback function */
while((fgets(text_line,LINEMAX,text_file))!=NULL) {

if(!assign_func(line_num,text_line,assign_ptr)) {
printf("ERROR: Could not assign line %d fields);
goto CLOSE_TEXT_FILE;
}

line_num++;
}

/* OK, looks like we've succeeded */
ret_val=TRUE;

/* try to close file, warn if failure */
CLOSE_TEXT_FILE :
if((fclose(db_init_file))==EOF)
printf("\nWARNING: Problem closing text file\n%s",
text_file_path);

/* buh-bye */
EXIT_FUNCTION :
return ret_val;
}
Your callback solution has its merits. But you could have done it

- without gotos
- whithout static FILE
- for arbitrary long lines (no hard-coded maximum line lenght)
- with a typedef for the callback function for better readability
- with an explanation for "rt" instead of "r"
- returning error codes instead of using printfs
- with self-explanatory names e.g. process_file_by_line (insted of
assign_text_file_line_fields), process_line (instead of assign_func),
data or context (instead of assign_ptr)

--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Nov 29 '07 #8

Roland Pibinger <rp*****@yahoo.comwrote in message
news:47*************@news.utanet.at...
On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
Anyway...

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

#define LINEMAX 512

extern unsigned
assign_text_file_line_fields
(char *,unsigned (*)(unsigned,char *,void *),void *);

static FILE *text_file;

static char text_line[LINEMAX];

/* assigns field values from text file lines using callback function */
unsigned assign_text_file_line_fields
(char *text_file_path,
unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
unsigned line_num=0;
ret_val=FALSE;

/* try to open text file, return if failure */
if((text_file=fopen(text_file_path,"rt"))==NULL) {
printf("\nERROR: Could not open text file\n%s",
text_file_path);
goto EXIT_FUNCTION;
}

/* get every line in file, pass to callback function */
while((fgets(text_line,LINEMAX,text_file))!=NULL) {

if(!assign_func(line_num,text_line,assign_ptr)) {
printf("ERROR: Could not assign line %d fields);
goto CLOSE_TEXT_FILE;
}

line_num++;
}

/* OK, looks like we've succeeded */
ret_val=TRUE;

/* try to close file, warn if failure */
CLOSE_TEXT_FILE :
if((fclose(db_init_file))==EOF)
printf("\nWARNING: Problem closing text file\n%s",
text_file_path);

/* buh-bye */
EXIT_FUNCTION :
return ret_val;
}

Your callback solution has its merits. But you could have done it

- without gotos
They're worth it just to irritate some people and don't hurt
anything...
- whithout static FILE
Possibly, but the idea here is just to read a single file and
then close it right up...
- for arbitrary long lines (no hard-coded maximum line lenght)
Yes, but again the idea here is we KNOW the maximum size
of our file lines, almost certainly because we wrote them in the
first place with trusted and checked data (note that I left out anything
about sizing the array for the number of lines, that's left "up to the
reader")...in real life, I do have a similar function that does dynamic
resizing for arbitrarily long lines for other types of files...
- with a typedef for the callback function for better readability
Uh, yeah, maybe, I'm not sure I'm following you here...
- with an explanation for "rt" instead of "r"
Read the friggin' man page!
- returning error codes instead of using printfs
Up to the original poster to implement their error handling
routines; actually, I use something else in "real life" but modified
it for "readability"...
- with self-explanatory names e.g. process_file_by_line (insted of
assign_text_file_line_fields), process_line (instead of assign_func),
data or context (instead of assign_ptr)
Yeah, semantics, maybe...
"The best software is simple, elegant, and full of drama" - Grady Booch
Ah, brinksmanship, most applicable to nuclear power plant software...

---
William Ernest Reid

Nov 30 '07 #9
Bill Reid wrote:
Roland Pibinger <rp*****@yahoo.comwrote in message
.... snip ...
>
>- whithout static FILE

Possibly, but the idea here is just to read a single file and
then close it right up...
>- for arbitrary long lines (no hard-coded maximum line lenght)

Yes, but again the idea here is we KNOW the maximum sizeof our
file lines,
However, some people want to copy files without worrying about line
length. With ggets (and fggets) you can handle this with ease, as
in the following:

[1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c

[1] c:\c\junk>fcopylns <junk.c
#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

int main(void) {
char *line;

while (0 == ggets(&line)) {
puts(line);
free(line);
}
return 0;
} /* main, fcopylns */

Note the complexity. You can get the source etc. for ggets at:

<http://cbfalconer.home.att.net/download/ggets.zip>

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 30 '07 #10
Bill Reid wrote:
>
Roland Pibinger <rp*****@yahoo.comwrote in message
news:47*************@news.utanet.at...
On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
if((text_file=fopen(text_file_path,"rt"))==NULL) {
- with an explanation for "rt" instead of "r"

Read the friggin' man page!
That's the problem.

Man pages aren't part of the C programming language.

Using "rt" as a second argument in a fopen function call
isn't part of the C programming language either.

--
pete
Nov 30 '07 #11

pete <pf*****@mindspring.comwrote in message
news:47***********@mindspring.com...
Bill Reid wrote:

Roland Pibinger <rp*****@yahoo.comwrote in message
news:47*************@news.utanet.at...
On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
if((text_file=fopen(text_file_path,"rt"))==NULL) {
- with an explanation for "rt" instead of "r"
Read the friggin' man page!

That's the problem.

Man pages aren't part of the C programming language.

Using "rt" as a second argument in a fopen function call
isn't part of the C programming language either.
Yeah, I guess you're right, from a completely strict interpretation
of the "standard"...except, of course, that the "standard" itself is
actually contradictory as a practical matter on the subject.

If "rt" is NOT a part of the "C programming language" (standard),
then of course it would be completely illegal to use "rt". But that's
NOT what the "standard" says, now is it?

Meanwhile, on my "implementation", there is a global file opening
mode variable that can be over-ridden by using either 't' or 'b'. Since
it is set to "O_TEXT" by default I don't actually NEED to use the "rt",
but since this has also been the case for several wildly-different
"implementations" in my experience, I am in the habit of setting it
that way. I suspect there aren't a lot of C compilers out there where
this would cause a problem, since a lot of them fudge around the
"undefined behavior" in their "man pages", explicitly allowing the
"rt" while acknowledging it is a waste of a character...

But, I guess you're "technically" correct, I should have noted that
to open a text file under the "C standard" you only need to use "r",
and "rt" MIGHT cause a "portability" problem...

---
William Ernest Reid

Nov 30 '07 #12
Bill Reid wrote:
CBFalconer <cb********@yahoo.comwrote in message
>Bill Reid wrote:
>>Roland Pibinger <rp*****@yahoo.comwrote in message
... snip ...
>>>
- whithout static FILE

Possibly, but the idea here is just to read a single file and
then close it right up...

- for arbitrary long lines (no hard-coded maximum line lenght)

Yes, but again the idea here is we KNOW the maximum sizeof our
file lines,

However, some people want to copy files without worrying about line
length. With ggets (and fggets) you can handle this with ease, as
in the following:

[1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c

[1] c:\c\junk>fcopylns <junk.c
#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

int main(void) {
char *line;

while (0 == ggets(&line)) {
puts(line);
free(line);
}
return 0;
} /* main, fcopylns */

Note the complexity. You can get the source etc. for ggets at:

<http://cbfalconer.home.att.net/download/ggets.zip>
Sure, something like that might come in handy in some situations,
but I actually take a somewhat different tack for parsing out text
"tables" with potentially (unpredictably) HUGE "field" sizes.
Try out ggets. It will handle ANY size line. I deliberately
designed it to replace gets, with the usage simplicity, but no
worry about over-run. It's primary use is in interactive work, but
the efficiency is not bad for general use.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 30 '07 #13
CBFalconer said:

<snip>
Try out ggets. It will handle ANY size line.
That's a dangerous claim. :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 30 '07 #14
"Bill Reid" <ho********@happyhealthy.netwrites:
pete <pf*****@mindspring.comwrote in message
news:47***********@mindspring.com...
>Bill Reid wrote:
>
Roland Pibinger <rp*****@yahoo.comwrote in message
news:47*************@news.utanet.at...
On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
if((text_file=fopen(text_file_path,"rt"))==NULL) {
- with an explanation for "rt" instead of "r"

Read the friggin' man page!

That's the problem.

Man pages aren't part of the C programming language.

Using "rt" as a second argument in a fopen function call
isn't part of the C programming language either.
Yeah, I guess you're right, from a completely strict interpretation
of the "standard"...except, of course, that the "standard" itself is
actually contradictory as a practical matter on the subject.
Why do you insist on using scare-quotes for the word "standard"? And
how is the standard contradictory?
If "rt" is NOT a part of the "C programming language" (standard),
then of course it would be completely illegal to use "rt". But that's
NOT what the "standard" says, now is it?
Here's what the standard actually says:

The argument mode points to a string. If the string is one of the
following, the file is open in the indicated mode. Otherwise, the
behavior is undefined.

This is followed by a list of mode strings, including "r" but not
including "rt". The "r" mode specifies opening a text file for
reading.

I see no contradiction. Using "rt" is not "completely illegal" (i.e.,
the implementation isn't required to reject it); the standard simply
assigns no meaning to it.
Meanwhile, on my "implementation", there is a global file opening
mode variable that can be over-ridden by using either 't' or 'b'. Since
it is set to "O_TEXT" by default I don't actually NEED to use the "rt",
but since this has also been the case for several wildly-different
"implementations" in my experience, I am in the habit of setting it
that way. I suspect there aren't a lot of C compilers out there where
this would cause a problem, since a lot of them fudge around the
"undefined behavior" in their "man pages", explicitly allowing the
"rt" while acknowledging it is a waste of a character...
There are *no* conforming C implementations on which using just "r"
rather than "rt" will cause a problem.
But, I guess you're "technically" correct, I should have noted that
to open a text file under the "C standard" you only need to use "r",
and "rt" MIGHT cause a "portability" problem...
Here's a clue. A simpler version of the phrase "technically correct"
is "correct". I can think of no reason to use "rt" rather than "r";
where "rt" is supported, it presumably does the same thing, and where
"rt" is not supported, using "r" is correct.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 30 '07 #15
CBFalconer wrote:
>
Bill Reid wrote:
CBFalconer <cb********@yahoo.comwrote in message
Bill Reid wrote:
Roland Pibinger <rp*****@yahoo.comwrote in message

... snip ...

- whithout static FILE

Possibly, but the idea here is just to read a single file and
then close it right up...

- for arbitrary long lines (no hard-coded maximum line lenght)

Yes, but again the idea here is we KNOW the maximum sizeof our
file lines,

However, some people want to copy files without worrying about line
length. With ggets (and fggets) you can handle this with ease, as
in the following:

[1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c

[1] c:\c\junk>fcopylns <junk.c
#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

int main(void) {
char *line;

while (0 == ggets(&line)) {
puts(line);
free(line);
}
return 0;
} /* main, fcopylns */

Note the complexity. You can get the source etc. for ggets at:

<http://cbfalconer.home.att.net/download/ggets.zip>
Sure, something like that might come in handy in some situations,
but I actually take a somewhat different tack for parsing out text
"tables" with potentially (unpredictably) HUGE "field" sizes.

Try out ggets. It will handle ANY size line. I deliberately
designed it to replace gets, with the usage simplicity, but no
worry about over-run. It's primary use is in interactive work, but
the efficiency is not bad for general use.
The definition of fggets declares no size_t type objects!

The cast in this expression in fggets, doesn't do anything:
realloc(buffer, (size_t)cursize))
I think that ggets.h:

int fggets(char* *ln, FILE *f);

#define ggets(ln) fggets(ln, stdin)

should also have this function declaration:

int (ggets)(char* *ln);

and that ggets.c should also have this function definition:

int (ggets)(char* *ln)
{
return ggets(ln);
}

--
pete
Nov 30 '07 #16
Richard Heathfield wrote:
CBFalconer said:

<snip>
>Try out ggets. It will handle ANY size line.

That's a dangerous claim. :-)
All right. Limited by available allocatable memory. It still
won't overrun.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 30 '07 #17
pete wrote:
CBFalconer wrote:
.... snip ...
>
>Try out ggets. It will handle ANY size line. I deliberately
designed it to replace gets, with the usage simplicity, but no
worry about over-run. It's primary use is in interactive work,
but the efficiency is not bad for general use.

The definition of fggets declares no size_t type objects!

The cast in this expression in fggets, doesn't do anything:
realloc(buffer, (size_t)cursize))
You didn't read it. cursize has been increased when this is
encountered. The testing in the zipfile proves it. Oh, you mean
the parameter. That is harmless. cursize should probably be a
size_t anyhow.
I think that ggets.h:

int fggets(char* *ln, FILE *f);
#define ggets(ln) fggets(ln, stdin)

should also have this function declaration:

int (ggets)(char* *ln);
Why?

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Dec 1 '07 #18
CBFalconer wrote:
>
pete wrote:
CBFalconer wrote:
... snip ...
Try out ggets. It will handle ANY size line. I deliberately
designed it to replace gets, with the usage simplicity, but no
worry about over-run. It's primary use is in interactive work,
but the efficiency is not bad for general use.
The definition of fggets declares no size_t type objects!

The cast in this expression in fggets, doesn't do anything:
realloc(buffer, (size_t)cursize))

You didn't read it. cursize has been increased when this is
encountered. The testing in the zipfile proves it. Oh, you mean
the parameter. That is harmless. cursize should probably be a
size_t anyhow.
I think that ggets.h:

int fggets(char* *ln, FILE *f);
#define ggets(ln) fggets(ln, stdin)

should also have this function declaration:

int (ggets)(char* *ln);

Why?
Just for kicks mostly.
That way you can both have the function and use the macro.

--
pete
Dec 1 '07 #19
Bill Reid wrote:
Keith Thompson <ks***@mib.orgwrote in message
news:87************@kvetch.smov.org...
....
>is "correct". I can think of no reason to use "rt" rather than "r";
where "rt" is supported, it presumably does the same thing, and where
"rt" is not supported, using "r" is correct.

Try reading what I actually wrote...carefully this time. With many
compilers, I might wind up opening the file as "binary" (now THAT'S
scary!)...
I know of compilers where text streams and binary streams behave in
exactly the same fashion (which is permitted). This is the norm for most
of the systems I've ever used; I've only seen them behave differently on
DOS/Windows machines, which I've rarely worked on.

Do you know of an implementation which has text streams which behave
differently from binary streams, where opening a text stream requires a
't' in the mode string? If so, it's non-conforming.

Dec 1 '07 #20
pete wrote:
>
pete wrote:
/* BEGIN file_parse.c */

I rewrote some of the code.
And then I decided to put it here:

http://www.mindspring.com/~pfilandr/...s/file_parse.c

--
pete
Dec 1 '07 #21
pete wrote:
CBFalconer wrote:
>pete wrote:
.... snip ...
>>
>>I think that ggets.h:

int fggets(char* *ln, FILE *f);
#define ggets(ln) fggets(ln, stdin)

should also have this function declaration:

int (ggets)(char* *ln);

Why?

Just for kicks mostly.
That way you can both have the function and use the macro.
Why? All that will ever do is increase the code space used and
slow down the operation. Zero benefit. Max. nuisance.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Dec 1 '07 #22

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Dariusz | last post by:
Below is part of a code I have for a database. While the database table is created correctly (if it doesn't exist), and data is input correctly into the database when executed, I have a problem...
7
by: gino | last post by:
Dear all, My monitor was set to 1600x1200 so the fonts in IE is too small for me even when I set the "View->Text Size->Largest"... I don't have previlage to change the monitor resolution... ...
2
by: cashdeskmac | last post by:
I have a form with 7 datagrids, each on a seperate tabpage and reading from it's own dataTable. I would like to take the first three fields of each row and show them in a listbox (for example, ID,...
2
by: Alexander Schmidt | last post by:
Hi, I am not very familiar with C++ programming, so before I do a dirty hack I ask for a more elegant solution (but only the usage of STL is allowed, no special libs). So I need to read a file...
3
by: Carl Lindmark | last post by:
*Cross-posting from microsoft.public.dotnet.languages.csharp, since I believe the question is better suited in this XML group* Hello all, I'm having some problems understanding all the ins and...
0
by: cashdeskmac | last post by:
I have a form with 7 datagrids, each on a seperate tabpage and reading from it's own dataTable. I would like to take the first three fields of each row and show them in a listbox (for example, ID,...
1
by: Mr. B | last post by:
VB.net 2003 c/w Framework 1.1 and MS Access db We have a commercial program that does our Acounting and Time Sheets (Timberline). At least once a day our Accounting department runs a Script...
9
by: dba123 | last post by:
I need some help and direction on what classes and an example or two (article) on how to read an Excel Worksheet and insert one column into a database table column. I am using .NET 2.0 only. What...
12
by: SAL | last post by:
Hello, Is it possible to read a CSV from the Client, and bind my Datagrid to the data in the CSV file without uploading the file to the Server first? I have tried and in Debug mode on my...
1
by: pvinod | last post by:
Hi, Consider a table have 10,00,000 records. What is the time difference between reading single record from the table and reading all the records from the table? which one will be faster? ...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.