Searching for sequence in a file

This is an exercise I found:
With a file containing a very long sequence of numbers, write a program that, asking for the path of the file and a new sequence of numbers where first is asked the lenght of the sequence(greater than 1), check if the sequece written is in the file and how many times the sequence is reapeted.

Example:
Sequence of number in the file:
23 45 21 33 12 33 22 44 66 45 21 33 12 11 876 11 45 21 33 12 13

Input:
file.txt
4
45 21 33 12

Output:
The sequence has been found 3 times.

The program has to be written in C++ and in functions


This is the code that I wrote until now. But there are a few things I don't know how to do.
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
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#define N 300

using namespace std;

//Prototype
void OpenFile(string path, int sequencefile[N]);
void CountSequence(int sequence[N], int sequencefile[N]);

fstream file;
int main()
{
	int *sequencefile[N];
	int *sequence[N];
	string path;
	cout<<"Write the path of the file: ";
	cin>>path;
	OpenFile(path, sequencefile[N]);
	CountSequence(sequence[N], sequencefile[N]);
	return 0;
}

void OpenFile(string path, int sequencefile[N])
{
	file.open(path.c_str(),ios::in);
	if(file.is_open())
	{
		int i=0;
		while(!file.eof())
		{
			file>>sequencefile[i];
			i++;
		}
	}
	else
	{
		cout<<"\nError! File not found!"<<endl;
	}
}

void CountSequence(int sequence[N], int sequencefile[N])
{
	int max=0;
	cout<<"Write the sequence of numbers you want to search(greater than 1): ";
	cin>>max;
	while(max<=1)
	{
		cout<<"You wrote an invalid number. Retry."<<endl;
		cin>>max;
	}
	cout<<"Write "<<max<<" numbers."<<endl;
	for(int i=0;i<max;i++)
	{
		cin>>sequence[i];
	}
	for(int j=0;j<max;j++)
	{
		while(sequence[j]==sequencefile[j])
		{
			
		}
	}
}


The problem is that I really don't know what code to write in order to compare the sequence I wrote and the sequence from the file. Does anyone have an idea for this?
Last edited on
It gives me now a problem in
1
2
3
4
5
while(!file.eof())
	{
		file>>sequencefile[i];
		i++;
	}

When I start the program it crashes in that part of the code. I'm having big problems with this exercise! D:
Last edited on
1) do not loop on eof()
http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong

2) Why do you have array of int pointers?

3) To find subsequence in larger sequence std::search can be used:
http://en.cppreference.com/w/cpp/algorithm/search
1) Okay, so I have to write it like this:
1
2
3
4
5
int i=0;
	while(file>>sequencefile[i])
	{
		i++;
	}


2) If I don't write the * before sequence[N] and sequencefile[N] they give me these errors:
In function 'int main()':
[Error] invalid conversion from 'int' to 'int*' [-fpermissive]
[Error] initializing argument 2 of 'void OpenFile(std::string, int*)' [-fpermissive]
[Error] invalid conversion from 'int' to 'int*' [-fpermissive]
[Error] initializing argument 1 of 'void CountSequence(int*, int*)' [-fpermissive]
[Error] invalid conversion from 'int' to 'int*' [-fpermissive]
[Error] initializing argument 2 of 'void CountSequence(int*, int*)' [-fpermissive]
And I don't know what to do.

3) I never used std::search. How does it works in this context?
1) Pretty much.
2) Line 22 and similar: you are not sending your array to function, you are sending Nth (nonexistent) element. Function should be called as OpenFile(path, sequencefile);
3) http://en.cppreference.com/w/cpp/algorithm/search
http://www.cplusplus.com/reference/algorithm/search/

Also you should save and pass to your Count function actual size of sequence loaded from file.
Note that you do not need to pass sequence to second function. It can be created in place.

Do not use global file. Create file where you need to use it. Also use ifstream instead of generic fstream and provide parameters in constructor. Also you do not have to call c_str() to pass path.
1
2
3
int OpenFile(string path, int sequencefile[N])
{
	std::ifstream file(path);
2) Okay, I got it.
3) How can I know the size of sequence loaded from file?
When you say "You do not need to pass sequence to second function. It can be created in place." you mean deleting int sequence[N] from the main and writing it in the second function? Like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CountSequence(int sequencefile[N])
{
	int sequence[N];
	int max=0;
	cout<<"Write the sequence of numbers you want to search(greater than 1): ";
	cin>>max;
	while(max<=1)
	{
		cout<<"You wrote an invalid number. Retry."<<endl;
		cin>>max;
	}
	cout<<"Write "<<max<<" numbers."<<endl;
	for(int i=0;i<max;i++)
	{
		cin>>sequence[i];
	}
	
}
you mean deleting int sequence[N] from the main and writing it in the second function? Like this:
Yes.
How can I know the size of sequence loaded from file?
There is variable i in OpenFile which holds index of last accessed element. Yiu can return it from function to pass it in main() then you can pass it in CountSequence
If I have to return i then the function OpenFile is no more a void but an int, right?
Yes.
I don't understand what ForwardIterator stand for.
Reading the links you posted I know that I have to use this:
1
2
3
4
template< class ForwardIt1, class ForwardIt2 >

ForwardIt1 search( ForwardIt1 first, ForwardIt1 last,
                   ForwardIt2 s_first, ForwardIt2 s_last );


So in my function CountSequence should be something like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void CountSequence(int sequencefile[N], int i)
{
	int sequence[N];
	int repetitions=0;
	int max=0;
	cout<<"Write the sequence of numbers you want to search(greater than 1): ";
	cin>>max;
	while(max<=1)
	{
		cout<<"You wrote an invalid number. Retry."<<endl;
		cin>>max;
	}
	cout<<"Write "<<max<<" numbers."<<endl;
	for(int j=0;j<max;j++)
	{
		cin>>sequence[j];
	}
	repetitions=search(sequencefile,sequencefile+i,sequence,sequence+max);
	cout<<"The sequence has been found "<<repetitions<<" times"<<endl;
}

Because it gives me this error at "search":

In function 'void CountSequence(int*, int)':
[Error] invalid conversion from 'int*' to 'int' [-fpermissive]
read reference more carefully. It does not return amount of entries. It returns an iterator (pointer in your case) to first found sequence or to last (sequencefile+i) if not found.

You want:
call search and save result to a variable
Check if result is not equal to last
If so, increase count, increment result (we do not want next search return the same)
repeat
If it is equal: stop looping.


Also I would suggest to move to C++ entities, such as vectors. They would make your code much cleaner. Example of your OpenFile function modified:
1
2
3
4
5
6
7
std::vector<int> load_from_file(std::string path)
{
    std::ifstream file(path);
    if(not file.is_open())
        std::cerr << "\nError! File not found!" << std::endl;
    return {std::istream_iterator<int>(file), std::istream_iterator<int>()};
}
Last edited on
Oh okay! Sorry!

1) Call search and save result to a variable
How? Isn't it like the code I wrote before?
1
2
repetitions=search(sequencefile,sequencefile+i,sequence,sequence+max);
//variable=search(etc,etc,etc,etc); 

2) Check if result is not equal to last
So something like:
1
2
3
if(variable!=lastresult) //with int lastresult=0 for the first time
	countsequence++;
	lastresult=variable;

3 and 4) Repeat. If it is equal: stop looping.
So all the code has to be in a do while iteration?

Anyway, for this exercise I prefer to continue with array if it's not a problem for you. :S
How? Isn't it like the code I wrote before?
In your code repetitions is int. In your case search will return int*

So something like:
Last here was referring to search parameter.
so it would be more like:
1
2
3
4
5
6
7
8
int* result;
//...
result = search(sequencefile,sequencefile+i,sequence,sequence+max);
if(result != sequencefile + i) {
    ++countresult;
    ++result;
}
//... 


Anyway, for this exercise I prefer to continue with array if it's not a problem for you. :S
Absolutely not.
It just a suggestion. You are missing the essence of C++ by not usoing standard library.

Okay, this is the code now:
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
// This program search for a sequence wrote before in a sequence already written in a file.
#include <iostream> 
#include <fstream> 
#include <string> 
#include <algorithm> // search(...);
#define N 300

using namespace std;

//PROTOTYPE
void OpenFile(string path, int sequencefile[N], int &i);
void CountSequence(int sequencefile[N], int i);

int main()
{
	int i=0;
	int sequencefile[N];
	string path;
	cout<<"Write the path of the file: ";
	cin>>path;
	OpenFile(path, sequencefile, i);
	CountSequence(sequencefile, i);
	return 0;
}

//Open the file and load the sequence.
void OpenFile(string path, int sequencefile[N], int &i) //"int i" must return his vaule for the next function.
{
	ifstream file(path.c_str()); //".c_str()" Get C string equivalent.
	if(file.is_open()) //It's true if the file is open (.is_open()).
	{
		while(file>>sequencefile[i]) //Load every number of the sequence into an array of integer.
		{
			i++; //Next position in the array.
		}
	}
	else
	{
		cout<<"\nError! File not found!"<<endl;
		exit(1);
	}
}

//This function count how many times the sequence written has been found.
void CountSequence(int sequencefile[N], int i)
{
	int sequence[N];
	int *result; //"result" must be a pointer in order to save the result from "search()"
	int max=0, countsequence=0;
	cout<<"Write the sequence of numbers you want to search(greater than 1): ";
	cin>>max;
	while(max<=1)
	{
		cout<<"You wrote an invalid number. Retry."<<endl;
		cin>>max;
	}
	cout<<"Write "<<max<<" numbers."<<endl;
	for(int j=0;j<max;j++)
	{
		cin>>sequence[j]; //Load every number of the sequence into another array of integer.
	}
	do
	{
		result=search(sequencefile,sequencefile+i,sequence,sequence+max);
		//Searches the range [sequencefile,sequencefile+i) for the first occurrence of the sequence defined by [sequence,sequence+max),
		//and returns an iterator to its first element, or sequencefile+i if no occurrences are found.
		if(result!=sequencefile+i)
		{
			++countsequence;
			++result;
		}
	}while(result==sequencefile+i);
	cout<<"The sequence has been found "<<countsequence<<" times"<<endl;
}

Now it counts wrong. It says me that he found the sequence 1 when it should be 3 times in the exemple.
(With the file containing this sequence:
"23 45 21 33 12 33 22 44 66 45 21 33 12 11 876 11 45 21 33 12 13"
and me writing this sequence:
"45 21 33 12")
I think I wrote something wrong in the do while iteration, right? XD

Yes, I know. I just started programming and there are a lot o things that I don't know but learning gradually. C:

EDIT: I copied the entire code in order to be clear.
Last edited on
MiiNiPaa wrote:
If it is equal: stop looping.
MiiNiPaa wrote:
if(result != sequencefile + i)

Your loop is terminated when they are not equal. Change while condition to correspond to if condition.
If I do that way, when I wrote the "n" numbers(4 in the example) it blocks like this and I can't write anything:
1
2
3
4
5
6
7
8
Write the path of the file: file.txt
Write the sequence of numbers you want to search(greater than 1): 4
Write 4 numbers.
45
21
33
12
_

It's like it's waiting for me to write but I can do nothing.
Last edited on
Show, what you have changed.
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
// This program search for a sequence wrote before in a sequence already written in a file.
#include <iostream> 
#include <fstream> 
#include <string> 
#include <algorithm> // search(...);
#define N 300

using namespace std;

//PROTOTYPE
void OpenFile(string path, int sequencefile[N], int &i);
void CountSequence(int sequencefile[N], int i);

int main()
{
	int i=0;
	int sequencefile[N];
	string path;
	cout<<"Write the path of the file: ";
	cin>>path;
	OpenFile(path, sequencefile, i);
	CountSequence(sequencefile, i);
	return 0;
}

//Open the file and load the sequence.
void OpenFile(string path, int sequencefile[N], int &i) //"int i" must return his vaule for the next function.
{
	ifstream file(path.c_str()); //".c_str()" Get C string equivalent.
	if(file.is_open()) //It's true if the file is open (.is_open()).
	{
		while(file>>sequencefile[i]) //Load every number of the sequence into an array of integer.
		{
			i++; //Next position in the array.
		}
	}
	else
	{
		cout<<"\nError! File not found!"<<endl;
		exit(1);
	}
}

//This function count how many times the sequence written has been found.
void CountSequence(int sequencefile[N], int i)
{
	int sequence[N];
	int *result; //"result" must be a pointer in order to save the result from "search()"
	int max=0, countsequence=0;
	cout<<"Write the sequence of numbers you want to search(greater than 1): ";
	cin>>max;
	while(max<=1)
	{
		cout<<"You wrote an invalid number. Retry."<<endl;
		cin>>max;
	}
	cout<<"Write "<<max<<" numbers."<<endl;
	for(int j=0;j<max;j++)
	{
		cin>>sequence[j]; //Load every number of the sequence into another array of integer.
	}
	do
	{
		result=search(sequencefile,sequencefile+i,sequence,sequence+max);
		//Searches the range [sequencefile,sequencefile+i) for the first occurrence of the sequence defined by [sequence,sequence+max),
		//and returns an iterator to its first element, or sequencefile+i if no occurrences are found.
		if(result!=sequencefile+i)
		{
			++countsequence;
			++result;
		}
	}while(result!=sequencefile+i);
	cout<<"The sequence has been found "<<countsequence<<" times"<<endl;
}


It's the same I wrote before. I just changed while(result==sequencefile+i); to while(result!=sequencefile+i);.
Oh, I noticed. You always search from the beginning of the sequence, so it will find the same position everytime. Instead, search beginning from previous fesult:
1
2
3
4
5
int* result = sequencefile; //Initialise result with beginning of sequence
//...
do {
    result = search(result, sequencefile + i, /*...*/);
//... 
Oh right!
Anyway, now it works! Thank you for your help! :D
Topic archived. No new replies allowed.