Flummoxed - Please Help!

M

Mike Copeland

I have the following (rather simple, I think) code which compiles but
executes in a bizarre way: the code in the subprogram is skipped when
called. 8<{{
Here's the code and the call to it I use:

string spellNumber(double value)
{
bool showThousands = false;
bool allZeros = true;
int ii, dPos, nn;
char wc;
string digits, temp;
ostringstream ossw;
static string builder;
ossw.str("");
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length();
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
// more code to be added here
return builder;
}
....
spellNumber(123.45); // call the function

I have, of course the normal stdafx.h header and "use namespace
std;", and this is code from a small test program I use to debug new
functions and such. Many other programs and many thousands of lines of
code work fine, but this code is weird...and I can't see what's wrong
with it!
Please advise... TIA
 
V

Victor Bazarov

I have the following (rather simple, I think) code which compiles but
executes in a bizarre way: the code in the subprogram is skipped when
called. 8<{{
Here's the code and the call to it I use:

string spellNumber(double value)
{
bool showThousands = false;
bool allZeros = true;
int ii, dPos, nn;
char wc;
string digits, temp;
ostringstream ossw;
static string builder;
ossw.str("");
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length();
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
// more code to be added here
return builder;
}
...
spellNumber(123.45); // call the function

I have, of course the normal stdafx.h header and "use namespace
std;", and this is code from a small test program I use to debug new
functions and such. Many other programs and many thousands of lines of
code work fine, but this code is weird...and I can't see what's wrong
with it!
Please advise... TIA

The logic error is on the line 42 of your original program, at least
according to my crystal ball, which is the best source of information I
have at this point, since you've chosen not to post the entire program.

http://www.parashift.com/c++-faq/posting-code.html

V
 
M

Mike Copeland

The logic error is on the line 42 of your original program, at least
according to my crystal ball, which is the best source of information I
have at this point, since you've chosen not to post the entire program.

http://www.parashift.com/c++-faq/posting-code.html

Fair enough; I was sloppy. Here's the entire program code:
// CPP10 Test Bed Program MRCopeland 02/18/2014
#include "stdafx.h"
string spellNumber(double value)
{
int ii, dPos, nn;
char wc;
string digits;
ostringstream ossw;
static string builder;
ossw.str(""); // Convert integer portion of value to string
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length(); // Traverse characters in reverse order
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
return builder;
}
int main(int argc, char *argv[])
{
string str = spellNumber(123.45);
return EXIT_SUCCESS;
} // main

During execution, the following occurs during the IDE trace:
1. The subprogram is entered and immediately jumps to the "return
builder" statement. (Why?)
2. Then, the function is reentered and code steps are taken - until the
"if" statement executes. The logic works as expected with the data
presented ("digits" is runcated to "123"), whereupon the function exits
(!).
3. The statements beyond the "if" are skipped for no apparent reason.
Any thoughts?
 
V

Victor Bazarov

The logic error is on the line 42 of your original program, at least
according to my crystal ball, which is the best source of information I
have at this point, since you've chosen not to post the entire program.

http://www.parashift.com/c++-faq/posting-code.html

Fair enough; I was sloppy. Here's the entire program code:
// CPP10 Test Bed Program MRCopeland 02/18/2014
#include "stdafx.h"
string spellNumber(double value)
{
int ii, dPos, nn;
char wc;
string digits;
ostringstream ossw;
static string builder;
ossw.str(""); // Convert integer portion of value to string
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length(); // Traverse characters in reverse order
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
return builder;
}
int main(int argc, char *argv[])
{
string str = spellNumber(123.45);
return EXIT_SUCCESS;
} // main

During execution, the following occurs during the IDE trace:
1. The subprogram is entered and immediately jumps to the "return
builder" statement. (Why?)
2. Then, the function is reentered and code steps are taken - until the
"if" statement executes. The logic works as expected with the data
presented ("digits" is runcated to "123"), whereupon the function exits
(!).
3. The statements beyond the "if" are skipped for no apparent reason.
Any thoughts?

I took your code and made only one change:

//#include "stdafx.h"
#include <string>
#include <sstream>
using std::string;
using std::eek:stringstream;

(since I have no idea what was in your 'stdafx.h' header). The program
compiled and ran fine (under the debugger). Stepping through it showed
that it followed all statements and returned an empty string (since no
change is made to 'builder' object in the 'spellNumber' function).

It sounds that you're trying to debug an optimized version of your
program (a "release" version). Perhaps you should disable optimizations
in order to step through it. The optimizer is often not the best tool
for verifying the logic of your program because it can determine and
throw away the code that has no effect. For instance, all the code that
follows the 'if' statement has no side effect (no change is made to any
memory location that would be noticed by the caller of the function),
methinks.

V
 
M

Mike Copeland

During execution, the following occurs during the IDE trace:
It gets weirder and weirder...
First, I'm not producing (or testing) a Release version, and I have
no non-normal optimizations set. I'm running "vanilla" VS2010 Express,
afaics.
Second, there are other things going that I hadn't mentioned:
1. As I debug, some of the variables in the function don't show up, nor
can I see their values during execution by holding my mouse over them
while the code is being stepped through. (Highly unusual!.) The
variables that don't show are all the scalars (ints and chars), while
the non-scalars do show (and change as code executes).
2. I have tried moving the position of the scalar variables within the
routine, but no change there.
3. I moved the scalars outside of the routine (making them global
<gasp!>), and they show and change, as execution proceeds - as they
should.
4. Also, once these scalars are moved and debug normally, the code runs
through the logic provided (!). (I know that nothing really changes in
terms of the return string, but there's more logic to be added to do
some of that - I'm just working out the logic to handle the data and
expand it as needed.)
Thus, it appears that the problem of code that isn't executed within
the routine is some effect of the scalar data declared and used in the
code (totally odd, in my experience...). I'm at a complete loss to
understand this... 8<{{
Here's my latest code (which as I said is working as I step through
the debugger). <sigh>
#include <string>
#include <sstream>
using std::string;
using std::eek:stringstream;
int ii, dPos, nn;
char wc;
int ndigit;
int column;
string spellNumber(double value)
{
string digitStr;
ostringstream ossw;
static string builder;
ossw.str(""); // Convert integer portion of value to string
ossw << value, digitStr = ossw.str();
dPos = digitStr.find(".");
if(dPos != string::npos)
digitStr.erase(dPos);
nn = digitStr.length(); // Traverse characters in reverse order
wc = digitStr.back();
for(ii = digitStr.length()-1; ii >= 0; ii--)
{
ndigit = (int)(digitStr.at(ii)-'0');
column = (digitStr.length()-(ii+1));
} // for
// more logic to be added here...
return builder;
}

int main(int argc, char *argv[])
{
string str = spellNumber(123.45);
return EXIT_SUCCESS;
} // main
 
Ö

Öö Tiib

First, I'm not producing (or testing) a Release version, and I have
no non-normal optimizations set. I'm running "vanilla" VS2010 Express,
afaics.

What you describe confirm what others said. Cut that "no non-normal" crap.
Remove every last of "normal" optimizations if you want to step thru and
see things. The compiler writers of Microsoft are far wiser than debugger
writers of Microsoft that are far wiser than IDE writers of Microsoft.
So if you want to see things of your program in IDE you *must* make
the compiler as dumb as you only can.
 
G

Geoff

The logic error is on the line 42 of your original program, at least
according to my crystal ball, which is the best source of information I
have at this point, since you've chosen not to post the entire program.

http://www.parashift.com/c++-faq/posting-code.html

Fair enough; I was sloppy. Here's the entire program code:
// CPP10 Test Bed Program MRCopeland 02/18/2014
#include "stdafx.h"
string spellNumber(double value)
{
int ii, dPos, nn;
char wc;
string digits;
ostringstream ossw;
static string builder;
ossw.str(""); // Convert integer portion of value to string
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length(); // Traverse characters in reverse order
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
return builder;
}
int main(int argc, char *argv[])
{
string str = spellNumber(123.45);
return EXIT_SUCCESS;
} // main

During execution, the following occurs during the IDE trace:
1. The subprogram is entered and immediately jumps to the "return
builder" statement. (Why?)
2. Then, the function is reentered and code steps are taken - until the
"if" statement executes. The logic works as expected with the data
presented ("digits" is runcated to "123"), whereupon the function exits
(!).
3. The statements beyond the "if" are skipped for no apparent reason.
Any thoughts?

The code as posted (and after making changes to make it compile due to
missing definitions) copies nothing into builder, the returned string
is empty.
 
G

Geoff

It gets weirder and weirder...
First, I'm not producing (or testing) a Release version, and I have
no non-normal optimizations set. I'm running "vanilla" VS2010 Express,
afaics.
Second, there are other things going that I hadn't mentioned:
1. As I debug, some of the variables in the function don't show up, nor
can I see their values during execution by holding my mouse over them
while the code is being stepped through. (Highly unusual!.) The
variables that don't show are all the scalars (ints and chars), while
the non-scalars do show (and change as code executes).

Are you looking at the Autos window or the Locals window? This
behavior is normal for Autos. The variables disappear as they go out
of scope.
2. I have tried moving the position of the scalar variables within the
routine, but no change there.
3. I moved the scalars outside of the routine (making them global
<gasp!>), and they show and change, as execution proceeds - as they
should.

You are looking at Autos window.
4. Also, once these scalars are moved and debug normally, the code runs
through the logic provided (!). (I know that nothing really changes in
terms of the return string, but there's more logic to be added to do
some of that - I'm just working out the logic to handle the data and
expand it as needed.)
Thus, it appears that the problem of code that isn't executed within
the routine is some effect of the scalar data declared and used in the
code (totally odd, in my experience...). I'm at a complete loss to
understand this... 8<{{
Here's my latest code (which as I said is working as I step through
the debugger). <sigh>
#include <string>
#include <sstream>
using std::string;
using std::eek:stringstream;
int ii, dPos, nn;
char wc;
int ndigit;
int column;
string spellNumber(double value)
{
string digitStr;
ostringstream ossw;
static string builder;
ossw.str(""); // Convert integer portion of value to string
ossw << value, digitStr = ossw.str();
dPos = digitStr.find(".");
if(dPos != string::npos)
digitStr.erase(dPos);
nn = digitStr.length(); // Traverse characters in reverse order
wc = digitStr.back();
for(ii = digitStr.length()-1; ii >= 0; ii--)
{
ndigit = (int)(digitStr.at(ii)-'0');
column = (digitStr.length()-(ii+1));
} // for
// more logic to be added here...
return builder;
}

int main(int argc, char *argv[])
{
string str = spellNumber(123.45);
return EXIT_SUCCESS;
} // main

All of this returns a blank string under debug and release builds. Do
you mean to return digits, not builder?
 
G

Geoff

I have the following (rather simple, I think) code which compiles but
executes in a bizarre way: the code in the subprogram is skipped when
called. 8<{{
Here's the code and the call to it I use:

What is this function supposed to do?
string spellNumber(double value)
{
bool showThousands = false;
bool allZeros = true;
int ii, dPos, nn;
char wc;
string digits, temp;
ostringstream ossw;
static string builder;
ossw.str("");
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);

Line above erases the decimal point and all after. Your string is now
"123". Why do you need to do anything else to this string?

nn = digits.length();
wc = digits.back();

OK, nn is 3, wc is '3'. Now what?
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for

WTF was this done for? You could have easily just said ndigit = nn. I
don't know what you are going to do with the column variable but they
both go out of scope when the for loop is completed, ii is 0xffffffff
(-1?) which suggests something went wrong in the loop.
 
M

Mike Copeland

What is this function supposed to do?

It's the start of a routine that will "spell a number": to produce
the sort of string data that's printed on a check. For example, 123
yields "One Hundred Twenty Three". The code that processes the
conversion isn't yet written...
Line above erases the decimal point and all after. Your string is now
"123". Why do you need to do anything else to this string?

See above. I will process the cents part separately. Ultimately I
want to print checks with the output from this routine.
nn = digits.length();
wc = digits.back();

OK, nn is 3, wc is '3'. Now what?
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for

WTF was this done for? You could have easily just said ndigit = nn. I
don't know what you are going to do with the column variable but they
both go out of scope when the for loop is completed, ii is 0xffffffff
(-1?) which suggests something went wrong in the loop.
Again, I'm testing only part of the code logic. 8<}}
 
G

Geoff

It's the start of a routine that will "spell a number": to produce
the sort of string data that's printed on a check. For example, 123
yields "One Hundred Twenty Three". The code that processes the
conversion isn't yet written...

You misunderstood the intent of my comments. They were intended to
tell you to properly document your code. State the purpose of the
function, THEN write the function.
Line above erases the decimal point and all after. Your string is now
"123". Why do you need to do anything else to this string?

See above. I will process the cents part separately. Ultimately I
want to print checks with the output from this routine.
nn = digits.length();
wc = digits.back();

OK, nn is 3, wc is '3'. Now what?
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for

WTF was this done for? You could have easily just said ndigit = nn. I
don't know what you are going to do with the column variable but they
both go out of scope when the for loop is completed, ii is 0xffffffff
(-1?) which suggests something went wrong in the loop.
Again, I'm testing only part of the code logic. 8<}}

.... and doing a very bad job of it by inspection. Those variables in
the for() loop go out of scope and can't be referenced outside that
loop. The loop becomes a no-op and yields nothing of interest. You
never documented why you need ndigit or column. You can get ndigit by
writing ndigit = digits.length() and immediately writing "one-hundred"
or "two-hundred" based on ndigit == 3 alone, the for loop becomes
superfluous.

You never addressed the issues of the IDE mentioned in my other posts
in this thread. What you are seeing is to be expected given the code
you've fed it. Your variables are going out of scope as you step
through the function and you are looking for them in all the wrong
places. Change your style, use white space, learn scoping rules and
declare your variables accordingly.

string spellNumber(double value)
{
int ndigit, column;
string digits;
ostringstream ossw;
static string builder;

// Convert integer portion of value to string
ossw.str("");
ossw << value;
digits = ossw.str();

// truncate the string
int dPos = digits.find('.');
if(dPos != string::npos)
digits.erase(dPos);

// Traverse characters in reverse order
int nn = digits.length();
char wc = digits.back();
for(int ii = digits.length()-1; ii >= 0; ii--)
{
ndigit = (int)(digits[ii]-'0');
column = (digits.length()-(ii+1));
}

return digits;
}
 
G

guinness.tony

I have the following (rather simple, I think) code which compiles but
executes in a bizarre way: the code in the subprogram is skipped when
called. 8<{{
Here's the code and the call to it I use:

string spellNumber(double value)
{
bool showThousands = false;
bool allZeros = true;
int ii, dPos, nn;
char wc;
string digits, temp;
ostringstream ossw;
static string builder;
ossw.str("");
ossw << value;
digits = ossw.str();
dPos = digits.find('.');
if(dPos != string::npos) digits.erase(dPos);
nn = digits.length();
wc = digits.back();
for(ii = digits.length()-1; ii >= 0; ii--)
{
int ndigit = (int)(digits[ii]-'0');
int column = (digits.length()-(ii+1));
} // for
// more code to be added here
return builder;
}
...
spellNumber(123.45); // call the function

I have, of course the normal stdafx.h header and "use namespace
std;", and this is code from a small test program I use to debug new
functions and such. Many other programs and many thousands of lines of
code work fine, but this code is weird...and I can't see what's wrong
with it!
Please advise... TIA

Your function returns a copy of the empty string named 'builder'.

Seeing this, the compiler can also determine that all the other code
has no observable external effect and is at liberty to ignore it.
 

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

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top