I am a beginner to C++ syntax. Now, I need to create an mxn 2D array in C++ to use it in another project. I have looked at other answers which involve using tools like vector, etc. Many tools are not working on my Visual Studio 15 i.e. for vector I can not define with std::vector without a message like vector is not in std. So, I have wrote the following code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int i; int j; int row[5][10] = {};
for (int j = 0; j < 10;)
for (int i = 0; i < 5;)
{
row[i][j] = 500;
int printf(row[i][j]);
i++;
j++;
cout << "Array:" << row[i][j] << endl;
}
return 0;
}
Surely, this is not the correct syntax. So the output is beyond my expectation. I want to create an m*n array with all the elements being the same integer; 500 in this case. That is, if m=3, n=2, I should get
500 500 500
500 500 500
There's a couple things wrong with your current code.
The first for loop is missing curly brackets
You're redefining int i and int j in your for loop. Not a complilation issue but still an issue.
You're using printf incorrectly. printf is used to output strings to the console. The correct line would be printf("%d", row[i][j]);
If you want to use a vector, you have to include it using #include <vector>. You can use a vector very similar to an array, but you don't have to worry about size.
You seem to be learning. So, I did minimal correctios to make it work. I suggest you to make modifications as per your needs.
#include <iostream>
using namespace std;
int main()
{
int row[5][10] = {};
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 5; i++) {
row[i][j] = 500;
cout << row[i][j] << " ";
}
cout << endl;
}
return 0;
}
Care and feeding of std::vector using OP's program as an example.
#include <iostream>
#include <vector> // needed to get the code that makes the vector work
int main()
{
int m, n; // declare m and n to hold the dimensions of the vector
if (std::cin >> m >> n) // get m and n from user
{ // m and n are good we can continue. Well sort of good. The user could
// type insane numbers that will explode the vector, but at least they
// are numbers.
// Always test ALL user input before you use it. Users are malicious
// and incompetent <expletive delteted>s, so never trust them.
// That said, input validation is a long topic and out of scope for this
// answer, so I'm going to let trapping bad numbers pass in the interests
// of keeping it simple
// declare row as a vector of vectors
std::vector<std::vector<int>> row(m, std::vector<int> (n, 500));
// breaking this down:
// std::vector<std::vector<int>> row
// row is a vector of vectors of ints
// row(m, std::vector<int> (n, 500));
// row's outer vector is m std::vector<int>s constructed with
// n ints all set to 500
for (int j = 0; j < n; j++) // note: j++ has been moved here. This is
// exactly what the third part of a for
// statement is for. Less surprises for
// everyone this way
// note to purists. I'm ignoring the possible advantages of ++j because
// explaining them would muddy the answer.
// Another note: This will output the transverse of row because of the
// ordering of i and j;
{
for (int i = 0; i < m; i++) // ditto I++ here
{
// there is no need to assign anything here. The vector did
// it for us
std::cout << " " << row[i][j]; // moved the line ending so that
// the line isn't ended with
// every column
}
std::cout << '\n'; // end the line on the end of a row
// Note: I also changed the type of line ending. endl ends the line
// AND writes the contents of the output stream to whatever media
// the stream represents (in this case the console) rather than
// buffering the stream and writing at a more opportune time. Too
// much endl can be a performance killer, so use it sparingly and
// almost certainly not in a loop
}
std::cout << std::endl; // ending the line again to demonstrate a better
// placement of endl. The stream is only forced
// to flush once, right at the end of the
// program
// even this may be redundant as the stream will
// flush when the program exits, assuming the
// program does not crash on exit.
}
else
{ // let the use know the input was not accepted. Prompt feedback is good
// otherwise the user may assume everything worked, or in the case of a
// long program, assume that it crashed or is misbehaving and terminate
// the program.
std::cout << "Bad input. Program exiting" << std::endl;
}
return 0;
}
One performance note a vector of vectors does not provide one long block of memory. It provides M+1 blocks of memory that may be anywhere in storage. Normally when a modern CPU reads a value from memory, it also reads values around it off the assumption that if you want the item at location X, you'll probably want the value at location X+1 shortly after. This allows the CPU to load up, "cache", many values at once. This doesn't work if you have to jump around through memory. This means the CPU may find itself spending more time retrieving parts of a vector of vectors than it does processing a vector of vectors. The typical solution is to fake a 2D data structure with a 1D structure and perform the 2D to 1D mapping yourself.
So:
std::vector<int> row(m*n, 500);
Much nicer looking, yes? Access looks a bit uglier, though
std::cout << " " << row[i * n + j];
Fun thing is, the work done behind the scenes converting row[j][i] to a memory address is almost identical to row[j*n+i] so even though you show more work, it doesn't take any longer. Add to this the benefits you get from the CPU successfully predicting and reading ahead and your program is often vastly faster.
Related
I have tried to solve the following problem: "n numbers are given. For every one of them, calculate the sum 1+(1+2)+(1+2+3)+...+(1+2+3+...+x) and output the results in a separate vector". I have gotten a formula for the sum and have implemented it into c++. The code seems to be working perfectly on vs code, but when I upload it to the website where I got the problem from I get 0 points, with the explanation: Caught fatal signal 11. I have read some articles but none of them have helped me crack the problem. Here is the code:
#include <iostream>
#define N 1000000
using namespace std;
int v[N], s[N];
int main()
{
int n, i;
cin >> n; // user inputs number of elements
for(i = 0; i < n; i++)
{
cin >> v[i]; // user inputs the elements
s[i] = v[i]*(v[i] + 1)*(v[i] + 2) / 6; // another vector is calculated using the formula
cout << s[i] << " ";
}
return 0;
}
Your problem is two fold. One, you're not using vectors, you're using C-style arrays. And two, you're running out of memory due to the size of your C-style arrays.
C-style arrays are allocated on the stack, and there is only limited memory on the stack. So if you allocate, say, two arrays of size, I don't know, 1000000, you might run into some memory issues.
On the other hand, C++ vectors are more modern, allow for dynamic resizing (useful for when you don't know how many elements you're going to have, I doubt you'll have 1000000), and it is also memory stored on the heap, giving you a lot more breathing room when it comes to memory.
Vectors work like this:
#include <vector>
std::vector<int> vec; // creates the vector
vec.push_back(5); // adds an element equal to 5 to the vector, vec size is now 1
vec.push_back(6); // adds an element equal to 6 to the vector, vec size is now 2
std::cout << vec[0]; // elements are accessed just like a C-style array
I've recently started learning c++ after 5 years with python and am struggling quite a bit when it comes to loops. the whole for(;;) business.
in python i was used to:
for x in y:
print(x)
> x
> y
> z
however in c++ i seem to need two semi-colons like
for(;;)
what i would like to do is print the paths of my directories given in the below code. Thank you for your time!
#include <windows.h>
#include <string>
#include <iostream>
#pragma comment(lib, "user32.lib")
using namespace std;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// -- main
int main(void) {
// -- console
SetConsoleTextAttribute(hConsole, 12);
// -- paths
string ScanDir[2] = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
// -- loops
for (int i = 0; i < ScanDir->length(); ++i) {
string ss = ScanDir[i];
cout << ss.c_str() << "\n";
}
return 0;
}
here is the error:
error screenshot
In C++ arrays are not objects in the OOP sense and do not have methods. They are just a dumb block of memory.
ScanDir->length()
is not getting the length of the array. Instread ScanDir is decaying to a pointer to the first string in the array and length is being called on this string. As a result
for (int i = 0; i < ScanDir->length(); ++i)
iterates length of the first string times, not length of the array, and shoots off the end of the array and into the unknown. This invokes Undefined Behaviour which in this case lead to a crash.
The smart thing to do is use a Range-based for loop
for (const auto & dir: ScanDir) {
cout << dir.c_str() << "\n";
}
which figures out the dimensions for you. Some additional reading on the const auto & bit: What is the correct way of using C++11's range-based for?
You can also use
for (int i = 0; i < std::size(ScanDir); ++i)
if compiling to C++ 17 or better or replace the magic number 2 in
string ScanDir[2] = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
with a constant that can be used wherever the size of the array is required.
Another alternative is replace the array with a smarter container like std::array
std::array<std::string, 2> ScanDir = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
which has a size method.
ScanDir->length() is the length of your strings which is notably greater than 2. You can either use 2 as upper loop boundary or sizeof(ScanDir) / sizeof(ScanDir[0]), or type the loop itself as for(auto const &ss: ScanDir) count << ss.c_str() << '\n';.
i am stuck on a problem where, after taking input of an array and sorting it and not doing any operation on it at all, the output shows a different array?
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long int c[n],h[n],a[n];
for(int i=0;i<n;i++){
cin>>c[i];
}
for(int i=0;i<n;i++){
cin>>h[i];
}
sort(h,h+n);
for(int i=0;i<n;i++){
a[i]=0;
}
int i=0;
int begin=(i+1)-c[i];
int end = (i+1)+c[i];
int j=begin;
while(i<n){
a[j-1]++;
j++;
if(j>end){
i++;
begin=(i+1)-c[i];
end= (i+1)+c[i];
j=begin;
}
}
sort(a,a+n);
for(int i=0;i<n;i++){
cout<<h[i]<<" ";
}
}
return 0;
}
input for h[]={8,8,8,8,8}..n=5
output h[]={10,10,9,9,8}
Here is a version of your code written in reasonably decent C++. I didn't touch the loop in the middle because I have no clue what it's doing. You're using obscure variable names and no comments and doing all kinds of bizarre things with indexes and mixing them up with user input.
Now, reading indexes from user input and using them isn't bad, though in a real program you'd want to be doing lots of bounds checking on that input to make sure people weren't feeding you bad data. But doing all that stuff with such poorly named variables with no explanation is going to leave anybody looking at it scratching their head. Don't do that.
Also, avoid the use of begin and end as variable names, especially if they hold indexes. In most cases it will confuse things terribly as begin and end are important identifiers in the standard library and always refer to iterators, which are sort of like indexes, but most definitely not indexes, adding greatly to the confusion. beginidx and endidx could be acceptable substitutes in this case.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using ::std::vector;
using ::std::sort;
using ::std::copy_n;
using ::std::copy;
using ::std::fill;
using ::std::istream_iterator;
using ::std::ostream_iterator;
using ::std::cin;
using ::std::cout;
int main() {
// your code goes here
using vec_el_t = long long int;
int t;
cin >> t;
while (t--) {
int const n = []() { int n; cin >> n; return n; }();
vector<vec_el_t> c{n}, h{n}, a{n};
copy_n(istream_iterator<vec_el_t>{cin}, n, c.begin());
copy_n(istream_iterator<vec_el_t>{cin}, n, h.begin());
// Suggested debugging code:
// cout << "h before sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
sort(h.begin(), h.end());
// Suggested debugging code:
// cout << "h after sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
fill(a.begin(), a.end(), 0);
// Weird, unexplained algorithm begins here
int i = 0;
int begin = (i + 1) - c[i];
int end = (i + 1) + c[i];
int j = begin;
while (i < n) {
a[j - 1]++;
j++;
if (j > end){
i++;
begin = (i + 1) - c[i];
end = (i + 1) + c[i];
j = begin;
}
}
// Weird unexplained algorithm ends here
sort(a.begin(), a.end());
copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
}
return 0;
}
Changes made... Use vector not a variable length array, which isn't valid C++ anyway and will only work in g++ and clang. Don't use explicit loops if there is an algorithm that will do the job. Try to make as many things const as you can so you can make sure that the compiler catches it if you try to change things you didn't mean to change. Avoid using std; and if you want to import names from ::std import exactly the ones you need. Don't use compiler or library implementation specific header files and use the ones from the standard instead (i.e. no bits/stdc++.h).
As for your problem, I have no idea. I suspect that the index manipulation combined with looping isn't doing what you expect. If you print out the arrays before and after sorting, you will discover that sort only alters order, and not content.
As a general rule, always suspect your own code first and make absolutely sure it's correct. And if you really think it's the library code, prove it beyond a shadow of a doubt before coming here to ask why the library isn't doing what it says it does.
The complicated code I didn't touch looks rife with opportunities for out-of-bounds access, and that results in undefined behavior, which means your program might do absolutely anything in that case. You might change uses of operator [] with calls to the at function (one of the many perks of using vector) instead. That way, attempts at out-of-bounds access will throw an exception.
Within these lines you are accessing a outside its limits:
int i=0;
int begin=(i+1)-c[i]; // begin = 1 - c[0]; <<-- this could be arbitrarily small!
int end = (i+1)+c[i]; // unrelated
int j=begin; // also equal to 1-c[0]
while(i<n){
a[j-1]++; // increment a[-c[0]] which is UB unless c[0]==0
This means undefined behavior (UB), i.e., it could do nothing, it could segfault, or (what apparently happened in your case) access elements of an adjacent data structure.
In a larger numerical computation, I have to perform the trivial task of summing up the products of the elements of two vectors. Since this task needs to be done very often, I tried to make use of the auto vectorization capabilities of my compiler (VC2015). I introduced a temporary vector, where the products are saved in in a first loop and then performed the summation in a second loop. Optimization was set to full and fast code was preferred. This way, the first loop got vectorized by the compiler (I know this from the compiler output).
The result was surprising. The vectorized code performed 3 times slower on my machine (core i5-4570 3.20 GHz) than the simple code. Could anybody explain why and what might improve the performance? I've put both versions of the algorithm fragment into a minimal running example, which I used myself for testing:
#include "stdafx.h"
#include <vector>
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
// Prepare timer
LARGE_INTEGER freq,c_start,c_stop;
QueryPerformanceFrequency(&freq);
int size = 20000000; // size of data
double v = 0;
// Some data vectors. The data inside doesn't matter
vector<double> vv(size);
vector<double> tt(size);
vector<float> dd(size);
// Put random values into the vectors
for (int i = 0; i < size; i++)
{
tt[i] = rand();
dd[i] = rand();
}
// The simple version of the algorithm fragment
QueryPerformanceCounter(&c_start); // start timer
for (int p = 0; p < size; p++)
{
v += tt[p] * dd[p];
}
QueryPerformanceCounter(&c_stop); // Stop timer
cout << "Simple version took: " << ((double)(c_stop.QuadPart - c_start.QuadPart)) / ((double)freq.QuadPart) << " s" << endl;
cout << v << endl; // We use v once. This avoids its calculation to be optimized away.
// The version that is auto-vectorized
for (int i = 0; i < size; i++)
{
tt[i] = rand();
dd[i] = rand();
}
v = 0;
QueryPerformanceCounter(&c_start); // start timer
for (int p = 0; p < size; p++) // This loop is vectorized according to compiler output
{
vv[p] = tt[p] * dd[p];
}
for (int p = 0; p < size; p++)
{
v += vv[p];
}
QueryPerformanceCounter(&c_stop); // Stop timer
cout << "Vectorized version took: " << ((double)(c_stop.QuadPart - c_start.QuadPart)) / ((double)freq.QuadPart) << " s" << endl;
cout << v << endl; // We use v once. This avoids its calculation to be optimized away.
cin.ignore();
return 0;
}
You added a large amount of work by storing the products in a temporary vector.
For such a simple computation on large data, the CPU time that you expect to save by vectorization doesn't matter. Only memory references matter.
You added memory references, so it runs slower.
I would have expected the compiler to optimize the original version of that loop. I doubt the optimization would affect the execution time (because it is dominated by memory access regardless). But it should be visible in the generated code. If you wanted to hand optimize code like that, a temporary vector is always the wrong way to go. The right direction is the following (for simplicity, I assumed size is even):
for (int p = 0; p < size; p+=2)
{
v += tt[p] * dd[p];
v1 += tt[p+1] * dd[p+1];
}
v += v1;
Note that your data is large enough and operation simple enough, that NO optimization should be able to improve on the simplest version. That includes my sample hand optimization. But I assume your test is not exactly representative of what you are really trying to do or understand. So with smaller data or a more complicated operation, the approach I showed may help.
Also notice my version relies on addition being commutative. For real numbers, addition is commutative. But in floating point, it isn't. The answer is likely to be different by an amount too tiny for you to care. But that is data dependent. If you have large values of opposite sign in odd/even positions canceling each other early in the original sequence, then by segregating the even and odd positions my "optimization" would totally destroy the answer. (Of course, the opposite can also be true. For example, if all the even positions were tiny and the odds included large values canceling each other, then the original sequence produced garbage and the changed sequence would be more correct).
Please i am stuck at this question for half an hour and can't find why the error comes?
Problem code : test
Life, Universe and Everything
#include<iostream>
using namespace std;
int main()
{
int a[20],i;
cin>>a[0];
for(i=1;a[i-1]!=42;i++)
{
cout<<a[i]<<"\n";
cin>>a[i];
}
return(0);
}
Your code tries to access non-existing array elements, which causes segfault. You should stop your loop before the array index gets larger than the length of the array minus 1:
int a[20];
for (i = 1; i < 20 && a[i - 1] != 42; i++)
{
// ...
}
Apart from limit problem, your printing elements without initializing them
//for i = 1, a[i] is uninitialized
cout<<a[i]<<"\n";
On accessing a local variable (like this), you're likely to get garbage value.
This might be better substitute for what you are trying to do:
int a[20],i;
for(i=0;i < 20;i++)
{
cin>>a[i];
if (a[i] == 42)
break;
cout<<a[i]<<"\n";
}
You are trying to print the uninitialized data...
#include<iostream>
using namespace std;
int main()
{
int a[20],i;
cin>>a[0]; // a[0] uninitialized
for(i=1;a[i-1]!=42;i++)
{
cout<<a[i]<<"\n";
cin>>a[i];
}
return(0);
}
In the for loop get the data first and then print it.Your array size is 20 but you are trying to write upto 42.
You use array values before initializing them. C++ doesn't initialize non-static arrays for you unless you tell it to, so $DEITY knows what's in there. And technically, whatever's in there could cause an exception...or any number of other things. (For ints, on an x86 machine, that's actually highly unlikely. But elsewhere, it's possible.)
The user can enter more than 20 numbers. That's really just a special case of the more general problem, though: You allow unknown number of entries, but aren't able to accept them all without crashing.
If you don't know beforehand how many objects there will be, use a vector.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> a;
int entry;
cin>>entry;
// Oh, yeah. This. You really, *really* want to check `cin`.
// Otherwise, if the user decided to type "i like cheese", you'd loop
// forever getting zeros while cin tried to parse a number.
// With the array, that'd typically cause a segfault near instantly.
// With a vector, it'll just eat up all your CPU and memory. :P
while (cin && entry != 42) {
a.push_back(entry);
cout << entry << "\n";
cin >> entry;
}
return 0;
}