I am working on a program in C++ that will read integers from a file, then pass them to a function that checks for a Subset Sum.
The file is formatted like so:
number of cases n
sum for case 1
list of integers separated by a space
sum for case
list of integers separated by a space
sum for case n
list of integers separated by a space
My problem now lies in how to read the list of integers into an array to be passed to my function.
This is my main so far:
fstream infile("subset.txt");
if(infile.is_open()){
int numCases, num;
infile >> numCases;
while(infile >> num){
for(int i = 0; i < numCases; i++)
{
int sum;
int set[30];
num >> sum;
for(int i = 0; i < 30; i++)
{
if(num == '\n')
{
sum[i] = -1
}
else
{
num << sum[i]
}
}
int n = sizeof(set)/sizeof(set[0]);
if(subsetSum(set, n, sum) == true)
printf("True");
else
printf("False");
}
}
}
else
printf("File did not open correctly.");
return 0;
Any help you guys can give me would be greatly appreciated.
Yes, this is for an assignment, so if you would rather just give me hints that would be appreciated as well. The assignment is for the algorithm and I have that working, I just need a hand with the I/O.
I would read the line containing the list of numbers using std::getline, then use an istringstream to parse numbers out of that string.
I'd also use a std::vector instead of an array to hold the numbers. For the actual parsing, I'd probably use a pair of std::istream_iterators, so the code would look something like this:
while (infile >> sum) {
std::getline(infile, line);
std::istringstream buffer(line);
std::vector<int> numbers{std::istream_iterator<int>(buffer),
std::istream_iterator<int>()};
std::cout << std::boolalpha << subsetSum(numbers, sum);
}
Related
I have an array that reads data from a file, the data is binary digits such as 010011001001 and many others so the data are strings which I read in to my 2d array but I am stuck on comparing each value of the array to 0. Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000][12];
int i = 0, zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while(!inFile.eof())
{
for(int i = 0; i < 5000; i++)
{
for(int j = 0; j < 12; j++)
{
inFile >> myArr[i][j];
j++;
}
i++;
}
}
for(int j = 0; j < 12; j++)
{
for(int i = 0; i < 5000; i++)
{
if(myArr[i][j].compare("0") == 0)
{
zeroCount++;
}
else
{
oneCount++;
}
i++;
}
if(zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
j++;
}
}
some input from the text file:
010110011101
101100111000
100100000011
111000010001
001100010011
010000111100
Thank you for editing you question and providing more information. Now, we can help you. You have 2 major misunderstandings.
How does a for loop work?
What is a std::string in C++
Let us start with the for loop. You find an explanation in the CPP reference here. Or, you could look also at the tutorial shown here.
The for loop has basically 3 parts: for (part1; part2; part3). All are optional, you can use them, but no need to use them.
part1 is the init-statement. Here you can declare/define/initialize a variable. In your case it is int i = 0. You define a variable of data type int and initialize it with a value of 0
part2 is the condition. The loop will run, until the condition becomes false. The condition will be check at the beginning of the loop.
part3 is the so called iteration-expression. The term is a little bit misguiding. It is basically a statement that is executed at the end of the loop, before the next loop run will be executed and before the condition is checked again.
In Pseudo code it is something like this:
{
init-statement
while ( condition ) {
statement
iteration-expression ;
}
}
which means for the part of your code for(int j = 0; j < 12; j++)
{
int j = 0; // init-statement
while ( j < 12 ) { // while ( condition ) {
inFile >> myArr[i][j]; // Your loop statements
j++; // Your loop statements PROBLEM
j++; // iteration-expression from the for loop
}
}
And now you see the problem. You unfortunately increment 'j' twice. You do not need to do that. The last part3 of the for loop does this for you already.
So please delete the duplicated increment statements.
Next, the std::string
A string is, as its names says, a string of characters, or in the context of programming languages, an array of characters.
In C we used to write actually char[42] = "abc";. So using really a array of characters. The problem was always the fixed length of such a string. Here for example 42. In such an array you could store only 41 characters. If the string would be longer, then it could not work.
The inventors of C++ solved this problem. They created a dynamic character array, an array that can grow, if needed. They called this thing std::string. It does not have a predefined length. It will grow as needed.
Therefore, writing string myArr[5000][12]; shows that you did not fully understand this concept. You do not need [12], becuase the string can hold the 12 characters already. So, you can delete it. They characters will implicitely be there. And if you write inFile >> myString then the extractor operator >> will read characters from the stream until the next space and then store it in your myString variable, regardless how long the string is.
Please read this tutorial about strings.
That is a big advantage over the C-Style strings.
Then your code could look like:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string myArr[5000];
int zeroCount = 0, oneCount = 0;
ifstream inFile;
inFile.open("Day3.txt");
while (!inFile.eof())
{
for (int i = 0; i < 5000; i++)
{
inFile >> myArr[i];
}
}
for (int i = 0; i < 5000; i++)
{
zeroCount = 0; oneCount = 0;
for (int j = 0; j < 12; j++)
{
if (myArr[i][j]== '0')
{
zeroCount++;
}
else
{
oneCount++;
}
}
if (zeroCount > oneCount)
{
cout << "Gamma is zero for column " << i << endl;
}
else
{
cout << "Gamma is One for column " << i << endl;
}
}
}
But there is more. You use the magic number 5000 for your array of strings. This you do, because you think that 5000 is always big enough to hold all strings. But what, if not? If you have more than 5000 strings in your source file, then your code will crash.
Similar to the string problem for character arrays, we have also a array for any kind of data in C++, that can dynamically grow as needed. It is called std::vector and you can read about it here. A tutorial can be found here.
With that you can get rid of any C-Style array at all. But please continue to study the language C++ further and you will understand more and more.
Ther are more subtle problems in your code like while(!inFile.eof()), but this should be solved later.
I hope I could help
I'm trying to solve this problem from an online judge (Codeforces):
One day Deivis came across two Vectors of integers A and B, and wondered, could it be possible to form the number X by adding an element of A to another element of B?
More formally, it is possible to choose two indexes i and j such that Ai + Bj = x?
Input
The first entry line is two integers n and x. The second line contains n numbers, the vector A. The third and last line contains n numbers, vector B.
Output
Print 1 if it is possible to form the number x from a sum of one element of each vector, and 0 otherwise."
My problem is that I can not fill in the second vector, when the program runs on the site it fills the vector with zeros. I am using C ++, here's my code:
#include <bits/stdc++.h>
using namespace std;
#define MAX 10
int main()
{
int n, x, i = 0, j = 0, resp = 0, sum;
vector<int> vetA(MAX), vetB(MAX);
cin >> n >> x;
while (scanf("%d", &vetA[i]) == 1)
i++;
while (scanf("%d", &vetB[j]) == 1)
j++;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
sum = vetA[i] + vetB[j];
if (sum == x)
{
resp = 1;
goto END;
}
}
}
END: printf("%d", resp);
return 0;
}
I try to use getchar() after each while loop, but seems that on the site it does not do data capture like on a keyboard, and so the second vector isn't receiving any data. I've also tried to capture data as a std::string but that doesn't work.
Can someone help me?
Here are some hints/examples to compare your program to:
#include <iostream> //Include each standard library seperately
#include <vector> //#include <bits/stdc++.h> is bad practice
// Only declare variables as they are used.
int n; // Better coding practice is one variable per line.
int x; // Competitions shouldn't care how many lines.
if (!(std::cin >> n >> x)) //This is basically the same as cin.fail()
{
std::cerr << "Error inputting data.\n";
return 1;
}
// Now create the vectors, after the size has read in.
std::vector<int> vetA(n);
std::vector<int> vetB(n);
// The number of elements is known, so use a "for" loop.
for (size_t i = 0; i < n; ++i)
{
std::cin >> vetA[i];
}
for (size_t i = 0; i < x; ++i)
{
std::cin >> vetB[i];
}
You should add in some error handling because your program will be given some invalid inputs.
The inputs and vector sizes are examples since you didn't specify the input format in your Post.
I am quite new to progamming, I would like to parse data in a format like this:
4 ((182, 207), (385, 153), (638, 639), (692, 591))
First number states the number of pairs that will occur. I want to save first number of each pair as X axis and second number of each pair as Y axis.
In my head for now I wanted to save entire line via scanf and then try to work around the amount of brackets and commas but I am not sure if that is the right method or how to implement it properly. I do not want to use any built in containers or string. I tried to do it straight away via scanf doing something like
for(int i= 0; i < pair_count;i++){
scanf("(%d, %d)",tabx[i],taby[i])
}
but it does not work :(. I don't know how to format the scanf correctly I guess or my idea on how to do it is completely wrong.
scanf() expects the address to a variable, not the variable itself. So try:
scanf("(%d, %d)",&tabx[i],&taby[i]);
You can also try to use c++ streams:
for(int i= 0; i < pair_count;i++){
char d1,d2,d3;
if ( (cin >> d1 >> tabx[i] >> d2 >> taby[i] >> d3) && d1=='(' && d3==')' && d2==',') {
... //process data
}
else cout << "Wrong input !"<<endl;
}
You have to input all matching characters. It's a bit tricky, because , is not present after last pair of numbers.
Following sample code solves your problem.
#include <cstdio>
#include <cstdlib>
int main() {
// 4 ((182, 207), (385, 153), (638, 639), (692, 591))
int pair_count;
scanf("%d", &pair_count);
scanf(" (");
int* tabx = new int[pair_count];
int* taby = new int[pair_count];
for (int i = 0; i < pair_count-1; ++i) {
if (scanf("(%d, %d), ", &tabx[i], &taby[i]) < 2) {
fprintf(stderr, "Input error!\n");
return EXIT_FAILURE;
}
}
if (scanf("(%d, %d))", &tabx[pair_count-1], &taby[pair_count-1]) < 2) {
fprintf(stderr, "Input error!\n");
return EXIT_FAILURE;
}
for (int i = 0; i < pair_count; ++i) {
printf("%d %d\n", tabx[i], taby[i]);
}
delete[] tabx;
delete[] taby;
}
Alternatively, you can read the entire input to string and replace all (, ) and , with (space). After that you can simply parse numbers. On the other hand, this removes validation of data format.
I have trouble to read in an input from user and convert them into matrix for calculation. For example, with the input = {1 2 3 / 4 5 6}, the program should read in the matrix in the form of
1 2 3
4 5 6
which have 3 cols and 2 rows. What i got so far which does not seem to work:
input.replace(input.begin(), input.end(), '/', ' ');
stringstream ss(input);
string token;
while (getline(ss, token, ' '))
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
int tok = atoi(token.c_str());
(*matrix).setElement(i, j, tok);
}
}
}
So what I'm trying to do is to break the input into token and store them into the matrix using the setElement function which take the number of row, column and the variable that user want to store. What wrong with this code is that the variable of tok doesnt seem to change and keep stuck in 0. Assuming that row and col are knows.
Thanks so much for any help.
Although many simple ways exist to solve the specific problem (and other answer have various good suggestions) let me try to give a more general view of the problem of "formatted input".
There are essentially three kind of problems, here:
at low level you have to do a string to number conversion
at a higher level you have to parse a composite format (understanding rows and line separation)
finally you also have to understand the size of the compound (how many rows and cols?)
this 3 things are not fully independent and the last is needed to know how to store elements (how do you size the matrix?)
Finally there is a 4th problem (that is spread all other the other 3): what to do if the input is "wrong".
These kind of problem are typically afforded in two opposite ways:
Read the data as they come, recognize if the format is matched, and dynamically grow the data structure that have to contain them or...
Read all the data as once as they are (textual form), then analyze the text to figure out how many elements it has, then isolate the "chunks" and do the conversions.
Point 2. requires good string manipulations, but also requires the ability to know how the input is long (what happens if one of the separating spaces is a new-line? the idea the everything is got with a getline fails in those cases)
Point 1 requires a Matrix class that is capable to grow as you read or a temporary dynamic structure (like and std container) in which you can place what you read before sending it into the appropriate place.
Since I don't know how your matrix works, let me keep a temporary vector and counters to store lines.
#include <vector>
#include <iostream>
#include <cassert>
class readmatrix
{
std::vector<int> data; //storage
size_t rows, cols; //the counted rows and columns
size_t col; //the counting cols in a current row
Matrix& mtx; //refer to the matrix that has to be read
public:
// just keep the reference to the destination
readmatrix(Matrix& m) :data(), rows(), cols(), cols(), mtx(m)
{}
// make this class a istream-->istream functor and let it be usable as a stream
// manipulator: input >> readmatrix(yourmatrix)
std::istream& operator()(std::istream& s)
{
if(s) //if we can read
{
char c=0:
s >> c; //trim spaces and get a char.
if(c!='{') //not an open brace
{ s.setstate(s.failbit); return s; } //report the format failure
while(s) //loop on rows (will break when the '}' will be found)
{
col=0;
while(s) //loop on cols (will break when the '/' or '}' will be found)
{
c=0; s >> c;
if(c=='/' || c=='}') //row finished?
{
if(!cols) cols=col; //got first row length
else if(cols != col) //it appears rows have different length
{ s.setstate(s.failbit); return s; } //report the format failure
if(c!='/') s.unget(); //push the char back for later
break; //row finished
}
s.unget(); //pushthe "not /" char back
int x; s >> x; //get an integer
if(!s) return s; //failed to read an integer!
++col; data.push_back(x); //save the read data
}
++rows; //got an entire row
c=0; s >> c;
if(c == '}') break; //finished the rows
else s.unget(); //push back the char: next row begin
}
}
//now, if read was successful,
// we can dispatch the data into the final destination
if(s)
{
mtx.setsize(rows,cols); // I assume you can set the matrix size this way
auto it = data.begin(); //will scan the inner vector
for(size_t r=0; r<rows; ++r) for(size_t c=0; c<cols; ++c, ++it)
mtx(r,c) = *it; //place the data
assert(it == data.end()); //this must be true if counting have gone right
}
return s;
}
};
Now you can read the matrix as
input >> readmatrix(matrix);
You will notice at this point that there are certain recurring patterns in the code: this is typical in one-pass parses, and those patterns can be grouped to form sub-parsers. If you do it generically you -in fact- will rewrite boost::spirit.
Of course some adaption can be done depending on how your matrix works (has it fixed sizes??), or what to do if rows sizes don't match (partial column filling ??)
You can even add a formatted input operator like
std::istream& operator>>(std::istream& s, Matrix& m)
{ return s >> readmatrix(m); }
so that you can just do
input >> matrix;
You are trying to operate on each cell of the matrix for each char read in the input!
You have to take one char for each cell, not multiple.
Splitting a string in tokens can be done by using the following function.
Please don't be shocked that the following code isn't runnable, this is due to the missing matrix class.
Try the following:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
void split(const string& str, char delimiter, vector<string>& result) {
string::size_type i = 0;
string::size_type delimOcc = str.find(delimiter);
while (delimOcc != string::npos) {
result.push_back(str.substr(i, delimOcc-i));
i = ++delimOcc;
delimOcc = str.find(delimiter, delimOcc);
if (delimOcc == string::npos) {
result.push_back(str.substr(i, str.length()));
}
}
}
int main()
{
std::string input = "1 2 3 / 4 5 6";
vector<string> rows;
split(input, '/', rows);
for(int i = 0; i < rows.size(); i++) {
vector<string> cols;
split(rows[i], ' ', cols);
for(int j = 0; j < cols.size(); j++) {
if(cols[j][0] != '\0'){
int tok = stoi(cols[j]);
(*matrix).setElement(i, j, tok);
cout << tok << " - " << i << " - " << j << endl;
}
else {
if(j == 0) j--;
}
}
}
return 0;
}
If you know the size of the matrix on forehand you actually don't need getline, you should read int by int. (untested code)
input.replace(input.begin(), input.end(), '/', '\n');
stringstream ss(input);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
int tok;
ss >> tok;
(*matrix).setElement(i, j, tok);
}
}
I have a set of strings which looks like
"4 7 14 0 2 blablabla"
"3 8 1 40 blablablablabla"
...
The first number N correspond to how many numbers will follow.
Basically, the format of a string is N+1 numbers, separated with a space, followed by an unknown number of irrelevant characters at the end that I don't need.
How can I get all the numbers in variables or a dynamic structure given that I don't know the number N in advance ?
In other words, I'd like something like:
sscanf(s, "%d %d %d %d",&n,&x,&y,&z);
which would work no matter how many numbers in the string.
The first thing would be to break up the input into lines, by using
getline to read it. This will greatly facilitate error recovery and
resynchronization in case of error. It will also facilitate parsing;
it's the strategy which should be adopted almost every time a newline in
the input is significant. After that, you use a std::istringstream to
parse the line. Something like:
std::vector<std::vector<int> > data;
std::string line;
while ( std::getline( input, line ) ) {
std::istringstream l( line );
int iCount;
l >> iCount;
if ( !l || iCount < 0 ) {
// format error: line doesn't start with an int.
} else {
std::vector<int> lineData;
int value;
while ( lineData.size() != iCount && l >> value ) {
lineData.push_back( value ) ;
}
if ( lineData.size() == iCount ) {
data.push_back( lineData );
} else {
// format error: line didn't contain the correct
// number of ints
}
}
}
int input;
std::vector<int> ints;
while(std::cin >> input) //read as long as there is integer
ints.push_back(input);
std::cin.clear(); //clear the error flag
//read the remaining input which most certainly is non-integer
std::string s = "3 54 -4 42 fdsvadsdsberwte";
std::istringstream source(s);
std::vector<int> ints;
int num = 0;
int temp = 0;
if (source >> num) // read the first number and if it succeeds, read the rest
{
while(source >> temp) ints.push_back(temp);
// Here, I'd compare the size of the vector with what was
// expected (num) and act accordingly.
}
else
{
// format error
}
You could do it something like this:
std::string buffer;
while(std::getline(in, buffer)) { // read a line
std::istringstream str(buffer); // put line in a stringstream for parsing
int count;
str >> count; // read first number
std::vector<int> numbers(count); // reserve space for other numbers
for(int i = 0; i < count; i++) { // read other numbers
str >> numbers[i];
}
}
Initialize an istringstream with your string, and read from it:
std::istringstream ss(s);
int N;
ss >> N;
std::vector<int> a(N); //int* a = new int[N];
for (int i=0;i<N;i++)
ss >> a[i];
You can use dynamic array and a linked list, of dynamic array type. After reading a line initialize the array using number N and insert the numbers sequentially on each index. Insert the node containing line data to linked list.
Pseudo code:
int *lineNumbers;
lineNumbers = new int[N];
List<int*> data;
data.insert(lineNumbers);