Need explanation of this, what actually is going on in this line? - c++

I am converting some C++ code into python. but I am not sure what exactly this line do.
vector<double>().swap(prev);
I compiled a simple program to see what it actually do, I found that it resizes the vector "prev" to 0.
#include <vector>
#include <iostream>
using namespace std;
int main(){
vector<int> ax;
ax.reserve(10);
for(int i=99; i<110; ++i){
ax.push_back(i);
}
for(int i=0; i<ax.size(); ++i){
std::cout << ax[i] << ' ';
}
vector<int>().swap(ax);
cout<<"\nAfter space \n";
cout<<"size is "<<ax.size();
for(int i=0; i<ax.size(); ++i){
std::cout << ax[i];
}
}

It's the result of the programmer deciding that, for some reason,
vector<int>().swap(ax);
is clearer than
ax.clear();
(The former exchanges the initially empty anonymous temporary vector<int>() with ax).
Somewhat less cyncially perhaps, the swap method might reset the capacity of the vector, whereas clear() never does. But it's still an odd choice: if you want the capacity to be reset then use
ax.clear();
ax.shrink_to_fit();
but even that is not guaranteed to reset the capacity; it's up to the implementation to decide.

Related

How do you put a letter triangle in a file?

So this is for some homework I am working on.
I've been working on this for days now. I need to print a letter triangle,
example
a
aa
aaa
to a file I create in the code. I have gotten the triangle part down using a for loop but cannot figure out how to get it into a file. here is what I have so far.
#include <iostream>
#include <fstream>
using namespace std;
char loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
cout << "a";
}
cout << endl;
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
if (week2.is_open()){
char result = loop();
{
week2 << loop() + "\n";
}
}
week2.close();
else cout << "file wasnt created";
return 0;
}
This is my first post on here and I am in my second week of learning C++ so any help would be appreciated immensely. Thank you all in advance.
You just need to replace cout with week2 everywhere, since cout is the terminal and week2 is your file.
Given the current structure of your code, where you write to cout in a function, you'll need to pass week2 as an argument to that function to use it there.
First of all, don't build a habit of using using namespace std
std::endl will put a linebreak, but it will also flush your stream. Put easily, outputting something is a really costly (=takes a long time) action in regard to other actions. To account for this, streams are buffered and once the buffer is full it will be flushed automatically. When you use std::endl the buffer might be flushed prematurely and this will tank performance. This is of course not really an issue in this small exercise, but I think it's still good to know. You can use \n instead. Although it might not look like it, it will provide a platform independend linebreak and should virtually always be used instead of std::endl.
Then consider what your function loop should do. Right now, you said it has return type char but it's not returning something. Therefore you should correct this and specify that this function is not returning anything, but just performing an action, hence return type void.
As suggested by John Zwinck, if you pass the stream as an argument, your function becomes more powerful and works with any kind of outgoing stream (i.e. std::ostream).
We can make the function even more generic, but I'll leave it to you to understand the code (if not, feel free to post a comment for clarification). Please note also, that loop is not a descriptive name. I have no idea what loop does. Always give your functions a name that makes it clear what they are doing.
#include <iostream>
#include <fstream>
void print_letter_triangle(std::ostream& out, char c = 'a', int count = 15)
{
for( int i = 0; i < count; i++ ){
for( int j = 0; j < i; j++ )
{
out << c;
}
out << '\n';
}
}
int main()
{
// for testing purposes
print_letter_triangle(std::cout);
print_letter_triangle(std::cout, 'b');
print_letter_triangle(std::cout, 'c', 7);
std::ofstream week2("week2assignment.txt");
if( week2.is_open() )
{
print_letter_triangle(week2);
week2.close();
}
else
{
std::cout << "Error: File wasn't created.\n";
}
return 0;
}
Lastly: Try to build an early habit of how you want to format your code, positions of curly braces, spaces around operators. Right now it was a little bit inconsistent (which might as well have been caused by putting it on StackOverflow).
There are a couple more nitpicks one can offer (for example, I changed the loop to start from 0 and used the < instead of the <= operator, you can convince yourself that this does not change the number of loop iterations. However, it is common in programming languages to start from 0 (as counter-intuitive as that might be at first). Finally, since negative counting values do not make sense in this loop, one might change int to unsigned int, but I felt that might have been a little too much. Feel free to do so on your own, if you wish).
I suggest you use this code:
#include <iostream>
#include <fstream>
using namespace std;
const char* loop()
{ for (int i = 1; i <=15; i++){
for (int j = 1; j <= i; j++){
return "a";
}
return "\n";
}
}
int main()
{
ofstream week2 ("week2assignment.txt");
week2 << loop() << "\n";
return 0;
}
You must return a value from your loop() function.

why is the sort() changing my input array?

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.

C++ program does nothing when executed

I am on Ubuntu 18.04 using the default c++ compiler it comes with. I am trying to get the size of vector required from the keyboard and eventually fill a vector with the increasing value of i in the makeGaps function. I would then like to return a filled vector to my variable x. However, when I run the code below, after it displays the "enter gap size" it does nothing even after I supply an integer. No output, no errors and also in code blocks all the debugger icons go gray. The code also doesn't
terminate and I cannot figure out what is wrong.
#include <iostream>
#include <vector>
using namespace std;
vector<int> makeGaps (int size){
vector<int> vectorOfGaps(size);
for(int i = 0; i <= vectorOfGaps.size();i++){
vectorOfGaps.push_back(i);
}
return vectorOfGaps;
}
void printV(vector<int> collection){
for (int i = 0; i <= collection.size(); i++){
cout << collection[i]<< '\n';
}
}
int main()
{ //get the number of gaps required
int numberOfGaps;
cout << "Enter gap size";
cin >> numberOfGaps;
vector<int> x = makeGaps(numberOfGaps);
printV(x);
return 0;
}
Also if i run it in the terminal that comes with vs code it crashes my machine.
Vectors in c++ are dynamically sized.
You can create a vector without a size argument in the constructor then push size number of elements like so:
vector<int> makeGaps (int size){
vector<int> vectorOfGaps;
for(int i = 0; i < size;i++){
vectorOfGaps.push_back(i);
}
return vectorOfGaps;
}
Edit: Also, as someone already pointed out in your comments, it appears you had an off by one error in your for loop. If the for loop runs until x <= size, it will iterate size+1 number of times.

creating mxn 2D array in c++ without using any external library

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.

Why is this code showing segmentation error on codechef?

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;
}