splitting a string and put it into an array

K

Kai Jaensch

Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);


I hope, anybody can help me.
Thanx a lot.

Kai Jaensch
 
L

lallous

Kai Jaensch said:
Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);


I hope, anybody can help me.
Thanx a lot.

Kai Jaensch
Hello,

Since you're posting in C++, it is recommended that you use: file streams
instead of C file I/O.
Also use std::map to create a 2D array that will associate the project
number/Id with a user name
 
S

Sean Kenwrick

lallous said:
Kai Jaensch said:
Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);


I hope, anybody can help me.
Thanx a lot.

Kai Jaensch
Hello,

Since you're posting in C++, it is recommended that you use: file streams
instead of C file I/O.
Also use std::map to create a 2D array that will associate the project
number/Id with a user name
Which part of his code is C++?
 
S

Sean Kenwrick

Sean Kenwrick said:
lallous said:
Kai Jaensch said:
Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);


I hope, anybody can help me.
Thanx a lot.

Kai Jaensch
Hello,

Since you're posting in C++, it is recommended that you use: file streams
instead of C file I/O.
Also use std::map to create a 2D array that will associate the project
number/Id with a user name
Which part of his code is C++?
Sorry I see now that your reply was because he cross posted to comp.lang.c++
 
A

Al Bowers

Kai said:
Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);

IF your requirement is to put the line data in a two-d array
then change the variable row to such an array like:
char row[25][200];

Also, you have a logic error if there is a failure to open the
file.

Correcting these errors the code should be looking somewhat like
this:

#include <stdio.h>

#define MAXLN 25 /* max lines in the file */
#define MAXLNLEN 200 /* max line length in the file */

int main(void)
{
FILE *importFile;
char row[MAXLN][MAXLNLEN] ;
int i, anzahl = 0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else
{
printf("Datei offen.\n");
for( ; anzahl < MAXLN &&fgets(row[anzahl],
sizeof row[anzahl], importFile) != NULL; anzahl++) ;
fclose(importFile);
}
/* print results */
for( i = 0; i < anzahl ;i++)
printf(row);
putchar('\n');
return 0;
}
 
L

Lyn Powell

Kai Jaensch said:
I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

There are a few ways you can do this, but because you don't have to do any
numeric conversions, strtok would be one simple way:

for (line = 0; fgets(buff, sizeof buff, fp) != NULL; line++) {
char *t = strtok(line, "\t");
for (i = 0; t != NULL && i < 3; i++) {
strcpy(array[line], t);
strtok(NULL, "\t");
}
}

Of course, A better way IMO would be to use an array of structures:

struct record {
int project;
int ID;
char *name;
};

....

for (line = 0; fgets(buff, sizeof buff, fp) != NULL; line++) {
char *endp, buffp;
array[line].project = (int)strtol(buffp, &endp, 0);
buffp = endp;
array[line].ID = (int)strtol(buffp, &endp, 0);
/* You didn't specify how many tabs are allowed */
while (*endp == '\t')
endp++;
array[line].name = malloc(strlen(endp) + 1);
strcpy(array[line].name, endp);
}
 
S

Sidney Cadot

Mark said:
Thats so obviously wrong, it scarcely merits comment.

How's that?

Assume a (correct) C++ compiler. Consider any text. Assume that this
text, when fed to the aforementioned C++ compiler, leads to "succesful
compilation". Why is it wrong to conclude that the text is C++ code?
Could you provide a counter-example, or explain where my reasoning fails?

Best regards,

Sidney
 
A

Adam Fineman

Kai said:
Hello,

i am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.
Every row has to be splitted (delimiter is TAB) and has to be saved in
an two-dimensional array.

The background is that in the next step i have to search for an ID in
that array and after that this part of an array is to be used, that has
the content of data (of the row) which belongs to the ID.
The data are used later in the program.

I tried different ways, but without success.
And here is the code i´ve written til now just to open the file and to
show the data:

FILE *importFile;
char row[100] = {0};
char test_array[100];
int anzahl=0;
importFile = fopen("datei.txt","r");
if(importFile == NULL) printf("Datei geschlossen.\n");
else printf("Datei offen.\n");

while(fgets(row, sizeof row, importFile) != NULL)
{
puts(row);
anzahl++;
}
if(EOF) printf("%d\n", anzahl);
fclose(importFile);


I hope, anybody can help me.
Thanx a lot.

Kai Jaensch
#include <vector>
#include <string>
#include <iterator>
#include <iostream>
#include <algorithm>

using namespace std;

class row_t
{
int project_num;
int id;
string first_name;
string last_name;

public:
friend istream& operator>>(istream& is, row_t& r);
friend ostream& operator<<(ostream& os, const row_t& r);
};

istream&
operator>>(istream& is, row_t& r)
{
is >> r.project_num >> r.id >> r.first_name >> r.last_name;

return is;
}

ostream&
operator<<(ostream& os, const row_t& r)
{
os << r.project_num << '\t'
<< r.id << '\t'
<< r.first_name << '\t'
<< r.last_name;

return os;
}


int
main()
{
vector<row_t> array;

copy(istream_iterator<row_t>(cin), istream_iterator<row_t>(),
back_inserter(array));

copy(array.begin(), array.end(),
ostream_iterator<row_t>(cout, "\n"));

return 0;
}
 
J

Jack Klein

How's that?

Assume a (correct) C++ compiler. Consider any text. Assume that this
text, when fed to the aforementioned C++ compiler, leads to "succesful
compilation". Why is it wrong to conclude that the text is C++ code?
Could you provide a counter-example, or explain where my reasoning fails?

Best regards,

Sidney

The key is the phrase "successful compilation", which means no
required diagnostics produced by the compiler and an executable
output. This does not guarantee "equivalent output" when executed.

Even something so simple as:

#include <stdio.h>

int main(void)
{
printf("size of character literal '!' is %d bytes\n",
(int)sizeof('!'));
return 0;
}

Will compile successfully on any conforming C or C++ compiler. The
output will be different on most, but not all, implementations, even
if compiled alternately as C and C++ with an implementation that
supports both languages.
 
S

Sidney Cadot

Jack said:
The key is the phrase "successful compilation", which means no
required diagnostics produced by the compiler and an executable
output. This does not guarantee "equivalent output" when executed.

This is the first mention of C/C++ equivalence here. That was not the
issue as far as I can tell.
Even something so simple as:

#include <stdio.h>

int main(void)
{
printf("size of character literal '!' is %d bytes\n",
(int)sizeof('!'));
return 0;
}

Will compile successfully on any conforming C or C++ compiler. The
output will be different on most, but not all, implementations, even
if compiled alternately as C and C++ with an implementation that
supports both languages.

All true. I'm just saying that your example, apart from being a valid C
program, is also a valid C++ program. The fact that they do different
things is immaterial to the discussion.

Best regards,

Sidney
 
P

Paul Hsieh

Kai Jaensch said:
I am an newbie and i have to to solve this problem as fast as i can. But
at this time i don´t have a lot of success.
Can anybody help me (and understand my english :))?

I have a .txt-file in which the data is structured in that way:
Project-Nr. ID name lastname
33 9 Lars Lundel
33 12 Emil Korla
34 19 Lara Keuler
33 13 Thorsten Lammert

These data have to be read out row by row.

The C library has a totally worthless complement of string parsing
functions. While you would expect that you should be able to use
strtok(), this function is non-reentrant which is fatal for this (and
most other) cases. (Just doing a nested line parse, then entry parse
actually won't work). So there is no really simple way of doing this
with just C and/or the C library. It should not surprise you that you
have not received anything remotely resembling a satisfactory response
to your question. (Of course in a more modern language like Python,
the only challenge would be to see if you could do this in one line.)

In C++, the "boost" libraries may be able to solve your problem, but I
am not familliar with them (they are actually *aware* of other good
languages like Python -- so its likely that they are at least aware of
proper split functions). It seems that STL is inadequate to the task.

But a way that you *can* do this, in a practical and straight foward
way using Bstrlib (http://bstring.sf.net/):

#include <stdio.h>
#include "bstrlib.h"

struct cbsScanLine {
bstring src;
int row, col;
};

int columnCb (void * parm, int ofs, int len) {
struct cbsScanLine * sc = (struct cbsScanLine *) parm;
bstring s;
struct tagbstring t;
struct tagbstring ws = bsStatic ("\t ");

if (len == 0) return 0;
blk2tbstr (t, sc->src->data + ofs, len);
sc->col++;

s = bstrcpy (&t);

/* Obviously this would be the spot where you stuff this
entry into your 2D array */
printf ("[%2d,%2d] -> <%s>\n", sc->row, sc->col, s->data);
bdestroy (s);
return 0;
}

int lineCb (void * parm, int ofs, int len) {
struct cbsScanLine * sl = (struct cbsScanLine *) parm;
struct cbsScanLine sc;
struct tagbstring t;
struct tagbstring ws = bsStatic ("\t ");

/* Deal with MS's CR+LF standard */
if (sl->src->data[ofs] == '\n') {
ofs++;
len--;
}
blk2tbstr (t, sl->src->data + ofs, len);
sl->row++;
sc.src = &t;
sc.row = sl->row;
sc.col = 0;
return bsplitscb (&t, &ws, 0, columnCb, &sc);
}

int parseLines (const bstring src) {
struct cbsScanLine sl;
sl.src = src;
sl.row = sl.col = 0;
return bsplitcb (src, '\r', 0, lineCb, &sl);
}

int main (int argc, char * argv[]) {
FILE * fp;

if (argc < 2) {
printf ("%s [inputfile]\n", argv[0]);
return -__LINE__;
}

if (NULL != (fp = fopen (argv[1], "rb"))) {
bstring src = bread ((bNread) fread, fp);
int ret = parseLines (src);
fclose (fp);
bdestroy (src);
return ret;
}
return -__LINE__;
}
 
R

Richard Heathfield

[followups set to comp.lang.c]

Paul said:
The C library has a totally worthless complement of string parsing
functions.

Not so. It has a rather minimalist approach to string parsing, it's true -
but the functions it provides are far from worthless, and the skilful
programmer can easily use these as components with which to build a much
more functional library.
 
D

Daniel Haude

["Followup-To:" header set to comp.lang.c.]
On 15 Jan 2004 03:58:59 -0800,
in Msg. said:
The C library has a totally worthless complement of string parsing
functions.

As far as I'm aware of it only has one function that deserves the name
"parsing function", which is sscanf().

Anyway, it's simple to roll your own. For delimiter-separated text data I
always use this function:

char **dh_splitstring(char *line, int maxfields, int sep)
{
char *a, *e, *s;
int i;
char **arr;

if (NULL == (arr = malloc((maxfields+1) * sizeof *arr))) return NULL;

e = line;
for (i = 0; i < maxfields; i++) {
/* skip leading WS */
for (s = e; *s && isspace(*s) && *s != sep; s++) ;
if (!*s) break;
for (a = s; *a && *a != sep; a++) ;
e = *a == sep ? a+1 : a;
/* chop off trailing WS */
for (a--; isspace(*a) && a > s; a--) ;
if (i < maxfields-1) *++a = 0;
arr = s;
}
for ( ; i < maxfields+1; i++) {
arr = NULL;
}
return arr;
}


line: The string to be parsed
maxfields: max number of fields
sep: field separator char (i.e., '\t')
Returns: A newly-allocated, NULL-terminated array of pointers to strings
with maxfields+1 elements. All fields have leading and trailing whitespace
removed.

Warning: Modifies line. If this is not what you want, pass a copy.

The returned pointers point into different positions of 'line', so 'line'
must not be freed or modified as long as you want to use the result.

Multiple separator tokens are not lumped together, but result in empty
tokens ("\0"). This makes using tab-separated data files dangerous because
there may be different numbers of tabs between columns. I always use
semicolons.

--Daniel
 
D

Default User

Paul said:
The C library has a totally worthless complement of string parsing
functions.


Oh yes. It's completely impossible to create any application using the
string-parsing utilities in C.

Unless you are a competent programmer.

You know, there are *other* things besides strtok() available. It's
really not that hard to use strchr() and your own state machine for
parsing if strtok() doesn't fit your needs.

Don't get wrong, std::string has a lot of nice features, but to poo-poo
the C string capabilities portrays either a lack of experience, or lack
of skill.




Brian Rodenborn
 
P

Peter Nilsson

Sidney Cadot said:
How's that?

Assume a (correct) C++ compiler. Consider any text. Assume that this
text, when fed to the aforementioned C++ compiler, leads to "succesful
compilation". Why is it wrong to conclude that the text is C++ code?

Nothing, so long as you're willing to accept binary streams of random
noise as valid C++ code.

I don't know about C++, but the only C construct where a translation
must fail is the #error directive. [And Dan Pop has argued that this
is still compilable since, in such circumstances, it can be considered
'unsuccessful' translation.]
 
J

Jeremy Yallop

Peter said:
I don't know about C++, but the only C construct where a translation
must fail is the #error directive.

In C89 an #error directive causes the issuance of a diagnostic
message; it isn't required to cause translation failure. In fact, a
conforming implementation isn't even generally /allowed/ to stop
translation on encountering #error, although there are a couple of
loopholes that can be used to justify doing so. There is at least one
implementation where an #error directive doesn't cause translation to
fail.

In C99 the implementation is not allowed to ("successfully") translate
programs containing active #error directives.

Jeremy.
 
S

Sidney Cadot

Peter said:
Nothing, so long as you're willing to accept binary streams of random
noise as valid C++ code.

Hang on, I've lost you there... Here's a bunch of random characters:

!&^fgfctq9786h0%(*&%h2owyp[1238n

Are you saying that a correct C++ compiler may compile this succesfully?
Same question for a correct C compiler?
I don't know about C++, but the only C construct where a translation
must fail is the #error directive. [And Dan Pop has argued that this
is still compilable since, in such circumstances, it can be considered
'unsuccessful' translation.]

Ok, under the assumption that feeding

!&^fgfctq9786h0%(*&%h2owyp[1238n

....to a correct C compiler does not have to fail, what /does/ the
standard have to say on what can be expected of a compiler on such input?


Best regards,

Sidney
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top