input from a file

Working my way through the Project Euler problems here, and I have a quick question:

Given a text file:
1
2
3
45646465465465478932187
12317894132198719465417
61871657197198419847941


Is there a way to put one digit at a time into a variable without having to introduce whitespace into the file after each digit?

What I'd like to do is get the first five digits into int a, b, c, d, e respectively so I can treat them all separately.

What I've written so far works if I put spaces or returns after each number, but not if I leave them as a solid block of numbers. The code below isn't complete, but it's where I'm at to start.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
#include<fstream>

using std::ifstream;
using namespace std;

int main()
{
    int a, b, c, d, e=0;
    string filename;
    ifstream indata;
    time_t begin, end;
    
    cout<<"Please enter the name of he file that you'd like to use."<<endl;
    cin>>filename;
    
    begin=clock();
    indata.open(filename);
    if (!indata)
    {
        cerr<<"Error: file name could not be opened."<<endl;
    }
    
    while (!indata.eof())
    {
        //a=b;    b=c;    c=d;    d=e;
        
        indata.get >>a;
        indata.get >>b;
        indata.get >>c;
        indata.get >>d;
        indata.get >>e;
        
        cout<<"The numbers input from your file are: ";
        cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<endl<<endl;
        
        cout<<"The product of these five numbers is: "<<a*b*c*d*e<<endl;
    }
    double diff=(double)(end-begin)/(double)CLOCKS_PER_SEC;
    cout<<"Elapsed calculation time: "<<diff<<endl;
    
    cin.sync();
    cin.get();
    return(0);
}


Also, I get a compiler error if I don't have quotes around filename in line 18, but the program still runs fine. Is there something else I should be doing to use a user-input string as my filename?

Thanks,

Vince
Apparently I'm not allowed to post full solution anymore, but whatever.

Anyways I believe you can go one character at a time like this:

indata >> a;
closed account (DSLq5Di1)
Because that is one giant number and "indata >> someIntegerVar" will extract the full line as a single number. You could use a temporary char variable to extract each digit and convert to an int, such as:-

1
2
3
4
5
6
7
8
9
10
inline int extract_digit(istream& is)
{
    int num = -1;
    char ch = is.get();

    if (isdigit(ch))
        num = static_cast<int>(ch-'0');

    return num;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    while (!indata.eof())
    {
        //a=b;    b=c;    c=d;    d=e;
        
        a = extract_digit(indata);
        b = extract_digit(indata);
        c = extract_digit(indata);
        d = extract_digit(indata);
        e = extract_digit(indata);
        
        cout<<"The numbers input from your file are: ";
        cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<endl<<endl;
        
        cout<<"The product of these five numbers is: "<<a*b*c*d*e<<endl;
    }

-edit-
Oh and your compiler error is because you haven't included the string header.

#include <string>
Last edited on
Two problems:

First, I'm getting the same compiler error even after adding #include<string> . For now, I've just put in the file name I want to use instead of using the variable, but I'd like to get this working.

Second, the program runs just as I'd like until it gets to the end of a line. At that point, it outputs 16384 as if it were another digit, meaning it sticks around for the next four iterations until we're evaluating only the numbers from a single line.

So if the first lines of my file are:

1
2
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843


If I output the current five digits and their products after each iteration, I get:

1
2
3
4
5
6
7
8
9
10
11
7  3  1  6  7  882
3  1  6  7  1  126
...
9  4  9  3  4  3888
4  9  3  4  16384  7077888
9  3  4  16384  9  15925248
3  4  16384  9  6  10616832
4  16384  9  6  9  31850496
16384  9  6  9  8  63700992
9  6  9  8  3  11664
6  9  8  3  5  6480


Once we're completely onto the second line, it works fine until the end of that line, and so on. Is there an end of line character I need to be accounting for?

Here's my current program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<iostream>
#include<fstream>
#include<string>

using std::ifstream;
using namespace std;


inline int extract_digit(istream& is)
{
    int num = -1;
    char ch = is.get();

    if (isdigit(ch))
    {
        num = static_cast<int>(ch-'0');
        return num;
    }
}

int main()
{
    string filename;
    ifstream indata;
    time_t begin, end;
    int a, b, c, d, e, a1, b1, c1, d1, e1, largestproduct;
    
    cout<<"Please enter the name of he file that you'd like to use."<<endl;
    cin>>filename;
    cout<<endl;
    
    begin=clock();
    indata.open("1000digits.txt");
    if (!indata)
    {
        cerr<<"Error: file name could not be opened."<<endl;
    }

    if (!indata.eof())
    {
        //gets the first five digits, multiplies them, and assigns that value to 
        //largestproduct
        a=extract_digit(indata);
        b=extract_digit(indata);
        c=extract_digit(indata);
        d=extract_digit(indata);
        e=extract_digit(indata);
        largestproduct=a*b*c*d*e;
        a1=a;   b1=b;   c1=c;   d1=d;   e1=e;
        
        cout<<"The first set of numbers from your file is: "<<a<<"  "<<b<<"  ";
        cout<<c<<"  "<<d<<"  "<<e<<"."<<endl;
        cout<<"The product of those numbers is: "<<largestproduct<<"."<<endl<<endl;
        system("pause");
        cout<<endl;
    }
    
    while (!indata.eof())
    {
        a=b;    b=c;    c=d;    d=e;    e=extract_digit(indata);
        
        cout<<"The numbers input from your file are: ";
        cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<endl;
        cout<<"The product of these five numbers is: "<<a*b*c*d*e<<endl<<endl;
        
        if (largestproduct<(a*b*c*d*e))
        {
            largestproduct=a*b*c*d*e;
            a1=a;   b1=b;   c1=c;   d1=d;   e1=e;
        }
        
        cout<<"The current five-digit set with the largest product is: ";
        cout<<a1<<"  "<<b1<<"  "<<c1<<"  "<<d1<<"  "<<e1<<"."<<endl;
        cout<<"The current largest product is: "<<largestproduct<<"."<<endl<<endl;
        system("pause");
        cout<<endl;
    }

    cout<<"The five consecutive digits from your file that produce the largest";
    cout<<" product are: "<<a1<<", "<<b1<<", "<<c1<<", "<<d1;
    cout<<", and "<<e1<<"."<<endl;
    cout<<"The product of those digits is ";
    cout<<largestproduct<<"."<<endl;
    double diff=(double)(end-begin)/(double)CLOCKS_PER_SEC;
    cout<<"Elapsed calculation time: "<<diff<<endl;
    
    cin.sync();
    cin.get();
    return(0);
}


and the contents of the file (I've named it "1000digits.txt") I'm working with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450


Thanks,

Vince
Weird. I added an if statement to move on if any of the variables in the string are "0":

1
2
3
4
        //if any variables are 0, the product of the sequence is 0 and not
        //what we're looking for; skip this iteration
        if(a*b*c*d*e==0)
            continue;


And suddenly the program works. I tried a few other things to check if any of the variables were a newline, but couldn't get it to work. After I took it out and added the code above, it magically works. As far as I can tell, that's the only substantial difference between the code in my last post and the code below. Can anyone tell me why it's suddenly working?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include<iostream>
#include<fstream>
#include<string>

using std::ifstream;
using namespace std;


inline int extract_digit(istream& is)
{
    int num = -1;
    char ch = is.get();

    if (isdigit(ch))
    {
        num = static_cast<int>(ch-'0');
        return num;
    }
}

int main()
{
    string filename;
    ifstream indata;
    time_t begin, end;
    //a-e are the current values from the file;a1-e1 are the current set that
    //gives the largest product
    int a, b, c, d, e, a1, b1, c1, d1, e1, largestproduct;
    
    //cout<<"Please enter the name of the file that you'd like to use."<<endl;
    //cin>>filename;
    //cout<<endl;
    
    begin=clock();
    indata.open("1000digits.txt");
    if (!indata)
    {
        cerr<<"Error: file name could not be opened."<<endl;
    }

    if (!indata.eof())
    {
        //gets the first five digits, multiplies them, and assigns that value to 
        //largestproduct
        a=extract_digit(indata);
        b=extract_digit(indata);
        c=extract_digit(indata);
        d=extract_digit(indata);
        e=extract_digit(indata);
        largestproduct=a*b*c*d*e;
        a1=a;   b1=b;   c1=c;   d1=d;   e1=e;


    }
    
    while (!indata.eof())
    {
        //moves the values of b, c, d, and e to the next variable down and
        //assigns the next number from the file to e
        a=b;    b=c;    c=d;    d=e;    e=extract_digit(indata);
        
        //if any variables are 0, the product of the sequence is 0 and not
        //what we're looking for; skip this iteration
        if(a*b*c*d*e==0)
            continue;
            

                
        //if the program identifies a new largestproduct, it stores the product
        //and the variables used to achieve it.
        if (largestproduct<(a*b*c*d*e))
        {
            largestproduct=a*b*c*d*e;
            a1=a;   b1=b;   c1=c;   d1=d;   e1=e;
        }
        

    }

    cout<<"The five consecutive digits from your file that produce the largest";
    cout<<" product are: "<<a1<<", "<<b1<<", "<<c1<<", "<<d1;
    cout<<", and "<<e1<<"."<<endl;
    cout<<"The product of those digits is ";
    cout<<largestproduct<<"."<<endl;
    double diff=(double)(end-begin)/(double)CLOCKS_PER_SEC;
    cout<<"Elapsed calculation time: "<<diff<<endl;
    
    cin.sync();
    cin.get();
    return(0);
}
closed account (DSLq5Di1)
1
2
3
4
5
6
7
    if (isdigit(ch))
    {
        num = static_cast<int>(ch-'0');
        return num; // undefined behaviour, not all code paths return a value
    }
    return num; // will return -1 for non-digits
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    while (!indata.eof())
    {
	int num = extract_digit(indata);

	if (num > 0) // or >= to include 0s but ignore non-digits
	{
		a=b;    b=c;    c=d;    d=e;    e=num;
        
		cout<<"The numbers input from your file are: ";
		cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<endl;
		cout<<"The product of these five numbers is: "<<a*b*c*d*e<<endl<<endl;
        
		if(a*b*c*d*e==0) // no longer needed
			continue;

		if (largestproduct<(a*b*c*d*e))
		{
			largestproduct=a*b*c*d*e;
			a1=a;   b1=b;   c1=c;   d1=d;   e1=e;
		}
        
		cout<<"The current five-digit set with the largest product is: ";
		cout<<a1<<"  "<<b1<<"  "<<c1<<"  "<<d1<<"  "<<e1<<"."<<endl;
		cout<<"The current largest product is: "<<largestproduct<<"."<<endl<<endl;
		system("pause");
		cout<<endl;
	}
    }

Forgot to mention previously you'll want to #include<cctype> for the use of isdigit() and your calls to clock() require #include<ctime> .

I'm stumped as to why you are having problems with std::string, perhaps an outdated compiler?
Thanks sloppy9.

For some reason, my output was incorrect with your line 16, so I revised to if (a*b*c*d*e==0) instead, and now that works.

I also added
1
2
#include<cctype>
#include<ctime> 


Neither worked. I tried #include<time.h> , which I'd previously used and just forgot to add for this project, and that fixed the timing issue.

Finally, per your advice, I tried a different compiler. I downloaded visualc++ 2010 express and (after a little learning curve on the software) the program compiled and run exactly as it should (in only 1 millisecond!).

I'm not too impressed with all the fluff of VisualC++ express. Anyone have any advice of how I can update the compiler in my Dev-C++? If not, how about suggestions on a comparable free compiler (that's easy to install)?

Marking this one as solved.

Thanks everyone. I've learned a lot on this one.

-Vince
Topic archived. No new replies allowed.