How to extract data from Minecraft .mca files - c++

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?

Related

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).

Why does this new [ ] and delete [ ] implementation break down for integers > 12?

The problem: I need to print the Pascal triangle for any (unsigned int) input passed as a command line argument. All the values must be stored in a LINEAR array and elements must only be manipulated as dereferenced pointers. Following this, the array elements must printed as a lower triangular matrix and subsequently deleted. My implementation functions perfectly for input ranging from 0 to 12 but produces spurious results for higher values.
I tried two different implementations.
Declare a pointer to an array of size (n+1)*(n+2)/2 (which is the number of elements in the triangle for input 'n'). Assign/print variables within a nested loop. Delete the pointer once both loops have been executed.
Run a nested loop, 0 <= i <= n, and 0 <= j <= i. Declare a pointer to an array of size (i+1) in the outer loop. Assign/print elements in the inner loop. Delete the pointer once the inner loop has been executed.
// VERSION 1
unsigned N = (n+1)*(n+2)/2;
unsigned* elements = new unsigned[N];
for(i = 0; i <= n; i++) {
for(j = 0; j <= i; j++) {
*(elements + j+(i*i+i)/2) = fact(i) / (fact(j) * fact(i-j));
// print statement
}
cout << endl;
}
delete [] elements;
// VERSION 2
for(i = 0; i <= n; i++) {
unsigned* elements = new unsigned[i+1];
for(j = 0; j <= i; j++) {
*(elements + j) = fact(i) / (fact(j) * fact(i-j));
// print statement
}
delete [] elements;
cout << endl;
}
Both these versions were tried separately on Xcode. In both cases, the triangle printed correctly until the 12th layer, i.e. n=12, but generated incorrect results for higher values.
0 | 1
1 | 1 1
2 | 1 2 1
3 | 1 3 3 1
4 | 1 4 6 4 1
5 | 1 5 10 10 5 1
6 | 1 6 15 20 15 6 1
7 | 1 7 21 35 35 21 7 1
8 | 1 8 28 56 70 56 28 8 1
9 | 1 9 36 84 126 126 84 36 9 1
10 | 1 10 45 120 210 252 210 120 45 10 1
11 | 1 11 55 165 330 462 462 330 165 55 11 1
12 | 1 12 66 220 495 792 924 792 495 220 66 12 1
13 | 1 4 24 88 221 399 532 532 399 221 88 24 4 1
14 | 1 0 1 5 14 29 44 50 44 29 14 5 1 0 1
15 | 1 1 0 0 2 4 7 9 9 7 4 2 0 0 1 1
16 | 1 0 0 0 0 4 0 1 1 1 0 4 0 0 0 0 1
The debugger, to the extent that I can use it, produced no error messages.
What is happening and how do I fix it?
fact(i) overflows really fast. I haven't checked the numbers, but I'm pretty sure that's what's happening.
Instead, use the fact that a number in Pascal's triangle is the sum of the two numbers above it.
Wikipedia has a nice animation for this.
When i is 13, fact(i) is 6227020800, which is too big to fit in a 32-bit unsigned integer, so integer overflow occurs.

Decimate vector in eigen

I have a float array Eigen::ArrayXf which I need to decimate (i.e. pick 1 out of f.i. 8 samples).
Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0, Eigen::InnerStride<8> >(signal.data(), length, 1).eval();
which works, with a caveat: I need to know how long length is, and it can be specified too long, leading to runtime errors.
Q: is there a way to decimate all that is possible, so that resultant length is == signal.size() / 8 ?
Two things. You are using the c'tor for mapping a matrix:
Map (
PointerArgType dataPtr,
Index nbRows,
Index nbCols,
const StrideType & a_stride = StrideType()
)
Constructor in the dynamic-size matrix case.
Parameters
dataPtr pointer to the array to map
nbRows the number of rows of the matrix expression
nbCols the number of columns of the matrix expression
a_stride optional Stride object, passing the strides.
I think you want the c'tor for a vector:
Map ( PointerArgType dataPtr,
Index a_size,
const StrideType & a_stride = StrideType()
)
Constructor in the dynamic-size vector case.
Parameters
dataPtr pointer to the array to map
a_size the size of the vector expression
a_stride optional Stride object, passing the strides.
The second thing is that you want length == signal.size())/8. Is that always a whole integer, or are you rounding up? If the data is 16 in length and you want the positions [0] and [8], then use 1+(signal.size()-1)/8 as the length parameter:
Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0, Eigen::InnerStride<8> >(signal.data(), 1+((signal.size()-1)/8) ).eval();
For example:
#include <Eigen/Core>
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
Eigen::VectorXf signal;
signal.setLinSpaced(64, 0.0, 63.);
cout << "Original signal:" << endl << signal.transpose() << endl;
Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0,
Eigen::InnerStride<8> >(signal.data(), 1+((signal.size()-1)/8)).eval();
cout << endl << "Decimated:" << endl << decimatedSignal.transpose() << endl;
return 0;
}
outputs
Original signal:
0 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
Decimated:
0 8 16 24 32 40 48 56
which I think is exactly what you want.

Using threads to sort two halves of an array, but only second half is being sorted

I wrote a quick program to sort two halves of one array, when i test the sort it works fine with one array, however when I split the array into two and pass a half to each thread for sorting, when they're done and I print the array, only the second half looks sorted. What am I doing wrong? Below are my sorting function and main.
void *sort(void *object){
struct array_struct *structure;
structure = (struct array_struct *) object;
int *array = structure->partition;
int size = structure->size;
qsort(array, size, sizeof(int), cmpfunc);
printf("Sorted %d elements.\n", size);
}
and this is my main, assume all includes are fine, and compilation is fine also, this is not all of my code, just the parts pertaining to my problem.
int main(int argc, char const *argv[]){
int segments = 2;
pthread_t threads[segments];
int i, *numbers; //iterator i, and pointer to int array 'numbers'
numbers = randomArray(); //return an array of size 50 filled with random ints
for(i = 0; i < segments; i++){
struct array_struct array;//struct to pass as argument on thread creation
int *partition = numbers + (i * (50/segments));//obtain the first index of partition
array.partition = partition; //when i = 0 partition is 0 through 24, when i = 1 partition is 25 through 49
array.size = 50/segments; //25
pthread_create(&threads[i], NULL, sort, (void *) &array);
}
for(i = 0; i < segments; i++){
pthread_join(threads[i], NULL);
}
for(i = 0; i < 50; i++){
printf("%d\n", numbers[i]);
}
pthread_exit(NULL);
}
and here is my output if it helps:
Sorted 25 elements.
Sorted 25 elements.
19
16
14
16
20
6
17
13
8
39
18
0
26
46
45
17
7
46
45
29
15
38
43
19
17
0
2
4
7
12
12
12
14
16
17
20
22
22
23
26
29
30
32
33
37
38
38
43
43
46
You are passing an argument to your first thread, array, and then immediately overwriting the contents of that struct with the arguments to the second thread. Both threads will therefore see the arguments for the second thread.
What you should do is have two separate arguments. For example make array an array of 2 structs and pass &array[0] to the first thread and &array[1] to the second thread.
Also, it is dangerous to declare array in the scope of the for loop. Once the for loop ends, that variable is out of scope and your threads may read into a dead variable. You should declare array at the function level so that it remains alive for the threads to access it.

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);