I have N+1 files in a folder called b0.txt,b1.txt,b2.txt, ....,bN.txt.
I would like to open them inside a loop because for each of them I would like to copy the first 15 characters inside an array.
The code lines I wrote are basically:
int main(){
int N=4;
int i;
char number [15];
for(i=0; i< N; i++){
ifstream OpenFile("b%i.txt");
int l=0;
while(!OpenFile.eof()) {
OpenFile >> number [l];
l++;
}
OpenFile.close();
}
}
I'm using Dev C++ and when I compile these code lines no errors are shown. However, I'm not able to run the program.
Do you have any tip?
You should build the string name of the file. You might try:
char bufname[64];
snprintf(bufname, sizeof(bufname), b%i.txt", i);
ifstream OpenFile(bufname);
or use std::string or std::ostringstream tricks.
The filename "b%i.txt" is used explicitly as written, not as a printf-style format specifier.
You can either use sprintf, e.g.:
char filename[512];
sprintf(filename, "b%i.txt", i);
ifstream OpenFile(filename);
or use the C++ ostringstream, e.g.:
std::ostringstream filename;
filename << "b" << i << ".txt";
ifstream OpenFile(filename.str().c_str());
"b%i.txt" doesn't put i into the string... you can use:
std::ostringstream oss;
oss << 'b' << i << ".txt";
if (std::ifstream f(oss.str().c_str()))
...f is an open stream - use it here...
else
std::cerr << "couldn't open file " << oss.str() << '\n';
Don't test for eof - it doesn't work like that. Just use read and gcount:
if (OpenFile.read(number, sizeof number) && f.gcount() == sizeof number)
...you got the data...
else
std::cerr << "unable to read 15 characters from " << oss.str() << '\n';
(FWIW, eof is set after an input operation is concluded or aborted due to hitting eof, so it's not false before you attempt input, and it not being set doesn't guarantee the next operation will succeed - how could it if the stream doesn't yet know what you'll try to read?)
Your program does nothing to get the value of i into the string that you are sending to OpenFile(). You have to create a string with a textual representation of i embedded in it, which this code does not do.
Change
OpenFile("b%i.txt")
to
char filename[8];
sprintf(filename, "b%d.txt", i); // Create filename with embedded number
ifstream OpenFile(filename);
ifstream OpenFile("b%i.txt");
You're not writing in Batch! Here you can't put number variable using %name syntax.
If you're using C++11, I'd recommend to use std::to_string and type:
ifstream OpenFile("b"+std::to_string(i)+".txt");
for the code line where you are reading the characters in array
"OpenFile >> number [l];"
the compiler will through the error "segmentation fault" due to array out of bound.
so you have to add condition like this
if( l <= 14) // bcz you are starting with l=0
{
OpenFile >> number [l];
}
else
break;
Related
I'm pretty sure that this is a common question, but I can't find an example similar to mine, so..
I have a text file called input.txt that has: 0.0001234 1.0005434 0.0005678 1.0023423 0.00063452 1.0001546 0.00074321 1.00017654 in it.
Now I want to write a program to read that into an array, and then quickly check that it worked. So far, I've got:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
double PA[8];
int n;
ifstream myfile ("input.txt");
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << PA[line]<< endl;
}
myfile.close();
}
else cout << "Unable to open file";
for (n=0; n<8; n++) // to print the array, to check my work
{
cout << " {" << PA[n] << "} ";
}
system("PAUSE");
return 0;
}
My problem so far is that I keep getting the error: line was not declared. And I want to use the array later with floats to calculate new data. I think I'm doing it wrong for that.. Any help? Thanks!
declare line variable
int n, line = 0;
std::string value;
proper load data:
getline (myfile,value);
PA[line] = atof(value.c_str());
cout << PA[line]<< endl;
line++;
the variable line here
cout << PA[line]<< endl;
is not declared. and if you declare it, you also have to give it a value, otherwise it's undefined and the PA[line] is undefined, in other words: will crash.
the entire while block seems suspicious:
while (! myfile.eof() )
{
getline (myfile,line);
cout << PA[line]<< endl;
}
are you sure about the getline call?
I know a getline with this signature:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
and that does not even match the number of arguments in your version.
if your input file has more than 8 lines on input, than the while loop will have that many interations - and your array has only space for 8 elements.
You need to declare the variable you called 'line' as follows:
int i=0;
while (! myfile.eof() && i<8)
{
std::string line; // this was the missing statement
getline (myfile,line);
double value = atof(line.c_str()); // convert line form char* to double
PA[i++] = value;
cout << value << endl;
}
Note that you need to convert line as double and use increment variable 'i' (for example, as I did. Make sure not overflowing PA capacity by checking i agains the size (currently 8, which should not hard coded, btw).
Also note that you shouldn't print the result if file access failed.
This seems like such an easy task, but everything I've tried hasn't worked so far.
I have a file foo.txt:
3
3 4 2
Now I want to read this file, read the first line and instantiate an int array with the size of the number it read on the first line.
Then it should populate that array with the elements in the second line, which has the exact same amount of elements and noted in line one.
If we're going to give you example code, might as well show you the best way to do it:
std::ifstream datafile("foo.txt");
if (!datafile) {
std::cerr << "Could not open \'foo.txt\', make sure it is in the correct directory." << std::endl;
exit(-1);
}
int num_entries;
// this tests whether the number was gotten successfully
if (!(datafile >> num_entries)) {
std::cerr << "The first item in the file must be the number of entries." << std::endl;
exit(-1);
}
// here we range check the input... never trust that information from the user is reasonable!
if (num_entries < 0) {
std::cerr << "Number of entries cannot be negative." << std::endl;
exit(-2);
}
// here we allocate an array of the requested size.
// vector will take care of freeing the memory when we're done with it (the vector goes out of scope)
std::vector<int> ints(num_entries);
for( int i = 0; i < num_entries; ++i )
// again, we'll check if there was any problem reading the numbers
if (!(datafile >> ints[i])) {
std::cerr << "Error reading entry #" << i << std::endl;
exit(-3);
}
}
Demo (with small changes because I can't provide a file with the right name on ideone): http://ideone.com/0vzPPN
You need to use ifstream object just like you use cin
ifstream fin("foo.txt"); //open the file
if(!fin.fail()){
int count;
fin>>count; //read the count
int *Arr = new int[count];
for(int i=0;i<count;i++){ //read numbers
fin>>Arr[i];
}
//... do what you need ...
//... and finally ...
delete [] Arr;
}
If you open a file using input filestream you can simply do that:
std::ifstream file_txt("file.txt");
int number_count = 0;
file_txt >> number_count; // read '3' from first line
for (int number, i = 0; i < number_count; ++i) {
file_txt >> number; // read other numbers
// process number
}
Filestreams just like other standard streams (std::cin, std::cout) can apply formatting depending on type supplied to operator>> (in this case an int).
This apply to both input and output.
Alternatively, you could avoid the entire need to read in the size beforehand by simply loading it into a std::vector:
std::ifstream fin("myfile.txt");
std::vector<int> vec{std::istream_iterator<int>(fin), std::istream_iterator<int>()};
fin.close();
or, if you cannot use C++11 syntax:
std::ifstream fin("myfile.txt");
std::vector<int> vec;
std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::back_inserter(vec));
fin.close();
I have a file that has a number in which is the number of names that follow. For example:
4
bob
jim
bar
ted
im trying to write a program to read these names.
void process_file(ifstream& in, ofstream& out)
{
string i,o;
int tmp1,sp;
char tmp2;
prompt_user(i,o);
in.open (i.c_str());
if (in.fail())
{
cout << "Error opening " << i << endl;
exit(1);
}
out.open(o.c_str());
in >> tmp1;
sp=tmp1;
do
{
in.get(tmp2);
} while (tmp2 != '\n');
in.close();
out.close();
cout<< sp;
}
So far I am able to read the first line and assign int to sp
I need sp to be a counter for how many names. How do I get this to read the names.
The only problem I have left is how to get the names while ignoring the first number.
Until then i cannot implement my loop.
while (in >> tmp1)
sp=tmp1;
This successfuly reads the first int from the and then tries to continue. Since the second line is not an int, extraction fails, so it stops looping. So far so good.
However, the stream is now in fail state, and all subsequent extractions will fail unless you clear the error flags.
Say in.clear() right after the first while loop.
I don't really see why you wrote a loop to extract a single integer, though. You could just write
if (!(in >> sp)) { /* error, no int */ }
To read the names, read in strings. A loop is fine this time:
std::vector<std::string> names;
std::string temp;
while (in >> temp) names.push_back(temp);
You'd might want to add a counter somewhere to make sure that the number of names matches the number you've read from the file.
int lines;
string line;
inputfile.open("names.txt");
lines << inputfile;
for(i=0; i< lines; ++i){
if (std::getline(inputfile, line) != 0){
cout << line << std::endl;
}
}
First of all, assuming that the first loop:
while (in >> tmp1)
sp=tmp1;
Is meant to read the number in the beginning, this code should do:
in >> tmp1;
According to manual operator>>:
The istream object (*this).
The extracted value or sequence is not returned, but directly stored
in the variable passed as argument.
So don't use it in condition, rather use:
in >> tmp1;
if( tmp1 < 1){
exit(5);
}
Second, NEVER rely on assumption that the file is correctly formatted:
do {
in.get(tmp2);
cout << tmp2 << endl;
} while ( (tmp2 != '\n') && !in.eof());
Although whole algorithm seems a bit clumsy to me, this should prevent infinite loop.
Here's a simple example of how to read a specified number of words from a text file in the way you want.
#include <string>
#include <iostream>
#include <fstream>
void process_file() {
// Get file name.
std::string fileName;
std::cin >> fileName;
// Open file for read access.
std::ifstream input(fileName);
// Check if file exists.
if (!input) {
return EXIT_FAILURE;
}
// Get number of names.
int count = 0;
input >> count;
// Get names and print to cout.
std::string token;
for (int i = 0; i < count; ++i) {
input >> token;
std::cout << token;
}
}
I'm trying to read character by character from a text file until EOF, put them into a character array, so that I can manipulate it after. Compiled with g++ without errors, and when run, I'm prompted for the input file but then it just hangs.
int main (int argc, char *argv[]) {
string filename;
ifstream infile;
char *cp, c[1024];
memset (c, 0, sizeof(c));
cp = c;
cout << "Enter file name: " << endl;
cin >> filename;
//open file
infile.open( filename.c_str() );
//if file can't open
if(!infile) {
cerr << "Error: file could not be opened" << endl;
exit(1);
}
while (!infile.eof()); {
infile.get(c, sizeof(infile));
// get character from file and store in array c[]
}
}//end main
You should try the istream::read() method rather than get(). This will help resolve any buffer overruns:
unsigned int chars_read = 0;
//...
// Read in the file.
if (!infile.read(c, sizeof(c))
{
// Handle the read error here.
// Also check for EOF here too.
}
// Obtain the number of characters actually read.
chars_read = infile.gcount();
First off, you don't want to test for eof()! Somehow I start to feel like Don Quixote having found my windmills. However, I do know that you need to check that the input was successful after trying to read it because before attempting to read the stream can't know whether it will be successful.
You program actually doesn't hang! It just waits for you to enter sizeof(infile) characters or end the input (e.g., using Ctrl-D on UNIXes and Ctrl-Z on Windows). Of course, this may look remarkable like a hanging program. You can verify that this is, indeed, the problem by using a smaller size, e.g., 4. Of course, sizeof(infile) is nearly as good as a small random number: It is the size of an object of type std::ifstream and who can tell what that is? You probably meant to use sizeof(c) to make sure that the call to get(c, n) won't write more character than can fit into c.
Try this:
int cont = 0;
while(infile.good()) {
c[cont++] = infile.get();
}
I work on using extensible hash to find the query FASTER.
my code is this steps:
1)read the main text file ( hudge file 4 GiB)
the file is some thing like this :
12435 alex romero
13452 jack robert
13485 marya car
45132 gun tribble
...
the user want to know that for example the key 12435 is related to what ?(answer:alex romero)
2)create a hash table for the keys in the file (i means 12435,13452,13485,...)
and i save this tables dynamically in hard disk in some text files named:0.txt,1.txt,2.txt and ....
3)when the user get query to the program then the program must calculate the hash function on its value and find the file that must be read then it is faster to find the result.
i have a function:
#define LIMIT 7
void writeInFile(int key , const char* charPos ){
int remainder = key%(LIMIT*LIMIT);
string myFileName;
ostringstream convert;
convert << remainder ;
myFileName = convert.str();
myFileName += ".txt";
FILE *my_file;
my_file = fopen(myFileName.c_str() ,"a");
fputs("\n" ,my_file);
fputs(charPos , my_file);
//fclose(my_file);
}
i wondered that when i use fclose then the speed of the program will reduced !!!
then i dont use it at the end of the function but a problem that is when i use this function many times i can't close them then i cant get access to the files.
i want to create a "list" of FILEs that i can send refrence of them to the function like: FILE &* myFiles[] or FILE &** myFiles as 3th parameter that function gets...
but i see the errors .i dont know how is its syntax of this.i means some syntax like:
void writeInFile(int key , const char* charPos , FILE &*myFiles[] ) // this makes error
the other method that i think is that can i close those files that now I can't access to them ? or can i change my code that cause this ?
update:this is my full code
#include <iostream>
#include <fstream>
#include <limits>
#include <string>
#include <sstream>
#include <stdio.h>
#include <vector>
#define LIMIT 7
using namespace std;
void writeInFile(int key , const char* charPos ){
int remainder = key%(LIMIT*LIMIT);
string myFileName;
ostringstream convert;
convert << remainder ;
myFileName = convert.str();
myFileName += ".txt";
FILE *my_file;
my_file = fopen(myFileName.c_str() ,"a");
fputs("\n" ,my_file);
fputs(charPos ,my_file);
//fclose(my_file);
}
int main(){
string fileName;
cout << "hello, please inter your file destination : " ;
cin >> fileName;
ifstream myFile ;
myFile.open(fileName.c_str() ,ifstream::in |ifstream::binary);
cout << "building the hash,please wait";
string havij;//:D this is an unusable variable in this section :))
int current;
int index;
int isCout=0;
char buffer [10];
//FILE *my_file[49];
while(!myFile.eof()){
cout << isCout << endl;
isCout++;
index = myFile.tellg();
itoa(index , buffer ,10);
//cout << buffer << endl;
myFile >> current;
writeInFile(current ,buffer);
getline(myFile,havij);
}
myFile.close();
fstream test;
//for(int i =0 ; i<LIMIT*LIMIT-1 ; i++){
// fclose(my_file[i]);
//}
cout << endl << "static extensible hash structure builded please inter your query : " ;
int query;
cin >> query;
int remainder = query%(LIMIT*LIMIT);
string myFileName;
ostringstream convert;
convert << remainder ;
myFileName = convert.str();
myFileName += ".txt";
ifstream myFile2;
//myFile2 is now the files that create by program like : 12.txt ,25.txt ,....
myFile2.open(myFileName.c_str() , ifstream::in | ifstream::binary);
ifstream mainFile;
mainFile.open(fileName.c_str(), ifstream::in | ifstream::binary);
int position;
string wanted;
int tester;
while(!myFile2.eof()){
myFile2 >> position;
mainFile.seekg(position ,ios::beg);
mainFile >> tester;
if (tester == query ){
getline(mainFile ,wanted);
cout << "the result of the key " << tester << " is " << wanted << endl;
}
}
return 0;
}
Or you could do this:
void writeInFile(int key , const char* charPos , std::vector<std::ofstream> & myFiles );
I find this makes my brain hurt less.
If you don't close your file in the same context where the FILE* variable is declared, you are leaking that file descriptor. At some point you are going to run out of resources and the program will crash.
Since you are using C++ from the snippet you've shown, then you would be much better off using std::vector and std::ofstream.
void writeInFile(int key, const char* charPos, std::vector<std::ofstream> my_files )
As has been said, you should close the file in the scope it is opened. This is the default behavior for C++ streams.
However it does not mean that you should open/close for each word you add! The files you write to should be kept open as long as you have things to add to them (beware there is a limit in the number of file descriptors an OS can handle).
Therefore, you should have:
Open all destination files (*)
For each line, select the appropriate file in a table/map and write into it
Close all destination files
(*) As said, you might run into a hard limit, in this case there is not much you can do, caching is unlikely to be effective if your hash function is worth anything. A possibility would be to make several runs over the big file and saving only a portion of the hashes at each run (say run 1: hashes in [0-9], run 2: hashes in [10-19], ...).
The fundamental type FILE* or ofstream that you use is of little importance, both have comparable speed (correctly tuned).