473,404 Members | 2,137 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,404 software developers and data experts.

Reading Lines with Fgets(?) and a bit of C++ {Novice Programmer}

Hello.
I have a file (for a school assignment) with the following format and
delimiter format. Each record in the file has the following format:
123423454567987,29873,James,Ha*rry,St. Louis,416-555-5555;
"accountNumber,balance,lastNam*e,city,phoneNumber; " Each record is
guranteed to be no longer than 350 characters. "balance" is no longer
than 20 characters, "accountNumber" is exactly 15 characters and the
total number of characters in "lastName,firstName,city,phone*Number;"
is
no longer than 315 characters. Copy the fields in this record to the
appropriate data member of the first empty Account in the array
savings, using all the rules for copying (initializing).
Contents of a3.dat
123423454567987,29873,James,Ha*rry,St.
Louis,416-555-5555;22342345456*7987,198745,Jones,Beth,Toronto*,4 16-555-5556;323423454567987,*2349,Ng,Wei,Montreal,416-555-5*557;423423454567987,9234617,Wo*o,Charles,Winnipe g,416-555-555*8;523423454567987,2534,DeJesus*,Pancho,Edmonto n,416-555-5559;*623423454567987,543876,Smith,B*ob,Charlottet own,416-555-5544;*723423454567987,1234,Kasim,Vla*dislov,Halifa x,416-555-5566;82*3423454567987,98765,Yamaha,Dav*id,Vancouve r,416-555-5577;9234*23454567987,26486,Lee,Jim,Calg*ary,416-555-5588;1134234545679*87,83456,Baker,Susan,St.

Louis-de-ha-ha,416-555-5599;13*3423454567987,29873,James,Harr*y,St.
Louis,416-555-5555;
Since each "record" is not a line and is shown as is (above) in the
file, how might I go and read each "record", extract the information
and send it to the correct data member of the first empty object in the
array?

So far I have my function like this

void Bank::workFP(FILE* fp)
{
if(fp != NULL){

}
else printf("Unable to open file.\n");
}
Thanks in advance. Appreciate any help whatsoever.

Jul 23 '05 #1
12 2225
It's not "nice" because the data file is intentionally jumbled. One
way to do this is to read exactly 350 characters, and parse it
according to the rules you've outlined for the data elements. Then,
save-off the remainder. Loop again, and read another 350, prepend the
remainder and continue. Keep in mind that you will not have nice NULL
terminated strings, and also check that you read 350 characters.

Jul 23 '05 #2
AMT2K5 wrote:


Since each "record" is not a line and is shown as is (above) in the
file, how might I go and read each "record"


From your description: Each "record" ends with a ';' character.
So read character by character until you encounter a ';'. Save those
characters in a buffer (probably a std::string). Then you have all
characters for one record and can proceed to break it into
individual pieces.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #3
since you can't guarantee that each record occupies it's own line, then
you will have to read the whole file into memory. if you can gaurantee
that the file is not of huge size, then you can just read the while
file into a char* buffer, or a std::string object:

if (fp != NULL)
{
char *chunk = new char[256];
std::string sBuffer;
while (!feof(fp))
{
fread(chunk, sizeof(char), 256, fp); // you might even be able to
read right into the string struct, but i'm not sure
string = string + sBuffer;
}
delete[] chunk;
chunk = null;
DoParsingAndOtherStuff(string);
}

once you have the whole file in a buffer, it's easy to use string
manipulation to parse it, first by ';' to get the records, then by ','
to get the fields in each record.

if you can't gaurantee that the file is reasonable in size, then it
gets trickier. you have to analyze each chunk for records first, and
then do an fseek to get to the last place in the file you left off:

if (fp != NULL)
{
char *chunk = new char[256];
int nextstartposition = 0;
while (!feof(fp))
{
fseek(fp, nextstartposition, 0);
fread(chunk, sizeof(char), 256, fp);
nextstartposition = nextstartposition +
DoParsingAndOtherStuff(chunk)
}
delete[] chunk;
chunk = null;
}

in this case DoParsingAndOtherStuff does the same thing, but it has to
return the position that the last ';' was found on, because everything
after that was only a partial record. then the file can seek to that
new starting location, and read another chunk. it's only a little
trickier than reading the whole thing into memory, really.

if you need help with what DoParsingAndOtherStuff would look like, let
me know.

hope this helps,

jason

Jul 23 '05 #4
How can I program my loop to read the next record after the first ';'?
Karl Heinz Buchegger wrote:
AMT2K5 wrote:


Since each "record" is not a line and is shown as is (above) in the
file, how might I go and read each "record"


From your description: Each "record" ends with a ';' character.
So read character by character until you encounter a ';'. Save those
characters in a buffer (probably a std::string). Then you have all
characters for one record and can proceed to break it into
individual pieces.

--
Karl Heinz Buchegger
kb******@gascad.at


Jul 23 '05 #5
AMT2K5 wrote:

How can I program my loop to read the next record after the first ';'?

Karl Heinz Buchegger wrote:
AMT2K5 wrote:


Since each "record" is not a line and is shown as is (above) in the
file, how might I go and read each "record"


From your description: Each "record" ends with a ';' character.
So read character by character until you encounter a ';'. Save those
characters in a buffer (probably a std::string). Then you have all
characters for one record and can proceed to break it into
individual pieces.

--
Karl Heinz Buchegger
kb******@gascad.at


As said: you can read character by character. eg.

std::string buffer;
char c;

while( fin >> c ) {
if( c == ';' ) {
// buffer contains a record, process it
Process( buffer );
buffer = "";
}
else
buffer += c;
}

Not very fast, but it does its job.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #6
What is that string = string come from? What is string?

I am trying to interpret your code.

jason wrote:
since you can't guarantee that each record occupies it's own line, then
you will have to read the whole file into memory. if you can gaurantee
that the file is not of huge size, then you can just read the while
file into a char* buffer, or a std::string object:

if (fp != NULL)
{
char *chunk = new char[256];
std::string sBuffer;
while (!feof(fp))
{
fread(chunk, sizeof(char), 256, fp); // you might even be able to
read right into the string struct, but i'm not sure
string = string + sBuffer;
}
delete[] chunk;
chunk = null;
DoParsingAndOtherStuff(string);
}

once you have the whole file in a buffer, it's easy to use string
manipulation to parse it, first by ';' to get the records, then by ','
to get the fields in each record.

if you can't gaurantee that the file is reasonable in size, then it
gets trickier. you have to analyze each chunk for records first, and
then do an fseek to get to the last place in the file you left off:

if (fp != NULL)
{
char *chunk = new char[256];
int nextstartposition = 0;
while (!feof(fp))
{
fseek(fp, nextstartposition, 0);
fread(chunk, sizeof(char), 256, fp);
nextstartposition = nextstartposition +
DoParsingAndOtherStuff(chunk)
}
delete[] chunk;
chunk = null;
}

in this case DoParsingAndOtherStuff does the same thing, but it has to
return the position that the last ';' was found on, because everything
after that was only a partial record. then the file can seek to that
new starting location, and read another chunk. it's only a little
trickier than reading the whole thing into memory, really.

if you need help with what DoParsingAndOtherStuff would look like, let
me know.

hope this helps,

jason


Jul 23 '05 #7
AMT2K5 wrote:
What is that string = string come from? What is string?

[snip]

You will need to get and read one of the fine introductory
textbooks on C++. The stuff you are talking about is fairly
elementary. For example, Koenig and Moo, _Accelerated C++_
is well thought of. Also, your instructor should have said
what text you should be reading, and you should be reading it.
Socks

Jul 23 '05 #8
it's from the std library. if you can't use such things in your
assignment, then char arrays work well too, though then it will be much
easier to just process each chunk that you pull out, so that you're not
constantly resizing the char array for the full file buffer.

either Karl or my samples should work. his processes character by
character, mine in larger chunks. both should be fine for an assignment.

Jul 23 '05 #9

"jason" <ia****@yahoo.com> wrote in message
{
char *chunk = new char[256];
std::string sBuffer;
while (!feof(fp))
{
fread(chunk, sizeof(char), 256, fp); // you might even be able to
read right into the string struct, but i'm not sure
string = string + sBuffer;
}
delete[] chunk;
chunk = null;
DoParsingAndOtherStuff(string);
}


Why would you allocate and delete a buffer like that? Why not just declare
a local array? Just because fread takes a pointer does not mean you have to
_declare_ a pointer. All that function wants is the address of the first
element, which you can get with either just "chunk" or "&chunk[0]". (If you
can avoid using new and delete, it's generally better to do so, both because
it is faster and because it's less error-prone.)

-Howard

Jul 23 '05 #10
I just want to keep this as simple as possible. For parsing and working
with the fields is it suggessted that I use strtok?

AMT2K5 wrote:
Hello.
I have a file (for a school assignment) with the following format and
delimiter format. Each record in the file has the following format:
123423454567987,29873,James,Ha*rry,St. Louis,416-555-5555;
"accountNumber,balance,lastNam*e,city,phoneNumber; " Each record is
guranteed to be no longer than 350 characters. "balance" is no longer
than 20 characters, "accountNumber" is exactly 15 characters and the
total number of characters in "lastName,firstName,city,phone*Number;"
is
no longer than 315 characters. Copy the fields in this record to the
appropriate data member of the first empty Account in the array
savings, using all the rules for copying (initializing).
Contents of a3.dat
123423454567987,29873,James,Ha*rry,St.
Louis,416-555-5555;22342345456*7987,198745,Jones,Beth,Toronto*,4 16-555-5556;323423454567987,*2349,Ng,Wei,Montreal,416-555-5*557;423423454567987,9234617,Wo*o,Charles,Winnipe g,416-555-555*8;523423454567987,2534,DeJesus*,Pancho,Edmonto n,416-555-5559;*623423454567987,543876,Smith,B*ob,Charlottet own,416-555-5544;*723423454567987,1234,Kasim,Vla*dislov,Halifa x,416-555-5566;82*3423454567987,98765,Yamaha,Dav*id,Vancouve r,416-555-5577;9234*23454567987,26486,Lee,Jim,Calg*ary,416-555-5588;1134234545679*87,83456,Baker,Susan,St.

Louis-de-ha-ha,416-555-5599;13*3423454567987,29873,James,Harr*y,St.
Louis,416-555-5555;
Since each "record" is not a line and is shown as is (above) in the
file, how might I go and read each "record", extract the information
and send it to the correct data member of the first empty object in the
array?

So far I have my function like this

void Bank::workFP(FILE* fp)
{
if(fp != NULL){

}
else printf("Unable to open file.\n");
}


Thanks in advance. Appreciate any help whatsoever.


Jul 23 '05 #11
jason wrote:
[redacted]
if (fp != NULL)
{
char *chunk = new char[256];
std::string sBuffer;
while (!feof(fp))
{
fread(chunk, sizeof(char), 256, fp); // you might even be able to
read right into the string struct, but i'm not sure
string = string + sBuffer;
}
delete[] chunk;
chunk = null;
DoParsingAndOtherStuff(string);
}


in addition to Howard's comment on allocating "chunk", you also have the
usage of feof incorrect. feof doesn't kick in until you try to read and
actually have alreay hit EOF. It's not predictive like Pascal.

while (fread(chunk, sizeof(char), 256, fp) > 0)
{
// ...
}

Also, sizeof(char) is redundant since by definition it's 1, but it's
probably better to use it since you may in the future want to go to wchar_t.

Perhaps

while (fread(chunk,sizeof(chunk[0]), 256, fp) > 0)
{
// ...
}

which then becomes independent of the size of your character.
Jul 23 '05 #12
Thanks for the help guys. I asked my prof for extra help today and he
suggested that I use fscanf.

Now I am using it but I am having trouble with my format string. I can
display the first fields fine, but the (%315) field I can not. I get a
single garbage character on my screen if I display it.

char accountTemp[16];
int balanceTemp = 0;
char stringTemp[316];

fscanf(fp, "%15[^,],%20d[^,],%315[^;]", accountTemp, &balanceTemp,
stringTemp);

red floyd wrote:
jason wrote:
[redacted]
if (fp != NULL)
{
char *chunk = new char[256];
std::string sBuffer;
while (!feof(fp))
{
fread(chunk, sizeof(char), 256, fp); // you might even be able to
read right into the string struct, but i'm not sure
string = string + sBuffer;
}
delete[] chunk;
chunk = null;
DoParsingAndOtherStuff(string);
}


in addition to Howard's comment on allocating "chunk", you also have the
usage of feof incorrect. feof doesn't kick in until you try to read and
actually have alreay hit EOF. It's not predictive like Pascal.

while (fread(chunk, sizeof(char), 256, fp) > 0)
{
// ...
}

Also, sizeof(char) is redundant since by definition it's 1, but it's
probably better to use it since you may in the future want to go to wchar_t.

Perhaps

while (fread(chunk,sizeof(chunk[0]), 256, fp) > 0)
{
// ...
}

which then becomes independent of the size of your character.


Jul 23 '05 #13

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

Similar topics

7
by: DJP | last post by:
Hi, I need to read a file programmatically until end of file. My logic is as follows: while(!feof(Fp)) { fgets(readLine,10000,Fp);
1
by: Blankdraw | last post by:
I thought I cut out for myself a "simple" 1-module ANSI C programming task. I will in fact require extensive use of step-thru debugging. My old MS Visual C Developer Studio 4.2 should do this,...
7
by: Mansoor | last post by:
Hi, I recently (1 week) started to learn C language. I have been reading a book about C and I've been using Turbo C++ in DOS. After I learnt the basic concepts I decided to write a demo program...
6
by: AMT2K5 | last post by:
Hello. I have a file (for a school assignment) with the following format and delimiter format. Each record in the file has the following format: 123423454567987,29873,James,Harry,St....
40
by: googler | last post by:
I'm trying to read from an input text file and print it out. I can do this by reading each character, but I want to implement it in a more efficient way. So I thought my program should read one...
4
by: trond | last post by:
Hello all, Before I start I'd like to point out that I am a complete novice when it comes to asp.net - My background is in network and operating systems, and although I have been doing a bit of...
10
by: broeisi | last post by:
What advantages does sscanf offer over scanf? I had the following code: #include <stdio.h> #include <string.h> int main(void) { int start, finish, values;
9
by: Justme | last post by:
Novice programmer needs help with using fgets to read and ignore the first two lines of a file. I've gone thru the previous posting regarding fgets, but none of them seems to help my situation. I...
21
by: Stephen.Schoenberger | last post by:
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.