tags:

views:

113

answers:

2

I wrote a simple program to grab stock prices from yahoo finance. The loop that reads the data was truncating early (and ending about where the data from the website shows as opposed to the full download to the correct date for the excell file). So I put in a cout command in the loop to try to debug and voila, it worked correctly!

So why does using the cout function alter the program function? Any ideas? Below is the code. (I found two related posts, but still cant figure it out, e.g. "Can cout alter variables somehow?" and "Weird Error in C++ Program: Removing Printout Breaks Program")

#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <windows.h>
#include <wininet.h>

using namespace std;
int main()
{
    HINTERNET hOpen, hURL;
    LPCWSTR NameProgram = L"Webreader"; // LPCWSTR == Long Pointer to Const Wide String 
    LPCWSTR Website;                    
    char file[101];
    int i;
    string filename;        
    unsigned long read;

    filename = "data.txt";
    ofstream myFile(filename);
    if (! myFile)
    {
        cout < "Error opening file\n";
    }
    if ( !(hOpen = InternetOpen(NameProgram, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 )))
    {
        cerr << "Error in opening internet" << endl;
        return 0;
    }                       
    Website = L"http://ichart.finance.yahoo.com/table.csv?s=MSFT&amp;a=00&amp;b=1&amp;c=2009&amp;d=09&amp;e=22&amp;f=2010&amp;g=d&amp;ignore=.csv";
    hURL = InternetOpenUrl( hOpen, Website, NULL, 0, 0, 0 ); //Need to open the URL
    InternetReadFile(hURL, file, 100, &read);
    file[read] = '\0';
    myFile << file;
    while (read == 100)
    {
        InternetReadFile(hURL, file, 100, &read);
        file[read] = '\0';
        myFile << file;
        cout << file; //If I take this line out, the function terminates early.
    }
    myFile << file;
    InternetCloseHandle(hURL);
    myFile.close();
    return 0;
}
+4  A: 

What you have is a "Heisenbug", one which disappears when you try to find it. Make no mistake, the problem is still there and you do need to find it.

The first thing you should be doing is checking the return code of InternetReadFile.

In addition, you should not assume that a successful read will return the full 100 bytes, even if there are more to come. The doco states:

To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.

: : :

Also, converted lines might not completely fill the buffer, so InternetReadFile can return with less data in lpBuffer than requested.

In other words, I would add:

BOOL rc;

and change your two:

InternetReadFile(hURL, file, 100, &read);

statements to:

rc = InternetReadFile(hURL, file, 100, &read);

then your loop becomes:

while ((!rc) || (read > 0))   // I *think* that's right.
paxdiablo
Bravo!! I changed the code to say
Gary White
Bravo! I changed the code to say while (reed != 0) and it worked!! Thanks!
Gary White
You changed the code to say Gary White? And it worked? I'm impressed :-) Seriously though, you _still_ need to check the return code.
paxdiablo
+1 for Heisenbug
Travis Christian
+1 for Heisenbug from me too
Chubsdad
The idea that the cout function takes time and that changed the operation of the program was a nice insight--I never would have thought. And I will put the above code in to verify all has been read by InternetReadFIle. Thanks again to all.
Gary White
+5  A: 

Doing a bit of output probably takes a little time, during which data can arrive from the net, ready to be read by your next call to InternetReadFile.

I haven't used that beast but if it works like other read-functions then it doesn't necessarily read 100 bytes, it may read anything less.

And if so then don't use read == 100 as continuation condition for your loop. Use e.g. read > 0. But do check the documentation, it should tell you what to expect.

Depending on how low-level that function is, it may also be that zero bytes read doesn't mean finished. It might be that you need to check the return value. And e.g. do a little delay before going on.

Cheers & hth.,

Alf P. Steinbach
Thanks to you as well!!! (Bravo! I changed the code to say while (reed != 0) and it worked!!) (You guys are great!)
Gary White