Connecting Tech Pros Worldwide Forums | Help | Site Map

program error

Baloff
Guest
 
Posts: n/a
#1: Aug 28 '05
Hello

I wrote a code which is suppose to read a file which contains lines of
double and prints it out.

thanks for helping

double.txt***************************************
1.01
2.0301
3.0604
4.10101
5.15202

in a stack.h I have
//stack.h****************************************
#ifndef STACK_H
#define STACK_H

struct Stack
{
struct Link
{
void* data;
Link* next;
void initialize (void* dat, Link* nxt);
}
* head;
void initialize ();
void push (void* dat);
void* peek ();
void* pop ();
void cleanup ();
};
#endif

in my main.cpp
string line;
while(getline(in, line)){
textlines.push(reinterpret_cast<void*>(&line));
}
works ok but the following is not printing out the lines

double* s;
while(( s = static_cast<double*>(textlines.pop() )) != 0) {
cout << *s << endl;
delete s;
}
[color=blue]
> LocalWords: txt ifndef struct endif cpp ok[/color]



Kai-Uwe Bux
Guest
 
Posts: n/a
#2: Aug 28 '05

re: program error


Baloff wrote:
[color=blue]
> Hello
>
> I wrote a code which is suppose to read a file which contains lines of
> double and prints it out.
>[/color]
[snip][color=blue]
> in a stack.h I have
> //stack.h****************************************
> #ifndef STACK_H
> #define STACK_H
>
> struct Stack
> {
> struct Link
> {
> void* data;
> Link* next;
> void initialize (void* dat, Link* nxt);
> }
> * head;
> void initialize ();
> void push (void* dat);
> void* peek ();
> void* pop ();
> void cleanup ();
> };
> #endif[/color]

Hm, you are using a stack, so maybe you want to revert the order in
printing?

All these void pointers are bad. You should use std::stack.
[color=blue]
>
> in my main.cpp
> string line;
> while(getline(in, line)){
> textlines.push(reinterpret_cast<void*>(&line));
> }
> works ok ...[/color]

Really? Now, I am pretty sure that this stores some *void items in your
stack, all of which will happily point to the address of the string
variable line which did not change!

[color=blue]
> ... but the following is not printing out the lines
>
> double* s;
> while(( s = static_cast<double*>(textlines.pop() )) != 0) {[/color]

which kind of magic is this cast supposed to perform? textlines.pop() will
return a *void pointing to &line. Now you are telling the compiler that it
should not expect a string there but treat the bytes there as the
representation of a double. [You might want to have a look into
boost::lexical_cast!]
[color=blue]
> cout << *s << endl;
> delete s;[/color]

Here, you are freeing memory that you nerver allocated!
[color=blue]
> }
>[/color]

Use the standard library:

#include <stack>
#include <iostream>
#include <string>
#include <fstream>

int main ( void ) {
std::stack< double > double_stack;
{
// read
std::ifstream in_file ( "numbers.txt" );
double value;
while ( in_file >> value ) {
double_stack.push( value );
}
}
{
// print
while ( ! double_stack.empty() ) {
std::cout << double_stack.top() << '\n';
double_stack.pop();
}
}
}


Best

Kai-Uwe Bux
Rolf Magnus
Guest
 
Posts: n/a
#3: Aug 28 '05

re: program error


Baloff wrote:
[color=blue]
> Hello
>
> I wrote a code which is suppose to read a file which contains lines of
> double and prints it out.
>
> thanks for helping
>
> double.txt***************************************
> 1.01
> 2.0301
> 3.0604
> 4.10101
> 5.15202
>
> in a stack.h I have
> //stack.h****************************************
> #ifndef STACK_H
> #define STACK_H
>
> struct Stack
> {
> struct Link
> {
> void* data;
> Link* next;
> void initialize (void* dat, Link* nxt);
> }
> * head;
> void initialize ();
> void push (void* dat);
> void* peek ();
> void* pop ();
> void cleanup ();
> };
> #endif
>
> in my main.cpp
> string line;[/color]

You define one single string here.
[color=blue]
> while(getline(in, line)){[/color]

Now you go through the file, overwriting the string contents with the
current line each time.
[color=blue]
> textlines.push(reinterpret_cast<void*>(&line));[/color]

Then you put a pointer to the string object into your stack. Note that it's
always the same string object and thus always the same pointer value. So at
the end, you have a stack of pointers that point all to the same string,
which contains the last line of your file, since that is what was last
written to it.
[color=blue]
> }
> works ok but the following is not printing out the lines
>
> double* s;
> while(( s = static_cast<double*>(textlines.pop() )) != 0) {[/color]

You cannot just take a pointer to a string and treat it as if it were a
pointer to double. This will not parse the string. It just interprets the
bits that the string is composed of as double value. The result is of
course garbage.
[color=blue]
> cout << *s << endl;
> delete s;
> }
>[color=green]
>> LocalWords: txt ifndef struct endif cpp ok[/color][/color]

Wha?

Baloff
Guest
 
Posts: n/a
#4: Aug 28 '05

re: program error


I think I need to show the whole code, it is an exercise form Thinking
In C++ by Bruce Eckel. page 255 (8)
I need to make the Stack example in the book holds doubles, fill it
with 25 double values and print them out.

thanks

//: C04:Stack.h******************************
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Nested struct in linked list
#ifndef STACK_H
#define STACK_H

struct Stack {
struct Link {
void* data;
Link* next;
void initialize(void* dat, Link* nxt);
}* head;
void initialize();
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
#endif // STACK_H ///:~

//: C04:Stack.cpp {O}*************************
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Linked list with nesting
#include "Stack.h"
#include "../require.h"
using namespace std;

void
Stack::Link::initialize(void* dat, Link* nxt) {
data = dat;
next = nxt;
}

void Stack::initialize() { head = 0; }

void Stack::push(void* dat) {
Link* newLink = new Link;
newLink->initialize(dat, head);
head = newLink;
}

void* Stack::peek() {
require(head != 0, "Stack empty");
return head->data;
}

void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}

void Stack::cleanup() {
require(head == 0, "Stack not empty");
} ///:~

//: C04:StackTest.cpp*************************
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
//{L} Stack
//{T} StackTest.cpp
// Test of nested linked list
#include "Stack.h"
#include "../require.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char* argv[]) {
requireArgs(argc, 1); // File name is argument
ifstream in(argv[1]);
assure(in, argv[1]);
Stack textlines;
textlines.initialize();
string line;
// Read file and store lines in the Stack:
while(getline(in, line))
textlines.push(new string(line));
// Pop the lines from the Stack and print them:
string* s;
while((s = (string*)textlines.pop()) != 0) {
cout << *s << endl;
delete s;
}
textlines.cleanup();
} ///:~

//: :require.h******************************
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Test for error conditions in programs
// Local "using namespace std" for old compilers
#ifndef REQUIRE_H
#define REQUIRE_H
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <string>

inline void require(bool requirement,
const std::string& msg = "Requirement failed"){
using namespace std;
if (!requirement) {
fputs(msg.c_str(), stderr);
fputs("\n", stderr);
exit(1);
}
}

inline void requireArgs(int argc, int args,
const std::string& msg =
"Must use %d arguments") {
using namespace std;
if (argc != args + 1) {
fprintf(stderr, msg.c_str(), args);
fputs("\n", stderr);
exit(1);
}
}

inline void requireMinArgs(int argc, int minArgs,
const std::string& msg =
"Must use at least %d arguments") {
using namespace std;
if(argc < minArgs + 1) {
fprintf(stderr, msg.c_str(), minArgs);
fputs("\n", stderr);
exit(1);
}
}

inline void assure(std::ifstream& in,
const std::string& filename = "") {
using namespace std;
if(!in) {
fprintf(stderr, "Could not open file %s\n",
filename.c_str());
exit(1);
}
}

inline void assure(std::ofstream& out,
const std::string& filename = "") {
using namespace std;
if(!out) {
fprintf(stderr, "Could not open file %s\n",
filename.c_str());
exit(1);
}
}
#endif // REQUIRE_H ///:~
[color=blue]
> LocalWords: Eckel txt struct ifndef dat endif namespace std nxt newLink cpp
> LocalWords: oldHead StackTest fstream iostream int argc argv requireArgs
> LocalWords: ifstream textlines getline cstdio cstdlib inline bool const msg
> LocalWords: args requireMinArgs minArgs[/color]
Karl Heinz Buchegger
Guest
 
Posts: n/a
#5: Aug 29 '05

re: program error


Baloff wrote:[color=blue]
>
> I think I need to show the whole code, it is an exercise form Thinking
> In C++ by Bruce Eckel. page 255 (8)
> I need to make the Stack example in the book holds doubles, fill it
> with 25 double values and print them out.[/color]

So then why don't you do exactly that?
[color=blue]
> int main(int argc, char* argv[]) {
> requireArgs(argc, 1); // File name is argument
> ifstream in(argv[1]);
> assure(in, argv[1]);
> Stack textlines;
> textlines.initialize();
> string line;
> // Read file and store lines in the Stack:
> while(getline(in, line))
> textlines.push(new string(line));[/color]

You are not filling the stack with 'doubles'. You are
filling it with std::string's.

Either you *read* the file not with getline into a std::string
but eg. into a double or you *convert* the string (which
holds the textual representation of that number) into
an actual number.
[color=blue]
> // Pop the lines from the Stack and print them:
> string* s;
> while((s = (string*)textlines.pop()) != 0) {[/color]

This will be wrong in any case. The stack holds pointers to
double, not to std::string!


--
Karl Heinz Buchegger
kbuchegg@gascad.at
Baloff
Guest
 
Posts: n/a
#6: Aug 29 '05

re: program error


Karl Heinz Buchegger <kbuchegg@gascad.at> writes:
[color=blue]
> Baloff wrote:
>[color=green]
> >
> > I think I need to show the whole code, it is an exercise form Thinking
> > In C++ by Bruce Eckel. page 255 (8)
> > I need to make the Stack example in the book holds doubles, fill it
> > with 25 double values and print them out.[/color]
>
> So then why don't you do exactly that?[/color]
to summarize the problem and reduce your time of reading a long post
at first.
[color=blue]
>[color=green]
> > int main(int argc, char* argv[]) {
> > requireArgs(argc, 1); // File name is argument
> > ifstream in(argv[1]);
> > assure(in, argv[1]);
> > Stack textlines;
> > textlines.initialize();
> > string line;
> > // Read file and store lines in the Stack:
> > while(getline(in, line))
> > textlines.push(new string(line));[/color]
>
> You are not filling the stack with 'doubles'. You are
> filling it with std::string's.
>
> Either you *read* the file not with getline into a std::string
> but eg. into a double[/color]

how else would you read the file 'each line into a double'?
[color=blue]
> or you *convert* the string (which
> holds the textual representation of that number) into
> an actual number.
>[/color]

like this?
string line;
while(getline(in, line)){
textlines.push(new double( atof(line.c_str()) ));
}

[color=blue][color=green]
> > // Pop the lines from the Stack and print them:
> > string* s;
> > while((s = (string*)textlines.pop()) != 0) {[/color]
>
> This will be wrong in any case. The stack holds pointers to
> double, not to std::string!
>
>
> --
> Karl Heinz Buchegger
> kbuchegg@gascad.at[/color]
Karl Heinz Buchegger
Guest
 
Posts: n/a
#7: Aug 30 '05

re: program error


Baloff wrote:[color=blue]
>[color=green]
> > Either you *read* the file not with getline into a std::string
> > but eg. into a double[/color]
>
> how else would you read the file 'each line into a double'?[/color]

come on.

double value;

while( in >> value ) {
..
}

[color=blue]
>[color=green]
> > or you *convert* the string (which
> > holds the textual representation of that number) into
> > an actual number.
> >[/color]
>
> like this?
> string line;
> while(getline(in, line)){
> textlines.push(new double( atof(line.c_str()) ));
> }
>[/color]

Yep.
But atof() isn't a very good function. There is no way to check
if the string realy represents a valid number. Other methods
would be to eg. use string stream.
This topic has been beaten to death in this newsgroup. Search
the archives at google.

--
Karl Heinz Buchegger
kbuchegg@gascad.at
Closed Thread