I'm writing a basic chess program to calculate how many sets you can make with the given chess figures. The data file:
4
22 3 5 6 2 0
1 1 1 1 1 1
8 4 4 4 1 2
5 3 3 3 0 2
The code:
#include <iostream>
#include <fstream>
#include <vector>
int main
(int argc, char *argv[])
{
std::fstream data_file;
size_t i, k;
std::vector<long> chess;
long t, n;
data_file.open("U1.txt", std::ios::in);
data_file >> n;
for (i = 0; i < n; i++)
chess.push_back(0);
for (i = 0; i < n; i++) {
for (k = 0; k < 6; k++) {
data_file >> t;
std::cout << t << " ";
chess[k] += t;
}
std::cout << std::endl;
}
data_file.close();
for (int i = 0; i < 6; i++)
std::cout << chess[i] << " ";
std::cout << std::endl;
data_file.open("U1rez.txt", std::ios::out);
data_file << n;
std::cout << n << std::endl;
data_file.close();
return EXIT_SUCCESS;
}
The output:
22 3 5 6 2 0
1 1 1 1 1 1
8 4 4 4 1 2
5 3 3 3 0 2
36 11 13 14 3 4
4
Why am I getting 3 and 4 at the end result just after 36, 11, 13 and 14 at line 5? When I print the test values I seem to get the right numbers but something goes terribly wrong in the addition of them in the vector container.
for (i = 0; i < n; i++)
chess.push_back(0);
.
.
.
for (i = 0; i < n; i++) {
for (k = 0; k < 6; k++) {
data_file >> t;
std::cout << t << " ";
chess[k] += t;
}
std::cout << std::endl;
}
here, you initialized n(=4) places in the vector, but here you are accessing the index 4 and 5 of the vector chess which is causing the addition problem.
On an unrelated note, you will have a much easier time with C++ if you let go of some of the rules imposed by C.
The C++ API uses scope-bounded resource management; i.e. there's no need to explicitly close the file handle here, since the class does this for you when its destructor is called at the end of the declared scope.
Prefer std::cout << "\n" to std::cout << std::endl, unless you actually intend to insert a newline and flush the buffer. Many C++ programmers still use printf, and I personally think that it's a lot more elegant than C++'s ugly standard solution to IO -- feel free to use printf.
Do you find your code easier to manage and read when you declare your variable where they are used (e.g. for (size_type i = 0; ... ; ...)), rather than at the beginning of your method? This also allows the compiler to potentially make better choices about register usage, since it has more information about the scopes of your temporary variables.
Here are a few features of C++11 that can also save you some time:
Automatic type inference: when the compiler can infer the type of a variable, it's not necessary for you to explicitly specify it; you can use auto instead (e.g. auto x = parse_data();).
Range-for: if you are operating on a container that provides global definitions begin() and end() (such as any standard container), then instead of this:
typedef typename container_type::const_iterator iter;
for (iter i = begin(container), iter l = end(container); i != l; ++i) { ... }
You can do this:
for (const auto& x : container) { ... }
I just wanted to give you a few quick pointers that can save you some time.
Related
Suppose I give input to a C++ program as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
C++ code:
int n;
for (int i = 0; i < 15; i++)
{
std::cin >> n;
// use the value of n to make changes
}
In the above code I can read the input sequentially,
i.e. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.
Is there any way to read input directly (without using extra memory in C++ program) from the input stream in the following order:
5 4 3 2 1 10 9 8 7 6 15 14 13 12 11
First five digits in reverse order 5 4 3 2 1, next five digits in reverse order 10 9 8 7 6, ...
No.
You need to read the data as they flow into the input stream.
In your program then, you can re-order them in any way you like.
As noted in the comments, the best way to do this is to read them in the order they are given and sort them afterwards.
// vector to hold the values
std::vector<int> values;
values.reserve(15); // reserve for better performance
int n;
for (int i = 0; i < 15; i++)
{
std::cin >> n;
values.push_back(n); // add value to back of vector
}
// sort the vector
std::sort(values.begin(), values.end());
// use the values in ascending order...
for (int i = 0; i < 15; i++) {
std::cout << values[i];
}
Yes this is possible ,but it increase the running time complexity of the code .
First you can make the outer loop for how many series it insert , in the above test case its 3.
Secondly you can make a inner loop which adds the number .
I am not sure the code is running but the logic helps you .
I am implementing the psuedo code using stack !
int n=5;
for(int count = 1 ; count <= 3 ;count++)
{
for(int i=n ; i > n-5 ; i++)
{
push_on_stack(i);
}
n=n+5;
}
You need to wrap your taking input in some functionality that reorders the values for you. You might be able to do so outside the program, i.e., pipe the input stream through another program that reorders the values. Then your code might already work as you have it now.
Or you do this wrapping in your program. For example using a custom stream-like class that buffers the values in between.
There's no way to get this done without using extra memory to buffer the values you don't yet need.
Example:
#include <iostream>
#include <stack>
struct reader {
std::stack<int> data;
reader& operator>>(int & i) {
if (data.empty()) {
while (data.size() < 5) {
data.push(0);
std::cin >> data.top();
}
}
i = data.top();
data.pop();
return *this;
}
explicit operator bool() const { return bool(std::cin); }
};
int main () {
reader r;
int i;
while (r >> i) {
std::cout << i << std::endl;
}
}
Example output:
$ g++ tt.cc -std=c++11 && echo "1 2 3 4 5 6 7 8 9 10" | ./a.out
5
4
3
2
1
10
9
8
7
6
A more straight forward approach would probably be something like this:
#include <iostream>
#include <vector>
int main () {
std::vector<int> buffer;
for (int i; std::cin >> i; ) {
buffer.push_back(i);
if (buffer.size() == 5) {
// do something with buffer
//std::vector<int> reversed(buffer.rbegin(), buffer.rend());
while (!buffer.empty()) {
std::cout << buffer.back() << "\n";
buffer.pop_back();
}
}
}
}
I want to create a matrix of 5 lines and 5 columns which contains values from 1 to 9. The following programs displays numbers from 1 to 25 instead, when I input 5 to the program..
#include <iostream>
using namespace std;
int a[20][20], n, x = 0;
int main()
{
cout << "n=";
cin >> n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
a[i][j] = x+1;
x = x+1;
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
I'm a c++ beginner, so maybe it's simple to do but i don't know how to make it show values from 1 to 9. This is the matrix I except:
1 2 3 4 5
6 7 8 9 1
2 3 4 5 6
7 8 9 1 2
3 4 5 6 7
There are some issues in your code.
C arrays or STL containers?
First off, a your matrix may only hold matrices as big as 20x20. Your program will silently fail if you enter n bigger than 20, because you will access memory out of bounds; which causes an undefined behavior (see other common UB cases here).
You may want to use a dynamic size array - A good way to achieve this is to use std::vector. Unfortunately, this isn't as comfortable to use as a C-style array with two dimensions - you can achieve the same access syntax using a std::vector<std::vector<int>>, but this is not very efficient (see this answer if you are interested why) nor quite comfortable.
The Boost C++ library provides a multidimensional array library. Once you get experienced enough, you may find an use in it.
<= or <? 0-index or 1-indexed?
Many programming languages today uses 0-indexing for arrays. This means the first element of the array is located at index 0, not 1. Some languages, such as Lua, doesn't do this.
This means you should iterate i and j from 0 to n. This also means n is excluded, so you should use <, not <=.
Filling the matrix with numbers from 1 to 9
Your code doesn't do anything so you get numbers from 1 to 9 - it only fills the matrix with numbers from 1 to n * n. You could change this using an if clause to set x every time it goes above 9:
if (x > 9) { x = 0; } // x = 0 because it will be 1 on the next iteration
That being said, there is more convenient, as #PMar's answer says. The modulo operator % will do the task as well.
a[i][j] = (x % 9) + 1;
x = (x % 9) + 1;
This way, you will get every number from 1 to 9.
Now, you can also do another cleanup: Why are you calculating x's next value, and only then setting it? You could assign the new x value before the assignment to your matrix's cell. This allows having clearer code, with less copy pasting, which implies better maintainability.
x = (x % 9) + 1;
a[i][j] = x;
Another code quality consideration
I cannot say if your original code source was indented like your question (before it was edited), but you should really indent your code, for the future you and other people that will have to read your code. It allows for much better readability.
Same goes for different parts of your code : Add some space! It only can get more readable if you make a clear distinction between even just expressions.
You need to use the modulus operator (%). If you want the values in the matrix to be as you have computed them, but only need to change the display, you would output the matrix values as follows:
cout << (a[i][j] % 10) << " ";
If you want the one-digit values to be in the matrix itself, you would instead change the increment on 'x' to the following:
x = (x+1) % 10;}
#include <iostream>
int main()
{
int a[5][5];
int x = 1;
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
if(x > 9)
x = 1;
a[i][j] = x;
x++;
}
}
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
if(a[i][j] < 10)
std::cout << " ";
std::cout << a[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
return 0;
}
I think the following code snippet is perfectly legal (it builds anyway on MS Visual Studio 2008, C++).
I use it to link to a 3rd party library. But I think because I am passing a pointer to a vector element instead of a regular pointer that the 3rd party library function expects, I get a run-time error
Invalid parameter detected by C-runtime library
What am I doing wrong here?
std::vector<int> vec_ints(27,0);
std::vector<double> vec_doub(27, 0.);
for(int i = 0; i < n; ++i) {
//-Based on my understanding when i >=27, STL vectors automatically reallocate additional space (twice).
vec_ints[i] = ...;
vec_doub[i] = ...;
}
const int* int_ptr = &vec_ints[0];
const double* doub_ptr = &vec_doub[0];
//-Func is the 3rd party library function that expects a const int* and const double* in the last 2 arguments.
func(...,...,int_ptr,doub_ptr);
But running this after building on MS Visual Studio 2008 (Windows Vista), leads to run-time error as mentioned above, viz.,
Invalid parameter detected by C runtime library
Haven't tested this on Linux yet and I sure would like to avoid copying the contents of the vector into an array just for this. Any ideas what is going on?
Further edit to confirm usage of Nick and Chris' recommendation and to continue discussion with Vlad et al; here's a code snippet:
#include <iostream>
#include <vector>
int main() {
for(int i=2; i<6; ++i) {
int isq = i*i;
std::vector<int> v;
v.reserve(4);
for(int j=0; j<isq; ++j) {
v.push_back(j);
}
std::cout << "Vector v: size = " << v.size() << " capacity = " << v.capacity()
<< "\n";
std::cout << "Elements: \n";
for(int k=0; k<v.size(); ++k) {
std::cout << v.at(k) << " ";
}
std::cout << "\n\n";
}
return 0;
}
Gives output:
Vector v: size = 4 capacity = 4
Elements:
0 1 2 3
Vector v: size = 9 capacity = 16
Elements:
0 1 2 3 4 5 6 7 8
Vector v: size = 16 capacity = 16
Elements:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Vector v: size = 25 capacity = 32
Elements:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22 23 24
So atleast for the usage in this context, where no explicit resize is used, it seems to work as intended/expected.
std::vector<T> expands if you are adding elements using std::vector<T>::push_back(T &), std::vector<T>::insert(iterator, T &) (thanks K-ballo) or explicitly calling std::vector<T>::resize(size_t). Otherwise, it doesn't expand.
std::vector<int> vec_ints;
vec_ints.reserve(27);
std::vector<double> vec_doub;
vec_doub.reserve(27);
for(int i = 0; i < n; ++i) {
vec_ints.push_back(...);
vec_doub.push_back(...);
}
const int* int_ptr = &vec_ints[0];
const double* doub_ptr = &vec_doub[0];
func(...,...,int_ptr,doub_ptr);
You want something like that
No, vector doesn't expand automatically. You need to expand it yourself:
if (n > 27)
vec_ints.resize(n, 0);
etc.
Why not just create the vectors with the correct size to begin with? Like so:
std::vector<int> vec_ints(n,0);
std::vector<double> vec_doub(n, 0.);
I am a java/C# developer and i am trying to write a C or C++ code to read data from a text file. this is very easily done in java and c# but not in c or c++.
the textfile i am reading looks like this:
a,b,c,d,e
1,0,1,1,0
0,1,1,0,0
0,0,0,1,1
i need to store the values in 2 arrays.
the 1st one is a 1D char array which will contain: a b c d e
the 2nd one is a 2D bool array which will contain:
1 0 1 1 0
0 1 1 0 0
0 0 0 1 1
how can i do this?
I suggest you at least make an attempt at what you are trying to do, to help you get started, here is a basic read out of the example data you provided. This example should be simple enough to allow you to expand it to meet other data sets.
#include <iostream>
#include <fstream>
int main() {
const int n_letters = 5;
const int n_columns = 5;
const int n_rows = 3;
char letters[n_letters];
bool booleans[n_rows][n_columns];
std::ifstream stream("myfile.txt");
if (stream) {
for (int i = 0; i < n_letters; ++i) {
stream >> letters[i];
std::cout << letters[i] << ',';
}
std::cout << '\n';
for (int i = 0; i < n_rows; ++i) {
for (int j = 0; j < n_columns; ++j) {
stream >> booleans[i][j];
std::cout << booleans[i][j] << ',';
}
std::cout << '\n';
}
}
return 0;
}
Reads the following text:
a b c d e
1 0 1 1 0
0 1 1 0 0
0 0 0 1 1
And outputs:
a,b,c,d,e
1,0,1,1,0
0,1,1,0,0
0,0,0,1,1
A first comment: when parsing a file, it's often useful to read
the file line by line, and then parse each line, using
std::istringstream, or boost::regex, or whatever other technique
you please. I like boost::regex, because it immediately
indicates if there is a syntax error, but carefully designed,
istream can as well.
The first thing, in any case, is to specify more precisely the
formats: Is there always just one letter? Are the numbers always
Just 0 and 1? Are there always exactly five values per line?
Until we know that, it's rather difficult to say more.
I have a std::vector. I want to create iterators representing a slice of that vector. How do I do it? In pseudo C++:
class InterestingType;
void doSomething(slice& s) {
for (slice::iterator i = s.begin(); i != s.end(); ++i) {
std::cout << *i << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
slice slice1 = slice(v, 1, 5);
slice slice2 = slice(v, 2, 4);
doSomething(slice1);
doSomething(slice2);
return 0;
}
I would prefer not to have to copy the elements to a new datastructure.
You'd just use a pair of iterators:
typedef std::vector<int>::iterator vec_iter;
void doSomething(vec_iter first, vec_iter last) {
for (vec_iter cur = first; cur != last; ++cur) {
std::cout << *cur << endl;
}
}
int main() {
std::vector v();
for (int i= 0; i < 10; ++i) { v.push_back(i); }
doSomething(v.begin() + 1, v.begin() + 5);
doSomething(v.begin() + 2, v.begin() + 4);
return 0;
}
Alternatively, the Boost.Range library should allow you to represent iterator pairs as a single object, but the above is the canonical way to do it.
I learnt Python before I learnt C++. I wondered if C++ offered slicing of vectors like slicing in Python lists. Took a couple of minutes to write this function that allows you to slice a vector analogous to the way its done in Python.
vector<int> slice(const vector<int>& v, int start=0, int end=-1) {
int oldlen = v.size();
int newlen;
if (end == -1 or end >= oldlen){
newlen = oldlen-start;
} else {
newlen = end-start;
}
vector<int> nv(newlen);
for (int i=0; i<newlen; i++) {
nv[i] = v[start+i];
}
return nv;
}
Usage:
vector<int> newvector = slice(vector_variable, start_index, end_index);
The start_index element will be included in the slice, whereas the end_index will not be included.
Example:
For a vector v1 like {1,3,5,7,9}
slice(v1,2,4) returns {5,7}
Taken from here:
std::vector<myvector::value_type>(myvector.begin()+start, myvector.begin()+end).swap(myvector);
Usage example:
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> indexes{3, 6, 9};
for( auto index : indexes )
{
int slice = 3;
std::vector<int> bar{1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int>( bar.begin() + index - slice, bar.begin() + index ).swap(bar);
std::cout << "bar index " << index << " contains:";
for (unsigned i=0; i<bar.size(); i++)
std::cout << ' ' << bar[i];
std::cout << '\n';
}
return 0;
}
Outputs:
bar index 3 contains: 1 2 3
bar index 6 contains: 4 5 6
bar index 9 contains: 7 8 9
As others have said, you can represent the "slice" as pair of iterators. If you are willing to use Boost, you can use the range concept. Then you will have even begin()/end() member functions available and the whole thing looks a lot like a container.
use boost range adapters. they are lazy:
operator|() is used to add new behaviour lazily and never modifies its
left argument.
boost::for_each(v|sliced(1,5)|transformed(doSomething));
doSomething needs to take range as input. a simple (may be lambda) wrapper would fix that.
You can represent those "slices" with a pair of iterators.
You don't need a pair of iterators to slice a vector. Three indexes will do because it allows you to create slices with steps:
static const int arr[] = {16,2,77,29,42};
vector<int> v (arr, arr + sizeof(arr) / sizeof(arr[0]) );
vector<int>::iterator i;
const int step = 2;
const int first = 0;
const int last = v.size()-1;
int counter=first;
for (i = v.begin()+first; counter<last; i+=step, counter+=step) {
// Do something with *i
cout << *i << endl;
}
Prints:
16
77
In this code, a counter is needed to track the position because not all iterators can do this.
It is possible to use slices with std::valarray. Which is an STL analogue of numpy.array in python. It support different vectorized operations like min, max, +,-, *, /, etc.
More info here.
std::slice(start, length, stride) allows to select and modify slices of an array without copying (documentation here).
The slicing would look like this:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | | | |
std::slice myslice=std::slice(1,5,1); // v v v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 20 30 40 50 6 7 8
Or with stride=2:
std::valarray<int> foo (9);
for (int i=0; i<9; ++i) foo[i]=i; // 0 1 2 3 4 5 6 7 8
// | | |
std::slice myslice=std::slice(1,3,2); // v v v
foo[myslice] *= std::valarray<int>(10,3); // 0 10 2 30 4 50 6 7 8
// | | |
foo[std::slice (0,3,3)] = 99; // v v v
// 99 10 2 99 4 50 99 7 8
std::cout << "foo:";
for (std::size_t n=0; n<foo.size(); n++)
std::cout << ' ' << foo[n];
std::cout << '\n';