end-of-line character problem while reading stream characters and wrinting into array

D

dbuser

Hi,
I need help on a problem, as described below. I am reading a file
"input.txt"which has data like this:
abc def gh izk lmnopq rst uvwxyz

I am using fstream object to read the file and writing into a dynamic
array. My problem is that the array shows extra z and probably because
of this further processing gives run time error in borland compiler.
Can you please tell me, if the problem is related to handling end-of
line , how do i do it.
here is the piece of code I am using:
char ch;
char * input;
input = new char[size]; // size is determined at runtime
memset(input, 0, sizeof(input));
ifstream infile("input.txt", ios::in);
if(!infile) cerr << "Error opening file" << endl;
while(!infile.eof()){
infile.get(ch);
input = ch;
i++;
}
cout << input << endl;
infile.close();


as you can see, the output shows extra 'z'
abc def gh izk lmnopq rst uvwxyzz

Thanks for any help!
regards!
dbuser
 
J

John Harrison

dbuser said:
Hi,
I need help on a problem, as described below. I am reading a file
"input.txt"which has data like this:
abc def gh izk lmnopq rst uvwxyz

I am using fstream object to read the file and writing into a dynamic
array. My problem is that the array shows extra z and probably because
of this further processing gives run time error in borland compiler.
Can you please tell me, if the problem is related to handling end-of
line , how do i do it.
here is the piece of code I am using:
char ch;
char * input;
input = new char[size]; // size is determined at runtime
memset(input, 0, sizeof(input));
ifstream infile("input.txt", ios::in);
if(!infile) cerr << "Error opening file" << endl;
while(!infile.eof()){
infile.get(ch);
input = ch;
i++;
}
cout << input << endl;
infile.close();


as you can see, the output shows extra 'z'
abc def gh izk lmnopq rst uvwxyzz

Thanks for any help!
regards!
dbuser


The problem is that your end of file handling is wrong.

infile.eof() is true is the *last* operation failed because of end of
file, it is not true because the *next* opeation will fail because of
end of file. So you are going round you loop one to many times.

It is simply unbelievable how many newbies manage to get this wrong. I
don't know where they are getting their information from. Did you read
this in a book, or did you just think it must be right?

Here is how you should write your loop

while(infile.get(ch)){
input = ch;
i++;
}

Now the extra z will disappear.

john
 
J

Jacques Labuschagne

dbuser said:
Hi,
I need help on a problem, as described below. I am reading a file
"input.txt"which has data like this:
abc def gh izk lmnopq rst uvwxyz

I am using fstream object to read the file and writing into a dynamic
array. My problem is that the array shows extra z and probably because
of this further processing gives run time error in borland compiler.
Can you please tell me, if the problem is related to handling end-of
line , how do i do it.
here is the piece of code I am using:
char ch;
char * input;
input = new char[size]; // size is determined at runtime
memset(input, 0, sizeof(input));
ifstream infile("input.txt", ios::in);
if(!infile) cerr << "Error opening file" << endl;
while(!infile.eof()){

This is your problem. The test for eof() is only meaningful after you
try to get() something. This loop should be written as

while (infile.get(ch)){
input = ch;
++i;
}

You may want to consider reading the file in bigger chunks. Reading it
one character at a time is slooow.

Jacques.
 
T

Thomas J. Gritzan

dbuser said:
char ch;
char * input;
input = new char[size]; // size is determined at runtime
memset(input, 0, sizeof(input));
^^^^^^^^^^^^^

This is a bad idea. The size of the character array input is pointing to
is "size" and not sizeof(input). sizeof(input) is equal to sizeof(char*).
ifstream infile("input.txt", ios::in);
if(!infile) cerr << "Error opening file" << endl;
while(!infile.eof()){
infile.get(ch);
input = ch;
i++;
}


I would do it here instead:

input = '\0';
cout << input << endl;
infile.close();



Thomas
 
D

dbuser

Hi John,
Thanks for such a quick response. the extra z disappeared , but it
added a junk in the array , I am printing (see the last character.
abc def gh izk lmnopq rst uvwxyz☻

somehow, the file pointer is reading endof line and fills garbage. what
am I missing here?
since I am using this array data to manipulate later, this causes run
time error.
Thanks again ,
dbuser
 
J

Jacques Labuschagne

dbuser said:
Hi John,
Thanks for such a quick response. the extra z disappeared , but it
added a junk in the array , I am printing (see the last character.
abc def gh izk lmnopq rst uvwxyz☻

somehow, the file pointer is reading endof line and fills garbage. what
am I missing here?
since I am using this array data to manipulate later, this causes run
time error.
Thanks again ,
dbuser

Thomas has answered this. You aren't NUL-terminating your string properly.

Jacques.
 
D

dbuser

Hi Thomas,
Thanks ! Null terminating the string resolved this garbage problem.I
have couple of more questions:
1) I need to find the no. of characters in the input file so that I can
determine the size of the dynamic array. right now, I am using C method
_lseek to find beginning and end value and calculating the size.
Can I do this using C++ methods seekg(ios::beg) and seekg(ios::end)
this does not return a long value , whats the efficient way of finding
size in C++?

2) I am calling a scramble function which fills another dynamic array
with scrambled values, at the end, I need to move user input key into
that array. like moving a null terminating string, I am trying to move
the key value but it is not working.. is this doable.
The other bad idea I have is to write entire array into a file and then
move that key value at end of file , but I am getting run time error
when i try to open the filestream object .
Please help !
Thnaks !
 
D

dbuser

Hi Thomas,
Great, the input = '\0' removed the last unwanted character in the
dynamic array. your suggestion greatly appreciated.
can I ask you another question here... after filling this array, I am
calling a swap function and a scramble function to manupulate the
string... I may not be efficient because I am making another dynamic
array and filling scrambled data.
After I am done, I need to insert a user entered key ( a single digit
number) at the end of the array.
c[j] = x; // x is integer
does not work.
I tried to open a file and write this array data into file so that I
can write end character but then ofstream object creation statement
--- ofstream outfile("name.txt", ios::ate);
gives me run time error. here is the code :
void scramble( char *w, int key)
{
int x = key;
int len = strlen(w);
len = (len + len/x);
char s[] = "@#$";
int n = strlen(s);
int i,j,k,m=0;
static char * c;
c = new char[len];
memset(c, 0, sizeof(c));

if (c == NULL) exit(1);
for (i=0,j=0,k=0; i<len; i++){
if(k<x) {
c[j++] = w;k++;
}
else {
if(m<n)
c[j++] = s[m++];
else {
c[j++] = s[0]; m = 1;}
c[j++]=w; k=1; }
}
c[j] = x;
cout << "c is " << c << endl;
//write scramble into a file
cout << "I am starting writefile" << endl;
ofstream outfile("name.txt", ios::ate);
cout << "I m after opening writefile" << endl;
if (!outfile) {
cerr << "file could not be opened " << endl;
exit(1);
} else cout << "file created successfully" << endl;
for (int i=0; i< strlen(c); i++) {
outfile<<c;
}

outfile.close();


Thanks a lot for help !
dbuser
 
T

Thomas J. Gritzan

dbuser said:
Hi Thomas,

Hi again,
After I am done, I need to insert a user entered key ( a single digit
number) at the end of the array.
c[j] = x; // x is integer
does not work.

Of course not. Characters are represented as ASCII code in memory (or
similar on other platforms).
If you want the characters '0', '1', ... write this:

c[j] = '0'+x; // assumes that 0 <= x <= 9
I tried to open a file and write this array data into file so that I
can write end character but then ofstream object creation statement
--- ofstream outfile("name.txt", ios::ate);
gives me run time error.

Try ios::ate|ios::eek:ut as second parameter. ios::ate does not imply ios::eek:ut.
here is the code :
void scramble( char *w, int key)
{
int x = key;
int len = strlen(w);
len = (len + len/x);
char s[] = "@#$";
int n = strlen(s);
int i,j,k,m=0;
static char * c;

Why static?

Here are the errors:
c = new char[len];
memset(c, 0, sizeof(c));

if (c == NULL) exit(1);

First, don't check c for NULL after using it. That really makes no
sense. Then, you don't have to check c for being null-pointer, since
operator new does not return NULL, it throws an exception instead.

You also need to reserve space for the null-terminator:

c = new char[len+1];

Then again, as I said in the other posting, the array c points to does
not have size sizeof(c). It's size is len.
Write this:

memset(c, 0, len); or better omit it, you don't need it.

Instead, terminate the string with '\0' when done, just as in the other
function.
for (i=0,j=0,k=0; i<len; i++){
if(k<x) {
c[j++] = w;k++;
}
else {
if(m<n)
c[j++] = s[m++];
else {
c[j++] = s[0]; m = 1;}
c[j++]=w; k=1; }
}


What are you doing here anyway? What do you scramble the string for?
c[j] = x;

See above.
cout << "c is " << c << endl;
//write scramble into a file
cout << "I am starting writefile" << endl;
ofstream outfile("name.txt", ios::ate);
cout << "I m after opening writefile" << endl;
if (!outfile) {
cerr << "file could not be opened " << endl;
exit(1);

Don't forget to free the memory c is pointing to bevor exiting.
} else cout << "file created successfully" << endl;
for (int i=0; i< strlen(c); i++) {
outfile<<c;
}


Why do you write the characters one at a time?
outfile.close();

Again, don't forget to delete c!

Thomas
 

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

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top