I have a text file containing names and numbers. The name or the string contains 15 chars and I need to put it to the string. I'm working with structures.
struct grybautojas{
string vardas;
int barav, raudon, lep, diena;
}gryb[100];
After that, there are simple calculations which is done right, the problem is, it only reads everything once. After taking a first "box" of information, it just stops. Everything else in the result file is either blank as a string or 0 as an integer.
Here's my input function:
void ivedimas(){
char eil[16];
int b,r,l;
inFile >> n;
inFile.ignore();
for(int i=0;i<n;i++){
inFile.get(eil,15);
gryb[i].vardas=eil;
inFile >> gryb[i].diena;
gryb[i].barav=0, gryb[i].raudon=0, gryb[i].lep=0;
for(int m=0;m<gryb[i].diena;m++){
inFile >> b >> r >> l;
gryb[i].barav+=b, gryb[i].raudon+=r, gryb[i].lep+=l;
}
inFile.ignore();
}
inFile.close();
}
And here's the file containing data:
4
Petras 3
5 13 8
4 0 5
16 1 0
Algis 1
9 6 13
Jurgis 4
4 14 2
4 4 15
16 15 251
1 2 3
Rita 2
6 65 4
4 4 13
What's the problem?
inFile.get(eil,15);
Rita 2
Petras 3
00000000011111
12345678901234
I don't count 15, I count 14. Also, some of your lines seem to have a space at the end. You should rewrite your input logic to be much more robust. Read lines and parse them.
This line:
inFile.get(eil,15);
is reading the number that follows the name.
When you try to read the number (3 in your example), you get the next one (5) instead.
Related
My problems here is to take all the integers in a file, and store to an int array (of course without |), and then do something with it (here I just need help to print out the array).
The data from the file is said to be a 10x10 matrix.
My code output is another 10x10 with trash values, as I tried using std::stringstream.
Input:
1|11|2|13|2|2|2|11|13|2
1|11|2|13|2|2|2|13|2|11
1|13|1|13|2|2|2|2|2|2
1|13|1|12|2|2|2|2|2|2
1|13|1|13|1|2|2|2|2|2
1|13|1|13|1|1|2|2|2|2
1|13|1|13|1|1|1|2|2|2
1|13|1|13|1|1|1|1|2|2
1|13|1|13|1|1|1|1|1|2
1|13|1|13|1|1|1|1|1|1
Code:
#include<iostream>
#include<cstring>
#include<fstream>
#include<sstream>
using namespace std;
int main(){
//read data from file and store in a 2d array
ifstream myfile("input.txt");
string arr[10][20];
for(int i=0;i<10;i++){
for(int j=0;j<20;j++){
getline(myfile,arr[i][j],'|');
}
}
//convert string to int
//use stringstream
int arr2[10][20];
for(int i=0;i<10;i++){
for(int j=0;j<20;j++){
stringstream ss;
ss<<arr[i][j];
ss>>arr2[i][j];
}
}
//print arr2
for(int i=0;i<10;i++){
for(int j=0;j<20;j++){
cout<<arr2[i][j]<<" ";
}
cout<<endl;
}
myfile.close();
return 0;
}
The output should be:
1 11 2 13 2 2 2 11 13 2
1 11 2 13 2 2 2 13 2 11
1 13 1 13 2 2 2 2 2 2
1 13 1 12 2 2 2 2 2 2
1 13 1 13 1 2 2 2 2 2
1 13 1 13 1 1 2 2 2 2
1 13 1 13 1 1 1 2 2 2
1 13 1 13 1 1 1 1 2 2
1 13 1 13 1 1 1 1 1 2
1 13 1 13 1 1 1 1 1 1
My output:
1 11 2 13 2 2 2 11 13 2
1 13 2 2 2 2 2 2 13 1
1 2 2 2 2 2 13 1 13 1
1 2 2 2 13 1 13 1 1 1
1 2 13 1 13 1 1 1 1 1
1994842136 12 7086696 7085352 1994774642 0 1994842144 1994771436 0 0
6416848 2004213955 7086772 6416972 12 7086696 0 4 48 1994842112
2004213726 1 7149280 7149288 7086696 0 1988425164 0 2003400672 12
1999860416 6416972 2 1999966512 1999657456 1999691632 1999846272 1999845632 1999819744 1999860464
4194304 1994719472 0 6417024 0 6418312 2004471984 775517426 -2 6417120
Two issues: You try to read 10x20 when there is only 10x10 in the file. Further your code assumes that there is a | between all adjacent numbers, but thats not the case. There is no | between the last number in a line and the first in the next line.
Change the size accordingly and read full lines before you split them at |:
string arr[10][10];
for(int i=0;i<10;i++){
std::string line;
getline(myfile,line);
std::stringstream linestream{line};
for(int j=0;j<10;j++){
getline(linestream,arr[i][j],'|');
}
}
Live Demo
This is minimum changes on your code. Next I would suggest to extract integers from the stream directly instead of first extracting string and then convert them to integers (by placing the strings into another stream and then extracting the integer, you could do this already with the ifstream).
The basic problem is that the content of your input file doesn't map well to the operation that you're trying to do on that content. In particular, you've assumed that every character in your input file is separated by a | character which is not the case since there is a newline between the last character in any particular line and the first character in the next line.
Also, do note that you have created a 2D array that has 10 rows and 20 columns but your input file has only 10 rows and 10 columns.
Better would be to use a 2D std::vector as shown below:
#include <iostream>
#include<sstream>
#include<string>
#include<vector>
#include <fstream>
int main()
{
std::ifstream inputFile("input.txt");
std::string line;
//create a 2D vector
std::vector<std::vector<int>> arr;
int num = 0; //this will hold the current integer value from the file
std::string numTemp;
if(inputFile)
{
while(std::getline(inputFile, line)) //read line by line
{
std::vector<int> temp;//create a 1D vector
std::istringstream ss(line);
while(std::getline(ss, numTemp, '|') && (std::istringstream(numTemp) >> num)) //read integer by integer
{
//emplace_back the current number num to the temp vector
temp.emplace_back(num);
}
//emplace_back the current 1D vector temp to the 2D vector arr
arr.emplace_back(temp);
}
}
else
{
std::cout<<"input file cannot be opened"<<std::endl;
}
//lets confirm if our 2D vector contains all the elements correctly
for(const auto& row: arr)
{
for(const auto& col: row)
{
std::cout<<col<<" ";
}
std::cout<<std::endl;
}
return 0;
}
The output of the above program can be seen here.
The advantage of using std::vector over built in array is that :
You don't have to know the how many rows and columns are there in the input.txt file beforehand.
It is not necessary that all rows have the same number of columns.
That is, using std::vector is flexible.
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.
So i am working on my project and i am facing a problem. Every time i try to input data from file in c++ i got blank screen
The code :
int main() {
string make[1000],model[1000],partName[1000];
int partNo[1000],quantity[1000];
double price[1000];
int i = 0;
ifstream myFile("file.txt");
while (!myFile.eof())
{
myFile >> make[i] >>model[i]>> partNo[i] >>quantity[i]>> price[i]>>partName[i];
i++;
}
for (int j = 0;j < i;j++)
cout << make[j] <<"\t"<<model[j]<<"\t"<< partNo[j] <<"\t"<<quantity[j]<<"\t"<< price[j]<<"\t"<<partName[j]<<endl;
return 0;
}
a sample from data file :
Pajero NA1H25 1 26 3.65 BLADE W/S WIPER
Pajero NA1S25 2 12 65.7 OIL SEAL-T/M CASE
Pajero NA3H25 3 20 14.6 OIL SEAL-DIST
Pajero NA3H25 4 26 10.95 DISC-CLUTCH
Pajero NC3V25 5 13 14.6 FUSIBLE LINK
Pajero ND0000 6 12 3.65 WEATHERSHIELD PKGE-L
Pajero ND1V45 7 10 32.85 SEAL & BOOT KIT
Pajero ND1Z45 8 24 62.05 FUSIBLE LINK
Pajero ND1Z45 9 9 18.25 COVER-HANDLE LH
Pajero ND1Z45 10 6 3.65 PIPE ASSY-OIL
anyone can help ??
Input with operator >> to a std::string will only read a single word.
This means that the first input will read "BLADE" and leave "W/S WIPER" in the input buffer, and the next read will start from there. Eventually, an input operation for a numeric field will try to read letters, and fail to read.
After that the stream is in a bad condition and nothing else is read, even though myfile.eof() is not true (but myfile.fail() is). There you have an infinite loop. See Why is iostream::eof inside a loop condition considered wrong?
Each line of my file consists of an unknown number of integers, which are separated by spaces. I would like to read in each line as a vector of those integers.
Here is an example of such file:
11 3 0 1
4 5 0 3
2 3 4 1
23 4 25 15 11
0 2 6 7 10
5 6 2
1
11
I've been able to read in small amounts of data successfully using the following method (Note that outer_layers is a vector that contains these vectors I'm trying to populate):
for (int i = 0; i < outer_layers.size(); i++)
{
while (in >> temp_num)
{
outer_layers[i].inner_layer.push_back(temp_num);
if (in.peek() == '\n')
break;
}
}
However, when I'm trying to read in larger amounts of data, sometimes it'll read in two lines under one vector. In one of the files, out of 24 lines, it read two-liners on two occasions, so last two vectors did not have any data.
I can't wrap my head around it. Any ideas what I'm doing wrong?
EDIT: Something interesting I've noticed in some of the lines of the trouble-maker file is this:
Let's say there are three lines.
23 42 1 5
1 0 5 10
2 3 11
Line #1 reads in just fine as 23 42 1 5; however, line #2 and #3 get read together as 1 0 5 10 2 3 11.
In Notepad++ they look just fine, each on their own lines. However, in Notepad, they look like this:
23 42 1 51 0 5 10 2 3 11
If you notice, the 5 (last integer of line #1) and 1 (first integer of line #2) are not separated by spaces; however, 10 and 2 are separated by a space.
I've noticed that behavior on any double-read-in lines. If they are separated by a space, then they're both read in. Not sure why this is occurring, considering there should still be a new line character in there for Notepad++ to display the on separate lines, am I right?
I'm not sure how your outer_layers and inner_layers is setup, but you can use std::getline and std::stringstream to fill your vectors something like this :
std::vector< std::vector<int> > V ;
std::vector <int> vec;
std::ifstream fin("input.txt");
std::string line;
int i;
while (std::getline( fin, line) ) //Read a line
{
std::stringstream ss(line);
while(ss >> i) //Extract integers from line
vec.push_back(i);
V.push_back(vec);
vec.clear();
}
fin.close();
for(const auto &x:V)
{
for(const auto &y:x)
std::cout<<y<<" ";
std::cout<<std::endl;
}
I have this code :
int obj;
while ( std::cin >> obj )
{
std::cout << obj << std::endl ;
int temp = obj ;
++ temp;
std::cout << temp << std::endl ;
}
When I give proper integer inputs, I understand the output.
eg. If I get 12 as input, I see something like this on console :
12
12
13
But, if I give some integers with white spaces as input, I can't seem to understand the output.
eg. If I give 12 12 12 12 as input, I see this on console :
12 12 12 12
12
13
12
13
12
13
12
13
Can someone please explain ?
The first example includes your input.
input
12
output
12
13
The second example is exactly this, multiplied 4 times, for each of the 4 numbers received as input. The seperator is "whitespace" - spaces, new lines or tabs. It is not a "non integer", but rather "four integers":
The input:
12 12 12 12
is equivalent to
12
12
12
12
output:
12
13
12
13
12
13
12
13
The loop reads whatever the input is, only after you hit "enter". So in the first case, it reads one value 12, prints 12 then 13 for the updated value in temp, then goes back waiting for you to type more numbers.
In the second case, it reads 12, prints 12 & 13, then goes back, reads another 12, prints 12 & 13, and so on another 2 times. Then goes back waiting for your to type more data.
Note that whitespace is a proper separator for your input. If you want it to go wrong, try typing 12a, in which case it will print 12 & 13 forever (well, until you get bored and stop it), since it will "stop reading" at the 'a' without updating obj - and because nothing in the loop clears out the a, it keeps going.
When you add the space, it takes them as separate values. And run the while loop for each of them.
int obj;
cin >> obj;
cin reads valid integer data from your input until it finds a character that does not belong to an integer, or there is no more data. In your first example, cin hits the end of your input and returns the number. In your second example, cin reads the input from the string "12 12 12 12", extracts the first integer from your input stream and writes it to obj. In the next run of your while loop, cin is confronted with the string "12 12 12" (since it has extracted/removed the first number from your input stream) and the story continues until there is no more input to read from.