after msgget() , cout or printf are not working - c++

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

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

cin.ignore() enter twice to get one pause

Problem statement:
I am just learning the syntax for C++ and for some reason I have to enter cin.ignore(); twice in my script to get my program to pause once. Note that line 48 is commented out for troubleshooting purposes.
Code:
1 // Lab 3 Exercise 1
2 // Input Using cin >>
3 //
4 // Program by: Robert J
5
6 #include <iostream>
7 #include <cmath>
8 #include <string>
9 using namespace std;
10
11 // creating functions
12 float delta_miles(float end_mileage, float start_mileage){
13 return end_mileage - start_mileage;
14 };
15
16 float mileage(float end_mileage, float start_mileage, float travel_time){
17 return (end_mileage - start_mileage) / travel_time;
18 };
19
20 float mileconv(float miles){
21 // There are 1604 m in a mile
22 return miles * 1.604;
23 };
24
25 int main(){
26 // Variable definitions
27 float milestart, milesend, hours, total_miles, mph; // floatValue is of type float
28
29 printf("Enter the starting mileage (miles): " );
30 cin >> milestart;
31 printf("Enter the ending mileage (miles): " );
32 cin >> milesend;
33 printf("Enter the number of hours traveled (2.25 horus = 2 horus 15 minutes): " );
34 cin >> hours;
35
36 // Calculations
37 total_miles = delta_miles(milesend, milestart);
38 mph = mileage(milesend, milestart, hours);
39
40 // Output
41 printf("\n"); // seperator that is easy to find
42
43 printf("Total miles traveled:\t%f\n", total_miles);
44 printf("Miles per Hour: \t%f\n", mph);
45 printf("Total kilometers:\t%f\n", mileconv(total_miles) );
46 printf("Kilometers/Hour:\t%f\n", mileconv(mph) );
47
48 // cin.ignore();
49 cin.ignore();
50 // Exit code:
51 return 0;
52 }
Attempted solutions:
I don't want to use the system("pause"); function like my professor does because am using a Unix system and would have to do system("read"); at which point the grader would not see my output.
I have also tried removing the \n from the last printf to no avail.
Questions:
Does anyone see what am doing wrong here?
Thanks in advance all.
It is because of this line of code:
cin >> hours;
This reads the number of hours, but not the enter you pressed after it. So your first cin.ignore() call ignores that enter key. Only your second one causes a pause.
If you want to read lines, use a function that reads lines. Don't use a function that reads a number and expect it to read a line.
David Schwartz answered your why but a solution to your problem, pausing for at the end of the program, can be solved by this (which is what I always do in situations like this)
cin.get();
get() retrieves a character from the stream but can only do so when it's flushed by the enter key

getline item returning empty variable

I'm trying to read in a text file and separate the lines into cities and locations. Everything is working for most of the lines, but for I'm getting a
terminate called after throwing and instance of 'std::invalid_argument'
what(): stoi
Aborted (core dumped)
After some investigating, I figured out that it's hanging up on the 2 in Lima, Peru. I could be that the getline function is giving it something it can't handle, but there are instances of exactly the same number in exactly the same position earlier in the document.
...
Hobart, Tasmania: 42 52 S 147 19 E
Hong Kong, China: 22 20 N 114 11 E
Iquique, Chile: 20 10 S 70 7 W
Irkutsk, Russia: 52 30 N 104 20 E
Jakarta, Indonesia: 6 16 S 106 48 E
Johannesburg, South Africa: 26 12 S 28 4 E
Kingston, Jamaica: 17 59 N 76 49 W
Kinshasa, Congo: 4 18 S 15 17 E
Kuala Lumpur, Malaysia: 3 8 N 101 42 E
La Paz, Bolivia: 16 27 S 68 22 W
Leeds, England: 53 45 N 1 30 W
Lima, Peru: 12 0 S 77 2 W
Lisbon, Portugal: 38 44 N 9 9 W
Liverpool, England: 53 25 N 3 0 W
London, England: 51 32 N 0 5 W
Lyons, France: 45 45 N 4 50 E
Madrid, Spain: 40 26 N 3 42 W
...
Here's the section of the code that I think is throwing the error. I can post more if needed, but I think this is the relevant part.
while(is_more_stuff_there(file_to_read))
{
getline(file_to_read, line);
// parse city
index = line.find(':');
city_name = line.substr(0 , line.find(':'));
istringstream position_stream(line.substr(index + 2 , line.find(':')));
cout << city_name << endl;
// initialize an array to store the parsed values from the position_string
string position_array[6];
string item;
int i = 0;
// fill the array, split by spaces
while (getline(position_stream, item, ' '))
{
position_array[i] = item;
i++;
cout << item << endl;
}
cout << position_array[4] << endl;
// initialize the position variables
lat_min = stoi(position_array[0]);
lat_sec = stoi(position_array[1]);
long_min = stoi(position_array[3]);
long_sec = stoi(position_array[4]);
// determine positivity of lats and longs
if (position_array[2] == "S") { lat_min *= -1; lat_sec *= -1; }
if (position_array[5] == "E") { long_min *= -1; long_sec *= -1; }
vertex city(city_name, lat_min, lat_sec, long_min, long_sec);
g.add_vertex(city);
}
There is a non-printing character in your text file, just before the 2 in question. you could find what exactly it is by using od -x (if you're on a unix box). Or simply remove the line and retype it.
One problem that I can see with your code is that the second parameter passed to the substr function seems wrong. It should be the length of the sub-string to extract but that need not coincide with the index of the :. You can simply leave the second parameter out to get the entire remaining sub-string.
std::istringstream position_stream(line.substr(index + 2));
If you only add 1 to index, your code will also parse inputs where there is no space after the colon.
Although not fundamentally wrong, the code could be simplified by using the C++ style extraction operators. You can read in your four fields directly from the stream.
int lat_min, lat_sec, long_min, long_sec;
std::string ns, we;
position_stream >> lat_min >> lat_sec >> ns >> long_min >> long_sec >> we;
Then continue processing them with whatever logic is required.

istream not working in DEV 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.