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
Related
Problem Description
Basically, Inside of my "Roster.h" header file, i have an array of "Student" objects from the student class ( which includes the functions changeScore, SetID, setTotal,setLetterGrade). In the function that will be attached below, it is only reading the first line of data and then quitting at the while condition. I've been staring at this issue for hours now and could use a second (or third) pair of eyes. Any criticism is also appreciated, as i know that i am not the most effective programmer.It should be noted that "m_studentnum",is private data that is initialized to 0 in the constructor. Thanks in advance!
Code
void Roster::readStudentRecord(string file)
{
ifstream in;
string studentID;
string line;
int ola, cla, quiz, homework, exam, bonus, total, final = 0;
in.open(file.c_str());
getline(in, line);
while (in >> studentID) {
in >> cla >> ola >> quiz >> homework >> exam >> bonus >> total >> final;
m_students[m_studentNum].Student::setID(studentID);
m_students[m_studentNum].Student::changeScore(Student::CLA, cla);
m_students[m_studentNum].Student::changeScore(Student::OLA, ola);
m_students[m_studentNum].Student::changeScore(Student::QUIZ, quiz);
m_students[m_studentNum].Student::changeScore(Student::HOMEWORK, homework);
m_students[m_studentNum].Student::changeScore(Student::EXAM, exam);
m_students[m_studentNum].Student::changeScore(Student::BONUS, bonus);
total = cla + ola + quiz + homework + exam + bonus;
m_students[m_studentNum].Student::setTotal(total);
if (total >= 90) {
m_students[m_studentNum].Student::setLetterGrade('A');
}
else if (total >= 80 && total < 90) {
m_students[m_studentNum].Student::setLetterGrade('B');
}
else if (total >= 70 && total < 80) {
m_students[m_studentNum].Student::setLetterGrade('C');
}
else if (total >= 60 && total < 70) {
m_students[m_studentNum].Student::setLetterGrade('D');
}
else {
m_students[m_studentNum].Student::setLetterGrade('F');
}
m_studentNum++;
}
}
Data file
-note that i am doing a getline to get read in the headline for the data column's
ID CLA OLA Quiz Homework Exam Bonus Total FinalGrade
c088801 10 15 4 15 56 5
c088802 9 12 2 11 46 2
c088803 8 10 3 12 50 1
c088804 5 5 3 10 53 3
c088805 3 11 1 10 45 0
c088806 8 14 2 11 40 -1
c088807 4 12 2 12 48 -2
c088808 10 10 3 11 36 0
c088809 8 8 3 11 39 0
c088810 6 9 4 9 47 3
c088811 8 7 3 13 41 3
c088812 4 11 3 11 37 1
The "Total" and "FinalGrade" columns are empty, and you unconditionally try to read them.
When you attempt to do that, the input will contain the "ID" from the next line, and as that is not an integer, leading to the failbit flag being set for the stream which causes the loop condition to be false and the loop to end.
One possible solution is to read the while line into a string, put that string into an std::istringstream object, and read the non-empty columns as you do now. Then try to read the possibly empty columns from the input string stream.
Another solution, if those columns are supposed to be empty, is to simply not read them.
I was asked to calculate the average of marks for 10 students.
First, I was able to read and retrieve the data from data.txt file which looks like this:
No. Name Test1 Test2 Test3
1 Ahmad 58 97 83
2 Dollah 78 76 70
3 Ramesh 85 75 84
4 Maimunah 87 45 74
5 Robert 74 68 97
6 Kumar 77 73 45
7 Intan 56 23 27
8 Ping 74 58 18
9 Idayu 47 98 95
10 Roslan 79 98 78
Then I have to calculate the average for each student and determine the grades.
Here are what I've done so far.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
ifstream inFile1;
string temp;
int line=0;
inFile1.open("data.txt");
if(inFile1.fail())
{
cout << "File cannot be opened" << endl;
exit(1);
}
while(getline(inFile1, temp))
{
line++;
}
inFile1.close();
return 0;
}
This program should at least consists two prototype function: average() and grade().
This is where I got stuck.
You can check the answers here: find average salaries from file in c++.
Basically when you iterate through the file lines you should split the temp string into tokens you are interested in. How? An option would be to use getline with the delimeter ' ' or look into the std::noskipws stream manipulator or simply use operator>> to read from the file - depends on the details of your requirements.
If I correctly understand your case, I'd go with the operator>> to get the name of the student and then read using getline(inFile, gradesText) to read until end of line to get all grades for the current student.
Then I'd use a separate function to split the strings into a vector of grades. How to do the splitting you can check in Split a string in C++?. This way you could prepare a function like vector<int> split(const string& line, char delim = ' '). Within the implementation you should probably use std::stoi for the string-to-int conversion.
Afterwards, when you already have a proper collection you can calculate the mean from it with:
const double sum = std::accumulate(grades.begin(), grades.end(), 0.0);
const double gradesMean = sum / grades.size();
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);
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.
This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 8 years ago.
thanks for looking at this in advance.
I can get my code to compile correctly and whatnot, but when running I get stuck in an infinite seeming loop and I have to exit out manually every time. I am new to reading in data from files and I think that is probably my error but any help looking at my code would be appreciated.
In the interest of not submitting some giant file, I'm only going to submit my main function because I assume the error is in there, I'm just not sure of where.
4 #include "class.h"
5 #include <fstream>
6 using namespace std;
7
8
9 int main()
10 {
11 ifstream external; //declaring input stream for my external file
12 //external.open("external.txt"); //telling the compiler what the source of my external file is called
13 //external.close();
14
15 char time[4], course[4], section[3]; //places to store read in values
16 char dept_name[20];
17
18 table hash_table; //instance of my class
19
20 while(!external.eof()) //while it is not the end of the file
21 {
22 external.open("external.txt"); //opens file from location
23
24 external.getline(dept_name, 20); //grabs the info to be input
25 external.getline(time, 4);
26 external.getline(course, 4);
27 external.getline(section, 3);
28
29 external.close(); //closes file until new one must begin
30
31 cin.ignore(5, '\n'); //ignores five characters until next course
32 hash_table.insert(dept_name, course, section, time); //inserts to table
33 }
34 hash_table.display_all();
35 }
Don't open the file for every entry you read. Among other things, opening the file for each entry means you always start reading at the start of the file.
Change this:
20 while(!external.eof()) //while it is not the end of the file
21 {
22 external.open("external.txt"); //opens file from location
23
24 external.getline(dept_name, 20); //grabs the info to be input
25 external.getline(time, 4);
26 external.getline(course, 4);
27 external.getline(section, 3);
28
29 external.close(); //closes file until new one must begin
30
31 cin.ignore(5, '\n'); //ignores five characters until next course
32 hash_table.insert(dept_name, course, section, time); //inserts to table
33 }
to this:
20 external.open("external.txt"); //opens file from location
21 while(!external.eof()) //while it is not the end of the file
22 {
23
24 external.getline(dept_name, 20); //grabs the info to be input
25 external.getline(time, 4);
26 external.getline(course, 4);
27 external.getline(section, 3);
28
29
30 cin.ignore(5, '\n'); //ignores five characters until next course
31 hash_table.insert(dept_name, course, section, time); //inserts to table
32 }
33 external.close(); //closes file