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;
}
// ..
Related
So I'm trying to run this sim program for a class that makes us build a Bet class using sets.
Here's the class definition:
class Bet2{
private:
set<int> mainNumbers;
set<int> luckyNumbers;
public:
Bet2();
void show() const;
set<int> getMainNumbers();
set<int> getLuckyNumbers();
};
So I decided to use the random lib, since the rand() function that they gave us in class spat out the same values when creating a bunch of Bet2 objects at once, for the sim.
However, for some reason, it's not spitting out the number of values it's supposed to. Sometimes it spits out 4 main numbers (instead of 5), or just 1 lucky number (instead of 2)
Here's the code for the constructor:
Bet2::Bet2() {
random_device rd;
uniform_int_distribution<int> main(1, 50);
for (int i = 0; i < 5; i++)
mainNumbers.insert(main(rd));
uniform_int_distribution<int> star(1, 12);
for (int i = 0; i < 2; i++)
luckyNumbers.insert(star(rd));
}
I ran a few tests using the uniform_int_distribution and the random_device, in the main fucntion, and it ran without any problem. For some reason it eats up values when i initialize a Bet2 vector for my sim:
Main Numbers: 11 23 27 32 36
Star Numbers: 3 11
Main Numbers: 4 18 22 27 28
Star Numbers: 9 11
Main Numbers: 3 5 25 43 <-
Star Numbers: 1 <-
Main Numbers: 40 42 43 46 50
Star Numbers: 2 7
Main Numbers: 7 10 14 27 45
Star Numbers: 9 10
Main Numbers: 11 15 21 24 35
Star Numbers: 1 11
Main Numbers: 3 25 29 45 50
Star Numbers: 3 7
Main Numbers: 11 15 23 25 37
Star Numbers: 1 6
Main Numbers: 7 8 26 31 43
Star Numbers: 6 9
Main Numbers: 15 27 36 38 39
Star Numbers: 2 8
Tried to figure out of uniform_int_distribution can not generate a value, but didnt't find anything online.
Thanks in advance!
std::set can store only up to 1 copy of a given value.
The lack of numbers should be because the random numbers happened to become the same as the numbers that were previously seen.
If you want to store multiples of the same value, you should use std::multiset instead.
If you want to generate a unique set of defined number of values, it may be better to first generate a std::vector of candidate values, and then use std::sample() for that.
Assume that the file SCHOOLS.DAT is created
with the help of objects of class SCHOOLS, which is defined below:
class SCHOOLS
class SCHOOLS
{
int SCode; // School Code
char SName[20]; // School Name
int NOT; // Number of Teachers in the school
public:
void Display()
{cout<<SCode<<"#"<<SName<<"#"<<NOT<<endl;}
int RNOT(){return NOT;}
};
Question
Find the output of the following C++ code considering that the binary file
SCHOOLS.DAT exists on the hard disk with the following records of 10 schools of
the class SCHOOLS as declared in the previous .
SCode SName NOT
1001 Brains School 100
1003 Child Life School 115
1002 Care Share School 300
1006 Educate for Life School 50
1005 Guru Shishya Sadan 195
1004 Holy Education School 140
1010 Rahmat E Talim School 95
1008 Innovate Excel School 300
1011 Premier Education School 200
1012 Uplifted Minds School 100
void main()
{
fstream SFIN;
SFIN.open("SCHOOLS.DAT",ios::binary|ios::in);
SCHOOLS S;
SFIN.seekg(5*sizeof(S));
SFIN.read((char*)&S, sizeof(S));
S.Display();
cout<<"Record :"<<SFIN.tellg()/sizeof(S) + 1<<endl;
SFIN.close();
}
Output
1004#Holy Education School#140
Record :7
My Question How did Record is 7 and not 6.
My approach as the value of S will be 24 . Got it after adding the 2 byte of int Scode, 2 bytes of int NOT, 20 bytes of char SName[20].
so value of sizeof(S) will be 24 and value of SFIN.tellg will be 120 dividing them will give us 5 and then we have to add 1. So it will be 6 right?
You don't even need to think about the actual value of sizeof(S); just treat it as a constant K.
You initially seek to the position 5*K. Then you read K bytes from the file, leaving you at the position 6*K. That means the expression SFIN.tellg()/sizeof(S) + 1 is equivilent to 6*K/K + 1. K/K is equal to 1 for any K, so that further simplifies to 6*1 + 1, which equals 7.
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();
I've been racking my brain trying to get this information from a text doc into a few different arrays. The number before each name in the txt doc is the identification number, I want to put all these into a single double array. Then put every name into a single string array. Then finally put the numbers after each name into a double 2d array with 50 rows (one for each name) and 7 columns (for the seven scores/numbers for each client). I'm not asking for anyone to do my homework for me, I just need some info on how to get started.
using namespace std;
int main() { ifstream file("client_info.txt");
string txtArray[450];
for (int i = 0; i < 450; ++i)
{
file >> txtArray[i];
}
I thought maybe I'd put all of the text into a string array then split that array into several other arrays, but realized it would be difficult to use strings, since I need the numbers to be doubles for later when I'm finding the average of the clients scores.
Here is the txt doc:
93 SMITH 739.15 634.36 257.02 639.32 376.75 360.56 666.96 81 JOHNSON 888.08 975.86 672.78 176.35 114.58 511.24 502.56 50 WILLIAMS 222.27 171.83 232.83 609.79 726.69 444.89 520.63 32 JONES 343.13 687.73 931.93 72.36 183.93 486.3 90.09 68 BROWN 623.39 968.13 67.59 528.93 703.95 329.02 875.95 24 DAVIS 97.48 296.61 568.49 990.18 448.36 567.52 179.42 21 MILLER 147.68 38.87 64.78 463.19 172.39 914.68 827.42 90 WILSON 687.7 595.19 930.52 77.27 877.45 774.44 599.83 29 MOORE 739.33 402 825.29 859.63 937.14 405.2 89.22 12 TAYLOR 976.11 531.4 731.45 815.16 518.26 858.86 832.34 31 ANDERSON 133.12 355.22 517.53 926.54 552.05 932.52 745.75 89 THOMAS 217.72 266.14 622.99 541.35 618.49 268.9 243.63 87 JACKSON 352.81 772.31 109.43 139.14 430.43 625.92 207.79 46 WHITE 650.79 367.65 915.68 848.85 912.44 603.15 704.01 75 HARRIS 708.38 70.53 34.45 409.82 288.28 735.06 140.9 85 MARTIN 701.73 643.16 766.3 198.92 805.86 802.39 239.76 67 THOMPSON 993.9 274.75 72.87 928.41 208.81 260.42 5.56 52 GARCIA 871.48 646.48 914.77 98.61 724.86 680.7 363.15 60 MARTINEZ 293.38 448.24 985.08 135.2 277.77 705.58 567.81 69 ROBINSON 914.18 688.95 112.81 270.18 950.27 607.49 915.75 76 CLARK 956.12 110.6 820.53 140.97 906.2 529.52 75.24 82 RODRIGUEZ 224.88 324.32 672.74 502.27 768.99 116.42 880.86 39 LEWIS 805.89 274.54 211.14 82.04 804.41 259.69 408.08 48 LEE 80.06 381.7 975.29 448.33 578.49 548.19 818.85 26 WALKER 657.74 0.74 741.06 533.84 887.36 38.35 619.17 55 HALL 266.9 46.42 825.89 986.01 146.96 349.07 386.64 100 ALLEN 293.22 423.57 150.53 519.25 16.96 65.54 688.44 11 YOUNG 870.69 192.46 82.19 92.46 971.38 156.49 16.48 57 HERNANDEZ 145.33 123.45 860.78 521.86 739.9 138.88 169.33 96 KING 411.31 340.93 447.04 14.26 744.1 425.83 57.87 4 WRIGHT 503.48 488.13 603.12 198.14 425.51 216.28 49.75 64 LOPEZ 296.99 744.89 270.49 138.19 897.06 374.89 831.66 62 HILL 910.95 676.68 442.98 961.03 567.6 739.49 225.26 37 SCOTT 970.31 468.48 788.85 903.66 897.93 124.04 983.01 34 GREEN 260.42 714.42 496.13 492.39 170.17 999.36 890.8 51 ADAMS 212.36 115.84 308.57 741.29 780.3 193.71 423.82 40 BAKER 316.91 671.36 398.53 190.99 424.34 457.68 584.16 47 GONZALEZ 947.9 348.88 299.11 71.82 727.49 480.59 891.51 3 NELSON 160.13 962.1 903.76 107.34 127.07 844.07 575.1 36 CARTER 981.92 250.09 5.39 866.43 182.93 135.12 224.91 78 MITCHELL 805.83 181.19 549.25 815.72 776.2 887.33 144.86 28 PEREZ 144.04 616.81 637.07 342.41 818.58 901.72 104.02 8 ROBERTS 880.38 62.34 591.34 721.18 184.64 378.08 439.94 99 TURNER 21.83 227.82 378.42 680.24 336.24 703.13 52.36 2 PHILLIPS 664.1 879.16 811.4 842.3 463.96 446.52 919.31 17 CAMPBELL 392.91 26.12 591.74 766.1 30.91 108.24 863.81 33 PARKER 359.87 606.99 61.67 188.85 474.87 159.02 907.38 30 EVANS 770.78 70.1 724.89 490.02 667.93 116.4 938.55 70 EDWARDS 507.59 698.53 15.5 251.9 340.84 246.6 233.04 44 COLLINS 803.53 580.38 966.57 941.38 249.58 562.3 725.05
To make a multideminsional array use
type arrayName [x][y];
The first number is row, second is column. You can use arrayName[0][x] to set the names you mentioned, assuming you use each row for a single name and whatever properties belong to that name. Hope this helps :)
With error checking omitted:
const int NUM_PERSONS = 50;
const int SCORES_PER_PERSON = 7;
double scores[NUM_PERSONS][SCORES_PER_PERSON];
int ids[NUM_PERSONS];
std::string names[NUM_PERSONS];
for(int i = 0; i < NUM_PERSONS; ++i) {
file >> ids[i] >> names[i];
for(int j = 0; j < SCORES_PER_PERSON; ++j) {
file >> scores[i][j];
}
}
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.