How to calculate the average? - c++

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

Related

How to print table of 12 using recursion, I want it upto 10 but on running it turns out to be upto 12

I was trying to create a program to print table of 12 using recursion as I wrote a simple program for this I did get table, but table was instead upto 144 (12times12=144) instead of 120(12times10=120) I am sharing my code and output with you guys I was writing code in C++
//we will print table of 12 using concept of recursion
//a table of 12 is like this
//12 24 36 48 60 72 84 96 108 120
#include<iostream>
using namespace std;
void table(int n)
{
if(n==1)
{
cout<<12<<"\n";
return;
}
table(n-1);
cout<<n*12<<"\n";
}
int main(void)
{
table(12);
}
and now here is out put of this program
12
24
36
48
60
72
84
96
108
120
132
144
please help me what I'm missing here I am positive that adding some condition will help I tried one adding if(n==12) { return;} but it prevents does nothing as in the end it is return n*12

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

read file line by line and store different variables

My text file look like this:
1 52 Hayden Smith 18:16 15 M Berlin
2 54 Mark Puleo 18:25 15 M Berlin
3 97 Peter Warrington 18:26 29 M New haven
4 305 Matt Kasprzak 18:53 33 M Falls Church
5 272 Kevin Solar 19:17 16 M Sterling
6 394 Daniel Sullivan 19:35 26 M Sterling
7 42 Kevan DuPont 19:58 18 M Boylston
8 306 Chris Goethert 20:00 43 M Falls Church
9 262 James Sullivan 20:12 28 M Sterling
10 348 Bill Gaudere 20:17 54 M Hudson
11 13 Travis Wheeler 20:23 31 M Clinton
12 69 Eric Anderson 20:34 54 M Clinton
13 341 Alex Teixeira 20:46 0 M Clinton
14 112 James Long 20:50 38 M 0
15 279 Nate Richards 21:31 17 M Berlin
......................................................
There are eight columns, separated by 'tabs', except the first name and last name is separated by a space.
I must have eight different types of variables.
int a;
int b;
string c;
string d;
string e;
int f;
char g;
string h;
I need to read the file line by line and cout every line's a, b, c, d, e, f.
I also need those variables for later use.
So, I tried this:
std::ifstream infile("text.txt");
int a;
int b;
string c;
string d;
string e;
int f;
char g;
string h;
while(infile>>a>>b>>c>>d>>e>>f>>g>>h)
{
cout <<"C is: "<<c<<endl; // just to see if the loop is working.
}
I don't need arrays and vectors to store those variables, I have a linked structure. Right now, I just need a way to read the file and store those strings and integers into variables.
But it's not working, lol. Don't know why. I also thought about using getline, something like this:
while(getline(infield, s)):
But, isn't this essentially just giving me one big fat line, with all strings and integers smashed together.
Your approach works exactly as you want it to when testing it on my machine, except for the fact that it will stop at the third entry:
3 97 Peter Warrington 18:26 29 M New haven
This is because of the space in New haven, which will fail the while condition as it fails to be copied into the integer field, a on the next iteration. If you want to keep this structure, perhaps put underscores in place of spaces. Otherwise move to parsing it line by line, perhaps with the std::regex library.
For example, changing the location string to be seperated by underscores instead of spaces results in finding all 15 entries. To change the underscores back into spaces we can use std::replace, so the body of your while loop would look lile:
std::cout <<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e<<" "<<f<<" "<<g<<" ";
std::replace( h.begin(), h.end(), '_', ' ' );
std::cout<<h<<"\n";
(make sure to include algorithm)
We now have all our entires printed!
To directly answer your original question, I'm guessing the file doesn't exist.
std::ifstream infile("text.txt");
if(!infile.is_open()) {
std::cout<<"Couldn't find file";
return 0;
}
// ..

Search for a string in a binary file with C++

I wrote a short program to search for a string in a binary file. The file consists of text and Base64 content. If I test it with an ASCII text file, it works. If I try it with a binary file, it does not match anything.
So can you tell me:
Where's my fault?
What is the best (computational) way to search for a string in a binary file?
UPDATE: A direct string comparison works, so the problem has to be somewhere in the regex definition.
Code
19 #include<iostream>
20 #include<fstream>
21 #include<regex>
22 #include<string>
23
24 using namespace std;
25
26 int main(int argc, char* argv[]) {
27 if (argc != 2){
28 cout << "Error message";
29 }
30
31 regex type_response ("(TEST: )(.*)");
32 regex target_value ("(VALUE: )(.*)");
33 regex target_version ("(NAME: )(.*)");
34
35 ifstream infile(argv[1], ios::binary);
36
37 if (infile.is_open()){
38 string line;
39 while (getline(infile, line)){
40 if (regex_match(line ,target_version)){
41 cout << line;
42 }
43 };
44 infile.close();
45
46 return 0;
47 }
48
49 else {
50 cout << "Could not open file.\n";
51 return 1;
52 };
53 };
An ASCII file is a binary file that stores ASCII codes and an ASCII code is a 7-bit code stored in a byte. While a binary file has no such restrictions and any of the 8 bits can be used in any byte of a binary file.
In ASCII file the highest bit of each byte is not used and it means the highest bit is treated as 0. While in binary file, it maybe 0 or 1. So there are difference. You can check the hex detail of the binary file using tools like HxD.
The problem was a malformed regex, the rest of the code works.

I can't figure out what is wrong with this randomizer

I'm new to C++. Only been programming for 2 days so this will probably look messy. The purpose of the program is that you enter a word, and then the program randomizes the placement of the letters in the word.
I have three questions.
Why, if the same string is entered twice, will the same "random" numbers be output?
How can I make sure no random number is picked twice. I already tried an IF statement nested inside the FOR statement but it just made things worse.
What will make this work?
The code:
#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <stdio.h>
#include <string.h>
using namespace std;
int main () {
cout << "Enter word to be randomized: ";
char rstring[30];
char rstring2[30];
cin >> rstring;
strcpy(rstring2, rstring);
int length;
length = strlen(rstring);
int max=length;
int min=0;
int randint;
for (int rdm=0; rdm<length; rdm++) {
randint=rand()%(max-min)+min;
cout << rstring[rdm]; //This is temporary. Just a visualization of what I'm doing.
cout << randint << endl; //Temporary as well.
rstring2[randint]=rstring[rdm];
}
cout << endl << rstring2 << endl;
return 0;
}
If you compile and run this you will notice that the same random numbers are output for the same text. Like "hello" outputs 24330. Why is this random generator generating nonrandom numbers?
You need to seed your random number generator to get different results with each run. Otherwise, (as you have noticed) you will get the same random numbers with each run.
Put this at the start of the program:
srand(time(NULL));
This will seed the random number generator with time - which will likely be different between runs.
Note that you'll also need #include <time.h> to access the time() function.
You're not using a random number generator. You're calling rand(), a pseudo-random number generator, which produces sequences of numbers that share many properties with truly random numbers (e.g. mean, standard deviation, frequency spectrum will all be correct).
To get a different sequence, you have to initialize the seed using srand(). The usual way to do this is:
srand(time(NULL));
Furthermore, a sequence that guarantees the same number cannot be picked twice, is no longer a sequence of i.i.d. (independent identically distributed) random numbers. (the sequence is highly dependent) Most uses of random numbers rely on the i.i.d. property, so the library-provided functions are i.i.d. However, filtering out repeats yourself is not especially hard.
If you don't want to change the cardinality (number of occurrences) of each character in the string, the easiest thing to do is not pick one character after the other, but randomly pick a pair to swap. By only swapping, you change order but not cardinality.
You always get the same random numbers because you don't seed this random number generator. Call srand() before your first call to rand(). Examples: http://www.cplusplus.com/reference/clibrary/cstdlib/srand/
The random number generated by rand() is pseudo-random. C++ rand() documentation says following
rand() Returns a pseudo-random integral number in the range 0 to RAND_MAX.
This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using srand.
Because (at least on Linux) pseudo-random number generators are seeded with the same value (to make programs more deterministic, so two consecutive identical runs will give the same answers).
You could seed your PRNG with a different value (the time, the pid, whatever). On Linux you could also consider reading the /dev/urandom (or much rarely, even the /dev/random) pseudo file - often to seed your PRNG.
The code below remembers what random number that was previously picked.
It generates a unique random number only once.
It stores results in an array, so that when rand() produces a number
that already exists, it does not store that number in the array.
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
int size=100;
int random_once[100];
srand(time(0));
cout<<"generating unique random numbers between [0 and "<<size <<"] only once \n\n";
for (int i=0;i<size;i++) // generate random numbers
{
random_once[i]=rand() % size;
//if number already exists, dont store that number in the array
for(int j=0;j<i;j++) if (random_once[j]==random_once[i]) i--;
}
for ( i=0;i<size;i++) cout<<" "<<random_once[i]<<"\t";
cout<<"\n";
return 0;
}
Output :
generating unique random numbers between [0 and 100] only once
50 80 99 16 11 56 48 36 21 34
90 87 33 85 96 77 63 5 60 52
59 4 84 30 7 95 25 1 45 49
10 43 44 82 22 74 32 68 70 86
57 24 39 51 83 2 81 71 42 94
78 72 41 73 92 35 76 9 3 58
19 40 37 67 31 23 55 69 8 17
64 46 93 27 28 91 26 65 47 14
15 75 79 88 62 97 54 12 18 89
13 38 61 0 29 66 53 6 98 20
Press any key to continue