Reading file in C++ I/O

Hello,

I am working on some code that was in "C" but I would like to reuse this using C++. Even the code is running and working but I would like to use C++ stream I/O for more flexibility as I am learning through C++ provides more flexibility than C. Besides, I would like to make this later as user defined object based code. I will appreciate your help. It would be great if I can be confirmed in favor of the kind advice of the expert programmer in the forum what to do when
1
2
3
	FILE *fp = fopen(featfile, "r");
 {fread(&hdrs, 1, sizeof(hdrstr), fp);	
if(file_data.n != fread(file_data.data, 1, file_data.n , fp))
while I prefer using I/O stream in C++. The snippet of the prototype is also attached.
1
2
3
4
5
6
7
8
9
10
voice_data readmfc  (char *namefile){

    typedef struct hdrstr{
	       long Samp;
		long Perd;
		short Size;
		short Knd;
};
        


Thank you for your help and suggestions in advance.
Last edited on
So what exactly is the problem with declaring the function with extern "C"? Barring any specific technical requirements, I doubt throwing out a perfectly good zinc wheel and making a copper wheel to replace it is well-spent effort.
Thank you Helios for your kind response.

The mentioned code snippet i(n C) I would like to rewrite following C++ I/O stream classes.
1
2
3
FILE *fp = fopen(featfile, "r");
 {fread(&hdrs, 1, sizeof(hdrstr), fp);	
if(file_data.n != fread(file_data.data, 1, file_data.n , fp))


This is a user defined sequential file in C which I can use well in C++ as well. But I need to extend this for larger amount of files in project to read many data files. I thought in this case C++ STL would be a good choice for data structure related program. Is there any hints for the code snippet of my previous post for making this in full C++ string class related I/O based. the prototype:voice_data readmfc (char *namefile) has to be used for reading many files which I find inconvenient now. Can this be more flexible for example;
1
2
vector<voice_data> data;  
cin >> data ;
something like this for reading more files. Is this possible to have some hints for extending char *filename in a STL related I/O format type style. I am not sure if I could clarify my problem. If not, I will be happy to provide more info.

Thank you very much for the support.
1
2
vector<voice_data> data;  
cin >> data ;

Now, why would you want to do that?
It'd be just as easy to type something like
1
2
3
std::string filename;
readline(std::cin,filename);
data.push_back(readmfc(filename.c_str()));

and it'd be much more clear as to what exactly the code is doing.
iostream is not more flexible than stdio (mainly because it uses stdio internally), so I'm not sure what you're trying to accomplish. If you have an interface (in this case, a file IO interface) that works fine, don't waste your time rehashing it so you can do clever tricks with the language that don't really save you any work.

On a different subject, I don't think having a call to exit() in an IO interface is such a good idea.
Thank you very much, Helios.

Actually, I need to increase reading the voice data for some computation but it gives me error message when i try to increase the number of file reading. I do not have idea why it is giving me error when two files can be read well for computation. I thought using STL would help me to solve the problem.
Thanks, again for the help.
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
	
	
	
	recan1[ resultlichtant1] = "Fens";
	recan1[resultlichtant2] = "Fensd";
	recan1[resultlichtant3] =   "Lichd";
	......
	
			
	map<float, string>::iterator it;
	
	
	fstream resout("/Desktop/project/result.txt", ios::out);
	if(!resout){
		cerr << "file is not created" << endl;
	}
	
	resout << it->second;
	cout << endl;
	resout.close();
		}
		
	

		return 0;
}

	
	
Last edited on
Okay, let's see.
As a rule of thumb, if you're using more than 4 variables that end with numbers, you probably need to use some sort of linear data structure (array, vector, list or whatever):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char *tr1 = "/Desktop/project/Fensd.mfc";
char *tr2 = "/Desktop/project/Fensref.mfcc";
char *tr3 = "/Desktop/project/Lichref.mfcc";
char *tr4 = "/Desktop/project/Licharef.mfcc";
char *tr5 = "/Desktop/project/jaref.mfcc";
char *tr6 = "/Desktop/project/Neinref1.mfcc";
char *tr7 = "/Desktop/_project/Lictref2.mfcc";
char *tr8 = "/Desktop/project/Lichref3.mfcc";
char *tr9 = "/Desktop/project/Neinref2.mfcc"; 
//Wrong!

char *tr[]={
	"/Desktop/project/Fensd.mfc",
	"/Desktop/project/Fensref.mfcc",
	"/Desktop/project/Lichref.mfcc",
	"/Desktop/project/Licharef.mfcc",
	"/Desktop/project/jaref.mfcc",
	"/Desktop/project/Neinref1.mfcc",
	"/Desktop/_project/Lictref2.mfcc",
	"/Desktop/project/Lichref3.mfcc",
	"/Desktop/project/Neinref2.mfcc", 
};
//Right! 

After you do that, the code will be much more scrutable.

What do you mean it gives you an error message? What kind of error message?
By the way, I'm pretty sure this like is problematic:
1
2
//What if there are less than sizeof(hdrstr) bytes in fp?
fread(&hdrs, 1, sizeof(hdrstr), fp);


This is also not a good idea:
system("/usr/local/bin/HCopy /Desktop/project/demo/Neintest.wav /Desktop/project/Neintest.mfc");
Avoid system() like the plague, except maybe in small test programs to save some time. If you need to do anything with the system you can't do with the standard library (in this case, you could write your own copy function, but it's usually a hassle), then prefer either some portable library (like boost) or use system calls
Thank you very much for the kind response and advice, Helios.

I was trying to put the above in a vector to read the file one at a time
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
char *tr[]={
	"/Desktop/project/Fensd.mfc",
	"/Desktop/project/Fensref.mfcc",
	"/Desktop/project/Lichref.mfcc",
	"/Desktop/project/Licharef.mfcc",
	"/Desktop/project/jaref.mfcc",
	"/Desktop/project/Neinref1.mfcc",
	"/Desktop/_project/Lictref2.mfcc",
	"/Desktop/project/Lichref3.mfcc",
	"/Desktop/project/Neinref2.mfcc", 
};
vector<char> tr;

vector<char>::iterator it;

it = tr.begin(); 
//cout << *it <<endl;
while (it != tr.end()){
++it;
 voice_data trdata = readmfc(*tr);
 cout << endl;


The error message I received from this: "tr has previous declaration ....";

How I can proceed from here? I will appreciate any advice and help.
The file is formed to provide such type of structure as hdrstr by the hdrs process and I must convert this to read the data from the hdrstr structure. I will learn how to use Boost .
Thank you.
About the error message "tr has previous declaration ....";
You define two tr, char *tr[] and vector<char> tr,you should define different name for the vector<char>!
Save data to vector<*char>,code as follow:
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
#include <vector>
#include <iostream>

using namespace std;

int main(int i, char* argv[])
{
	char *tr[]={
		"/Desktop/project/Fensd.mfc",
		"/Desktop/project/Fensref.mfcc",
		"/Desktop/project/Lichref.mfcc",
		"/Desktop/project/Licharef.mfcc",
		"/Desktop/project/jaref.mfcc",
		"/Desktop/project/Neinref1.mfcc",
		"/Desktop/_project/Lictref2.mfcc",
		"/Desktop/project/Lichref3.mfcc",
		"/Desktop/project/Neinref2.mfcc", 
	};

	vector<char*> myVector(tr,tr+9);
	vector<char*>::iterator Itor;

	for (Itor=myVector.begin(); Itor!=myVector.end(); Itor++)
	{
		cout<<*Itor<<endl;
	}

	return 0;
} 



Thank you very much, Bujiwu. This has been very helpful.

I have a few questions in this regard and your kind response would be highly appreciated.
Since the number of entry in the data is increasing as test grows in the task, can I make this
1
2
3
4
5
	vector<char*> myVector(tr,tr+9);
	vector<char*>::iterator Itor;
class="quote">
class="qd">as
vector<char*> myVector(tr); // and then as user input: some hints would be helpful vector<char*>::iterator Itor;

I have some structures as
1
2
3
4
5
6
7
8
9
voice_data tr1, tr2, tr3......tr20 /*and each has to be read for the next task**/ vector<voice_data>train;
vector<voice_data>::iterator itv; 
train.push_back(*itv);
while (itv != train.end()){
train[*itv] = readmfc[*Itor];
cout << train[*itv].frames<<endl;
float dist = dist(*itv -te); // dist is also a vector as vector<float> dist and it is also dynamic
cout <<dist;
} 

Is this possible to do the above or what possible mistakes there?

Thank you very much for the kind help and response.
using sizeof operator can solve the first question.As follow:
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
#include <vector>
#include <iostream>

using namespace std;

int main(int i, char* argv[])
{
	char*  tr[]={
		"/Desktop/project/Fensd.mfc",
		"/Desktop/project/Fensref.mfcc",
		"/Desktop/project/Lichref.mfcc",
		"/Desktop/project/Licharef.mfcc",
		"/Desktop/project/jaref.mfcc",
		"/Desktop/project/Neinref1.mfcc",
		"/Desktop/_project/Lictref2.mfcc",
		"/Desktop/project/Lichref3.mfcc",
		"/Desktop/project/Neinref2.mfcc", 
	};

	int length =sizeof(tr)/sizeof(char*);

	vector<char*> myVector(tr,tr+length);
	vector<char*>::iterator Itor;

	for (Itor=myVector.begin(); Itor!=myVector.end(); Itor++)
	{
		cout<<*Itor<<endl;
	}

	return 0;
} 


In you second question,I think the third code line( train.push_back(*itv) ) is error!You can do like this.
train.push_back(tr1). Otherwise,in the while loop,you didn't increment iterator(itv).
I hope these can help you.TKS!

I think the third code line( train.push_back(*itv) ) is error

Nope. It's correct. That's how you get a reference to the value the iterator points to.

But I'm not sure what this is anymore. Why do you want to copy the pointers to a vector? The array will work just fine. If you really want to do that, you might as well initialize it as
1
2
3
4
5
6
7
8
9
10
std::vector<char *> myVector;
myVector.push_back("/Desktop/project/Fensd.mfc");
myVector.push_back("/Desktop/project/Fensref.mfcc");
myVector.push_back("/Desktop/project/Lichref.mfcc");
myVector.push_back("/Desktop/project/Licharef.mfcc");
myVector.push_back("/Desktop/project/jaref.mfcc");
myVector.push_back("/Desktop/project/Neinref1.mfcc");
myVector.push_back("/Desktop/_project/Lictref2.mfcc");
myVector.push_back("/Desktop/project/Lichref3.mfcc");
myVector.push_back("/Desktop/project/Neinref2.mfcc"); 

Then, to process the strings, you do
1
2
3
4
5
6
7
8
std::vector<voice_data> train;
for (int i=0;i<myVector.size();i++)
	//Note that is line alone is copying the structure TWICE, so you may want to
	//consider using pointers if the structure is somewhat large.
	train.push_back(readmfc(myVector[i]));
//Or, with iterators...
for (std::vector<char*>::iterator i=myVector.begin();i!=myVector.end();i++)
	train.push_back(readmfc(*i));
Thank you very much Bujiwu and Helios for the help and advice.
Topic archived. No new replies allowed.