istream not working in DEV C++ - c++

I'm using ifstream and ofstream operations in DEV c++ but they don't seem to work correctly. I've been trying to write a little prime generator code but it doesn't work :\ When I display fstream::tellg() at any point, it displays -1:
#include<iostream>
#include<math.h>
#include<fstream>
using namespace std;
int prime (unsigned long long n)
{
ifstream f1;
ofstream f2;
unsigned long long i,m,root;
int flag=0;
for(i=2;i<=n;i++)
{
f1.open("prime2.txt",ios::binary);
if(!f1.is_open())
{
cout<<"NOT OPEN";
}
cout<<f1.tellg()<<" "; //Displaying getpointer pos
flag=0;
root=(unsigned long long)sqrt(i);
while(f1.read((char*)&m,sizeof(m)))
{
if((i%m)==0)
{
flag=1;
break;
}
if(m>root)
{
break;
}
}
f1.close();
if(!flag)
{
f2.open("prime2.txt",ios::app|ios::binary);
f2.write((char*)&i,sizeof(i));
cout<<i<<" "; //Displaying num being written
f2.close();
}
}
return 1;
}
int main(int argc, char* argv[])
{
prime(50);
system("pause");
}
(I'm sorry, i just couldn't make the whole thing get in one codeblock. I guess theres something wrong with [code] tag?)
Output:
NOT OPEN-1 2 -1 3 -1 4 -1 5 -1 6 -1 7 -1 8 -1 9 -1 10 -1 11 -1 12 -1 13 -1 14 -1
15 -1 16 -1 17 -1 18 -1 19 -1 20 -1 21 -1 22 -1 23 -1 24 -1 25 -1 26 -1 27 -1 2
8 -1 29 -1 30 -1 31 -1 32 -1 33 -1 34 -1 35 -1 36 -1 37 -1 38 -1 39 -1 40 -1 41
-1 42 -1 43 -1 44 -1 45 -1 46 -1 47 -1 48 -1 49 -1 50 Press any key to continue
. . .

The return value -1 of tellg() indicates failure. Check that the file path is correct. Your output clearly indicates that the file cannot be opened. If a file cannot be opened, you shouldn't perform read/write operation on the file, or in this case stream.
EDIT
f1.open("prime2.txt",ios::binary);
Here the location of prime2.txt is relative. Since you changed compiler there is a good chance that the file cannot be found. Try with some absolute value first (like C:\myprograms\test\prime2.txt) and then figure out where to put prime2.txt for your program to get it by only specifying prim2.txt in open().

The first thing in your ouput is 'NOT OPEN'. If file open fails, don't expect anything else to work.
Check file is present in the dir where your program executes. Try with absolute path in the filename instead of relative.
It might be better to build this logic up step by step, testing as you go, instead of writing the whole thing and then trying to debug a pile of output from failing code.

Related

How to extract data from Minecraft .mca files

I would like to generate a map for my own world, so I wrote a program try to analyze data from files in C++.
According to this page, the region file begins with a 4KB head which tells the positions of each chunk.
I wrote a program, but it outputs the wrong stuff.
This is my program
#include<bits/stdc++.h>
#include<fstream>
using namespace std;
char DataRaw[4100];
uint8_t DataUnsigned8[4100];
struct F4K{int pos,sz,dfn;} _chunk[40][40];
int main()
{
ifstream file("first4K.sample",ios::binary|ios::in|ios::ate);
ifstream::pos_type n=file.tellg();
freopen("offset.out","w",stdout);
file.seekg(0);
file.read((char*)(&DataRaw),n);
DataRaw[n]='\0';
file.close();
for (int i=0;i<n;i++)
DataUnsigned8[i+1]=uint8_t(DataRaw[i]);
for (int i=0;i<32;i++)
{
for (int j=0;j<32;j++)
{
int id=4*((i&31)+(j&31)*32);
_chunk[i][j].pos=(DataUnsigned8[id+1]<<16)|(DataUnsigned8[id+2]<<8)|(DataUnsigned8[id+3]);
_chunk[i][j].sz=DataUnsigned8[id+4];
}
}
cout<<" X Z offset sz\n-------------------"<<endl;
for (int i=0;i<32;i++)
{
for (int j=0;j<32;j++)
cout<<setw(2)<<i<<setw(3)<<j<<setw(9)<<_chunk[i][j].pos<<setw(4)<<_chunk[i][j].sz<<endl;
}
return 0;
}
And it outputs this
X Z offset sz
-------------------
0 0 2098751 32
0 1 2098252 2
0 2 139296 73
0 3 2113312 32
0 4 286978 32
0 5 2099058 3
0 6 2098275 2
0 7 139271 65
...
31 25 7602464 32
31 26 2556192 1
31 27 2105407 32
31 28 6546821 168
31 29 10927590 179
31 30 15109023 35
31 31 15315359 230
I expect that the offset is sorted and begins with 8192,but it was totally wrong! Some addressed (for example X:31,Y:31) is even bigger than the file size (The size is only 8,048,640 Bytes)
May anyone tell me why?

How do can I get rid of the blank lines that are created c++?

Edit:
Thank you all for the quick and helpful replies. I got it working now. It was because I had to reset the counter.
I have come to ask for help as my professor is not giving me the help I need. I am new to c++ and I am trying to program a program that displays all the integers from 1 to 100 that are divisible by 6 or 7, but not both. and I have to display 5 numbers per row. I got it working except I have blank lines forming in certain areas. I don't know if it's because of how I set up the counter or what.
Here is what I got.
#include <iostream>
using namespace std;
int main()
{
int counter = 0; // Counter for creating new lines after 5 numbers
for (int numRange = 1; numRange <= 100; ++numRange) // Starts the loop of number 1 to 100
{
if (numRange % 6 == 0 || numRange % 7 == 0) // Makes the numbers divisible by 6 and 7
{
cout << numRange << " "; // Displays the output of the divisible numbers
counter++; // Starts the counter
}
if (counter % 5 == 0) // using the counter to create new lines after 5 numbers displayed
{
cout << endl; // Creates a new line
}
}
return 0;
}
This is what is outputted:
6 7 12 14 18
21 24 28 30 35
36 42 48 49 54
56 60 63 66 70
72 77 78 84 90
91 96 98
and this is what it's supposed to look like
6 7 12 14 18
21 24 28 30 35
36 48 49 54 56
60 63 66 70 72
77 78 90 91 96
98
The problem that you're seeing is due to the fact that you are checking for "5 outputs" on every loop, rather than only on ones where a number has been output! So, to fix this issue (there are others), put the counter % 5 == 0 test inside the preceding if block:
for (int numRange = 1; numRange <= 100; ++numRange) // Starts the loop of number 1 to 100
{
if (numRange % 6 == 0 || numRange % 7 == 0) // Makes the numbers divisible by 6 and 7
{
cout << numRange << " "; // Displays the output of the divisible numbers
counter++; // Increments the counter
if (counter % 5 == 0) // Only need this if we have done some output!
{
cout << endl; // Creates a new line
}
}
}
Another problem is that, in this requirement:
that are divisible by 6 or 7, but not both
your code doesn't check for the "but not both" part (but that's not the 'title' question, and I'm not going to do all your homework in one fell swoop).

Need help reading from a file until end of line

I'm working on a a project for my class where I have to use all four algorithms for the maximum subarray sub problem (cubic, quadratic, linear, and recursive). My problem is that I'm supposed to read the input from a file and I'm having trouble figuring out how to read until the end of a line, execute code with that data, and then move onto the next line. The input file looks like this:
2
-5 -10 -2 -4
2
-2 10 -5 -6
3
-10 -5 0 5 -20 20 -50
4
10 8 2 -20 -50 -100 -150
0
-1 -2 -3 -4 -5
1
-100 -200 0
4
200 500 -700 1000 2000 -5000 4 10
4
100 200
6
0 0 0 0 0 0 -10
5
-4 10 -3 200 500 -700 2
0
5 10 15 20 25 30 35
2
10 30 50 70 100
3
-15 16 23 -30 0 -2 13 8 6 0 -4 -15
12
9 8 23 -1 -23 -4 0 0 4 7 9 10 -23 68 1 -2 -3 -6 -19 10 5 1 1 2 4 3 -46 12 -100 78 -23 0 0 12 2 7
5
-1 -3 0 2 3 6 1 -5 -3 -2
now my issue is that I want to be able to read in a single number (the minimum subarray length) and then fill the array with the row of numbers below it, then execute all four algorithms using that data, then I want to move on to the next minimum subarray length and the next array of values below it, execute all four algorithms etc., and I want to be able to do this all in one go.
For example, I want to read 2 as the minimum subarray length, then use (-5,-10,-2,-4) as the array, execute all four algorithms, then use 2 as the minimum length, (-5,10,-5,-6) as the array, execute all four algorithms, and keep doing that until the end of the file.
Here is a quick possible solution that might help ("test.txt" contains your values...)
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
ifstream in("test.txt");
string str;
int value;
while (in)
{
vector<int> vec;
getline(in, str);
stringstream stream(str);
while (stream)
{
stream >> value;
vec.push_back(value);
}
vec.erase(vec.end()-1);
//Here the vec conntains all values of the current line
for (auto v : vec)
cout << v << " ";
cout << endl;
}
}

after msgget() , cout or printf are not working

After using msgget() system call to create a msgQ im not able to use cout or printf.
Below is my code trying to receive from a message Queue.
The "printf" at line 28 does not print anything. But it works fine if i add one more "cout" or "printf" statement(say at line 29).Please let me know for any flaws in my code.
1 #include<sys/errno.h>
2 #include<sys/wait.h>
3 #include<sys/ipc.h>
4 #include<stdio.h>
5 #include<iostream.h>
6 #include<sys/msg.h>
7 #include<sys/types.h>
8
9 struct messgQ
10 {
11 char text[1024];
12 long int mtype;
13 };
14
15
16 int main()
17 {
18 struct messgQ R;
19
20 R.mtype=1;
21
22 int qid=0;
23 qid=msgget((key_t)1234,0766|IPC_CREAT);
24 cout<<"\n 1 MsgQ created with id ="<<qid;
25
26 if( qid > 0 )
27 {
28 printf("\n MsgQ created with id =%d",qid);
29 }
30
31 int rc=0,run=1;
32 while( run )
33 {
34 memset(R.text,0x00,sizeof(R.text));
35 msgrcv(qid,&R,sizeof(R.text),1,0);
36 cout<<"\n Recvd:"<<R.text;
37 if( !strncmp(R.text,"bye",3) )
38 {
39 cout<<"\n Exiting";
40 run=0;
41 }
42 }
43 rc=msgctl(qid,IPC_RMID,NULL);
44 if (rc < 0)
45 perror(strerror(errno));
46 }
The msgget documentation says
RETURN VALUE
If successful, the return value will be the message queue identifier (a nonnegative integer), otherwise -1 with errno indicating the error.
So your check on line 26 is flawed, it should be:
if( qid >= 0 )
Regarding your output, stdout is normally line buffered when you print to a terminal. That means output isn't actually written out until you write a newline. So don't start your lines with a newline, but end with one instead.
printf(" MsgQ created with id =%d\n",qid);
cout<<"Recvd:"<<R.text << '\n';
cout<<"Exiting\n";
Alternatively, force the flushing by doing
cout.flush();
Or if you're using the C stdio functions such as printf, flush it with
fflush(stdout);

Tellg returning unexpected value

I have a function which reads lines from a file. But before reading it returns the address from where its going to read the next line.
my function is:
void print()
{
int j=0;
string a,b,c,d,e;
ifstream i("data.txt");
cout<<setw(15)<<left<<"Hash Value"<<setw(15)<<left<<"Employee Name"<<setw(15)<<left<<"Employee ID"<<setw(15)<<left<<"Salary"<<setw(15)<<left<<"Link"<<endl;
while(j<10)
{
j++;
cout<<i.tellg()<<endl;
i>>a>>b>>c>>d>>e;
cout<<setw(15)<<left<<a<<setw(15)<<left<<b<<setw(15)<<left<<c<<setw(15)<<left<<d<<setw(15)<<left<<e<<endl;
}
i.close();
}
The file it is reading from is data.txt:
0 --- 0 0 -1
1 --- 0 0 -1
2 --- 0 0 -1
3 --- 0 0 -1
4 --- 0 0 -1
5 --- 0 0 -1
6 --- 0 0 -1
7 --- 0 0 -1
8 --- 0 0 -1
9 --- 0 0 -1
And the output I am getting is:
Hash Value Employee Name Employee ID Salary Link
0
0 --- 0 0 -1
81
1 --- 0 0 -1
157
2 --- 0 0 -1
233
3 --- 0 0 -1
309
4 --- 0 0 -1
385
5 --- 0 0 -1
461
6 --- 0 0 -1
541
7 --- 0 0 -1
617
8 --- 0 0 -1
693
9 --- 0 0 -1
Every line is of length 76 characters. So everytime the address printed should increase by 76.
But i dont understand whats going on when the 2nd line is printed[hash value 1], and the 7th line is printed [hash value 6].
Can someone please help me with this?
A couple of things:
First and foremost, you're not reading line by line, so there
is no reason to assume that you advance the number of characters
in a line each time through the loop. If you want to read line
by line, use std::getline, and then extract the fields from
the line, either using std::istringstream or some other
method.
The result of tellg is not an integer, and when converted to
an integral type (not necessarily possible), there is no
guaranteed relationship with the number of bytes you have
extracted. On Unix machines, the results will correspond, and
under Windows if (and only if) the file has been opened in
binary mode. On other systems, there may be no visible
relationship what so ever. The only valid portable use of the
results of tellg is to pass it to a seekg later; anything
else depends on the implementation.
How do you know that each line contains exactly 76 characters?
Depending on how the file was produced, there might be a BOM at
the start (which would count as three characters if the file in
encoded in UTF8 and you are in "C" locale). And what about
trailing whitespace. Again, if your input is line oriented, you
should be reading lines, and then parsing them.
Finally, but perhaps the most important: you're using the
results of >> without verifying that the operator worked. In
your case, the output suggests that it did, but you can never be
sure without verifying.
Globally, your loop should look like:
std::string line;
while ( std::getline( i, line ) ) {
std::istringstream l( line );
std::string a;
std::string b;
std::string c;
std::string d;
std::string e;
l >> a >> b >> c >> d >> e >> std::ws;
if ( !l || l.get() != EOF ) {
// Format error in line...
} else {
// ...
}
}
Outputting tellg still won't tell you anything, but at least
you'll read the input correctly. (Outputting the length of
line might be useful in some cases.)