Reading single lines from file into vector - c++

I have an input file of the following format:
# 1 2 3 4 5 6 7
0 0 0 1
1 0 0 1
2 0 0 1
3 0 0 1
5 0 0 1
6 0 0 1
# 0 0 2 2 4 4 5
0 0 0 1
0 1 0 1
0 2 0 1
0 3 0 1
# 9 10 11 12 13 14 15 16 17 18
0 0 0 1
0 0 1 1
0 0 2 1
0 0 3 1
Each line preceded by a # must be read into its own vector. The entries in between these vectors represent matrices that also must be read into their own matrix.
So from the input file above, what I want to end up having is the following:
knot1 = {1 2 3 4 5 6 7}
cp1= { {0,0,0,1} {1,0,0,1} {2,0,0,1} {3,0,0,1} {5,0,0,1} {6,0,0,1} }
knot2 = {0 0 2 2 4 4 5}
cp2= {{...} {...} {...} {...} }
knot3 = {9 10 11 12 13 14 15 16 17 18}
cp3= {{...} {...} {...} {...} }
Note, each vector is not necessarily the same size! Same goes for the matrices. Also, the number of #vectors and matrices can vary as well.
Here is what I have so far:
ifstream file;
file.open(filename.c_str());
if(file.fail()){
cout << "Cannot open " << filename << endl;
}
int curr_line = 0;
vector<int> knot_locations; //stores the locations of the #vectors
while(!file.eof()){ //loops over input file checking to see where the #vectors are
curr_line++;
string line;
getline(file,line);
if(line[0]=='#'){
knot_locations.push_back(curr_line);
}
}
for(int i=0; i < knot_locations.size(); i++){
file.seekg(std::ios::beg);
for(int i=0; i < knot_locations[i] - 1; ++i){ // this loop skips to the line that contains the #vectors.
file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
}
so now that I am at the line
containing the vector, how can I read
in JUST that SINGLE line into a vector?!
I'm not sure how to turn a string into
a vector of floats. Also, since I know all the
locations of the vectors, I can read everything
else between into the matrices. But again, same
problem. I am not sure how to go about actually
reading these into a numeric array/vector given a line (string)
file.close();
Probably better ways of doing this. Any ideas on how to go about this problem? The key is to be able to read all the vectors marked with a # into their own vector. There can be anywhere between 1-3 of these vectors. And in between each of these vectors is a matrix of unknown rows/columns that also need to be read into their own matrix. What I have above just locates the # marked vectors. Need help on how to read a string line into a numeric array OR a recommendation on a different way to go about this.
Thank you.

Related

Convert a string array with special characters to an int array. Inputs are from a file

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.

How to store a complete path that a priority queue follows while performing A* search

I have been give a problem in which I am provided with user-entered matrix (rows and columns). User will also provide Start State (row and column) and the Goal State.
The job is to use A* search to find the path from the start node to the goal node.
A sample matrix is provided below,
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 G
0 0 0 1 1 0 0 0 1 1
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
0 1 0 1 0 1 1 0 0 0
0 1 0 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
S 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
where "S" is the start state, and "G" is the goal state. 0 are the states, in which you can move to and 1 are the obstacles in the grid, you can't move to them.
There are 3 actions allowed.
Up one cell (cost is 1)
right one cell (cost is 3)
diagonally up towards the right (cost is 2)
To solve this problem, I used Manhattan's Distance as my heuristic function and calculated the heuristic values for all my states.... They looked something like this (for the grid specified above)
10 9 8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1 0
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2
12 11 10 9 8 7 6 5 4 3
13 12 11 10 9 8 7 6 5 4
14 13 12 11 10 9 8 7 6 5
15 14 13 12 11 10 9 8 7 6
16 15 14 13 12 11 10 9 8 7
17 16 15 14 13 12 11 10 9 8
18 17 16 15 14 13 12 11 10 9
19 18 17 16 15 14 13 12 11 10
20 19 18 17 16 15 14 13 12 11
21 20 19 18 17 16 15 14 13 12
Now, this is my code for A* search
void A_search()
{
priority_queue<node, vector<node>, CompareCost>q; // Priority Queue is used.
// node contains 4 elements... 1. "Heuristic" value, 2. Index row, 3. Index Col, 4. Actual Cost until this point
q.push(node(heuristic[srow][scol], srow, scol, 0)); // srow, scol is start state. 0 is Actual Cost
while (!q.empty())
{
node temp = q.top();
path_cost = temp.cost; // path_cost is global variable, which stores actual cost until this point
path[temp.i][temp.j] = true; // Boolean array, which tells the path followed so far.
q.pop();
if (temp.i == grow && temp.j == gcol) // If goal state is found, we break out of the loop
break;
if (temp.i > 0) // Checking for rows above the current state.
{
if (arr[temp.i - 1][temp.j] != 1) // Checking if index above current state is obstacle or not
{
q.push(node(heuristic[temp.i - 1][temp.j] + (temp.cost+1), temp.i - 1, temp.j, temp.cost + 1)); // pushing the above index into queue
}
if (temp.j - 1 < cols)
{
if (arr[temp.i - 1][temp.j + 1] != 1) // Diagonal Index checking
{
q.push(node(heuristic[temp.i - 1][temp.j + 1] + (temp.cost + 2), temp.i - 1, temp.j + 1, temp.cost + 2));
}
}
}
if (temp.j - 1 < cols) // Horizontal Index... Checking if column has exceeded the total cols or not
{
if (arr[temp.i][temp.j + 1] != 1) // Obstacle check for horizontal index
{
q.push(node(heuristic[temp.i][temp.j + 1] + (temp.cost + 3), temp.i, temp.j + 1, temp.cost + 3));
}
}
}
}
And this is the result I get after running this algorithm (Please note that # represents the path taken by the program... I am simply using a boolean 2D array to check which nodes are being visited by Priority Queue. For those indexes only, I am printing # and rest of the grid remains the same)
0 0 0 0 0 # # # # #
# # # 1 1 # # # # G
# # # 1 1 # # # 1 1
# # 0 # # # # # 0 0
# 1 1 # # # # 0 0 1
# # # # # # # 0 1 0
# # # # # 1 1 0 0 0
# # # # 0 1 1 0 0 0
# 1 # 1 0 1 1 0 0 0
# 1 # 1 0 1 1 0 0 0
# # 0 0 0 0 0 0 0 0
S 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
Path Cost: 21
Now, the problem, as evident from the output, is that it is storing every index that gets visited (because heuristic values have very low difference for all the indexes, that is why, almost every node is being visited.. However, ultimately, A* search finds the best path, and that can be seen from "Path Cost: 21" which is the actual cost of the optimal path)
I believe that my algorithm is correct, considering the path cost but what I want now is store also the path of the optimal path.
For this, I want to keep a record of all the indexes (row and column) that are visited by one path.
For example, my path starts from
Row 11, Col 0
Then "optimal paths" goes to,
Row 10, Col 1 -> When I push these nodes into queue, I want to store "11, 0" as well. So that, I can know what path this node has taken previously to reach this state.
Following the same, then it will go to,
Row 9, Col 2 -> So, this node should also store both "11, 0" and "10, 1" in it, hence keeping record of the path it has taken so far.
And this goes on, until the "goal" node.
But I can't seem to find a way to implement this thing, something that keeps track of all the path every node has taken. In this way, I can easily avoid the problem I am facing (I will simply print the path the "goal node" took to reach that point, ignoring all the other nodes which were visited unnecessarily)
Can anyone help me in trying to find a logic for this?
Also, just to be clear, my class node and CompareCost have this implementation,
class node
{
public:
int i, j, heuristic, cost;
node() { i = j = heuristic = cost = 0; }
node(int heuristic, int i, int j, int cost) :i(i), j(j), heuristic(heuristic), cost(cost) {}
};
struct CompareCost {
bool operator()(node const& p1, node const& p2)
{
return p1.heuristic > p2.heuristic;
}
};
I am guessing that I need to store something extra in my "class node" but I can't seem to figure out the exact thing.
Construct your node like a linked list:
class node
{
public:
int i, j, cost;
node* next;
}
Add a method to the class to display the full path:
void ShowPath()
{
Node* temp = this;
do
{
if (temp != NULL)
{
std::cout << "(" << temp->i << ", " << temp->j << ")";
temp = temp->next;
}
} while (temp != NULL);
}
Last, modify A_search() so that it returns the new node definition. You can then call ShowPath() on the return value.

How can I find the prime numbers?

How can I find the prime numbers in a one-dimensional array in C++ in a simple way ??
{
int list[5];
int i,sum = 0;
for (i = 0; i < 5; i++)
{
cout << "Enter The List [" << i << "]: "; cin >> list[i];
sum = sum + list[i];
}
cout << endl;
cout << "The Sum Is:" << sum << endl;
}
Emphasizing on the comment of #john:
Create a function (say bool is_prime(int n)).
Now check if the number n is a prime or not.
So, you need to check if each of the positive integers more than 1 before n divides n or not without leaving any remainder. There's a shorter workaround, which will greatly reduce the computational cost. Just checking till the square root of the number n will do. Hence the function sqrt() is used.
So now, our is_prime() function is pretty easy to build as you can see:
bool is_prime(int n)
{
int i,p=0;
for(i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
p=1;
break; //even if one integer divides the number, then it is composite.
}
}
if(p==1)
return false; //The number is a composite.
else
return true; //The number is a prime.
}
Now, you just need to pass every value of the array into this function, and your job will be done.
Also, this program can be made even better if you check for the special case of 1 which is neither composite nor prime. A suggestion is, check your array element if it is 1 or not. If not, then pass the value in the function, else just print that it is a 1.
NOTE: The sqrt() function is available in the cmath library in C++ so you need to include that in your program too.
You can use sieve of Eratosthenes. Simply how it works is it iterates (from 2) through an boolean array and if arr[i] is prime (is true, i is the given number), sets every multiplicity to false.
Start with an array filled with true
Numbers 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
is prime 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
first you have to set arr[0] and arr[1] to false, because these are not prime numbers
Numbers 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
is prime 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Now, you go to 2 and set every multiplication of it to false.
in this case 4, 6, 8, 10, 12, 14 16...
Numbers 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
is prime 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0
Then do it for 3
so 6, 9, 12, 15
Numbers 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
is prime 0 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0
4 is not prime so you skip it
5 is prime so you do the same as for 2 and 3 (10 -> false, 15 -> false etc.)
after you use it, you can simply check if n is prime
if (arr[n] == true)
cout << n << " is prime";
else
cout << n << " is not prime";
you can find it easily on internet, for example here (there are some optimizations you can add, too)

Read integers from a text file into a two-dimensional array and assess the length

I need to read integers from a text file into a two-dimensional array.
-1 indicates the end of array. Every array supposes to have 6 positive integers (-1 does NOT count as part of the array).
For example, if my text file contains the following integers:
1 3 4 6 1 7 -1 1 3 5 7 2 3 -1 2 5 7 2 6 3 -1
That means when these integers are read into the program, there will be 3 arrays:
1st Array: 1 3 4 6 1 7
2nd Array: 1 3 5 7 2 3
3rd Array: 2 5 7 2 6 3
I wrote a program to assess if each array has a correct length (6 integers) AND correct integers (all integers should be positive) and output corresponding error messages if these criteria are not met.
#include <iostream>
#include <fstream>
#include <string>
#define MAX_ROWS 3
#define MAX_COLUMNS 2
using namespace std;
int main()
{
string fileName = "testdata.txt"; //declare a string to store the Input File's name
ifstream inFile; //name the input file connection
inFile.open(fileName); //open the Input File
string errorMessage = "Input file cannot be found"; //Declare a string to store an error message, just in case the Input file doesn't exist or cannot be found
if (!inFile) { //If the Input File doesn't not exist, then display the error message
cout << errorMessage << '\n'; //also store the error message to the Output file
system("pause");
return 0; //end the program if the Input File does not exist
}
int checkNbr;
int ArrB[MAX_ROWS][MAX_COLUMNS];
int size = MAX_ROWS * MAX_COLUMNS;
bool bad = false;
bool invalidnum = false;
while (!inFile.eof())
{
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "\nThe array does not have enough integers" << endl;
break;
//return 1;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
cout << *(*(ArrB + i) + j) << " ";
}
}
if (invalidnum == true) {
invalidnum = false;
cout << "\nThere is/are negative number(s) or zero(s) in the array imported from your text file.\n";
}
if (bad == false) {
inFile >> checkNbr;
if (checkNbr == -1) {
cout << "\nThe size of the array is correct." << endl;
}
else {
while (checkNbr != -1)
{
cout << checkNbr;
cout << " ";
inFile >> checkNbr;
}
cout << "\nYou have too many numbers in this array\n";
}
}
}
return 0;
}
If I run my program:
Case 1 - PASSED
1 2 3 4 5 6 -1 3 5 2 1 6 8 3 2 5 -1 3 3 5 6 7 5 -1
Case 2 – PASSED
1 2 3 4 5 -6 -1 3 -5 2 1 6 8 -1 3 5 6 7 5 -1
Case 3 – FAILED(!)
1 2 3 4 -1 1 2 3 4 5 6 7 8 -1 1 2 3 4 5 -1
As you can see, case 3 failed. The second array (1 2 3 4 5 6 7 8) is actually longer than the declared array size, but it’s printing out “The array does not have enough integers” error message…..
The ONLY time this program won't work is when the first array does not have enough integers.
Any comments or hints would be appreciated!
The problem
bad is not reset after processing it.
Solution
Move bool bad = false; into the while (!inFile.eof()) loop body so it gets reset every iteration. If you define variables with the narrowest possible scope you can usually avoid this problem, so you should strongly consider doing the same thing with the rest of your variables.
This will solve the bug that was asked about and at least one other bug you haven't found yet. This leaves at least two more outstanding bugs for you to resolve, and both have been covered in the question's comments.
TL;DR version
A quick walk through of input 1 2 3 4 -1 1 2 3 4 5 6 7 8 -1 1 2 3 4 5 -1
1 2 3 4 -1 is parsed and found to be bad, so bad is set to true and the testing for a too-long value and clean-up is skipped. The file hasn't ended, so the program loops and starts reading the next array.
input remaining:
1 2 3 4 5 6 7 8 -1 1 2 3 4 5 -1
output so far:
1 2 3 4
The array does not have enough integers
1 2 3 4 5 6 is parsed. This fills the array and the for loops exit. bad is still true, so the check for overflow is skipped and no message is printed.
Input remaining:
7 8 -1 1 2 3 4 5 -1
output so far:
1 2 3 4
The array does not have enough integers
1 2 3 4 5 6
Now 7 8 -1 is parsed. This is too short to be an array and reported. Take careful note of what this does to the output.
Input remaining:
1 2 3 4 5 -1
output so far:
1 2 3 4
The array does not have enough integers
1 2 3 4 5 6 7 8
The array does not have enough integers
Whoops. Looks like 1 2 3 4 5 6 7 8, not merely 7 8, was too short.
the program then parses 1 2 3 4 5 and finds it to be too short.
Input remaining:
output so far:
1 2 3 4
The array does not have enough integers
1 2 3 4 5 6 7 8
The array does not have enough integers
1 2 3 4 5
The array does not have enough integers

How to fix a bug in my homework solution in C++?

I need to write a program which reads the statistics of n League A football teams and prints the teams name which fall in League B.
A team falls in League B, if it has less than k points after having played m weeks where m is between 1 and 150. Each team gets three points for a win, one point for draw and zero points when lost.
Input Specification: In the first line, you will be given the number of teams 0 < n ≤ 500 and the points 0 < k ≤ 300 needed to stay in league A. Then in the following n lines, there will be the team name and its results. Semicolon indicates the end of input series.
Number 2 represents win, number one represents draw and number zero represents loss.
Output specification:
Sample Input I
4 19
Team_A 1 1 1 1 1 1 1 1 1 0 1 1 1 0 2 1 0 ;
Team_B 0 1 0 2 2 1 1 0 1 1 0 2 0 1 0 0 2 ;
Team_C 0 0 1 0 2 2 2 1 1 1 1 1 0 0 2 1 2 ;
Team_D 0 1 0 1 2 1 2 1 0 0 0 2 2 2 0 0 0 ;
Sample Output I
Team_A 16
Team_B 18
This is the code I came up with, but the output is wrong and I don't know why,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,points,sum=0,i,value;
char name[15];
char p;
scanf("%d %d",&n,&points);
for(i=1;i<=n;i++)
{
scanf("%s",&name);
do
{
scanf("%c ",&p);
if(p!=';')
{
value=p-48;
sum=sum+value;
}
}while(p!=';');
if(sum<=points)
printf("%s %d",name,sum);
}
return 0;
}
You might look for problems by stuffing the program with output statements.
If you add after scanf("%c ",&p); an output statement to show the value of p, you will find that the first value for p is a space character, which spoils your calculation.
In the same way, if you trace the value of value, you will find that you forgot to initialize this variable to zero for each team.