I have a piece of code that was written by someone else before the New ISO come into effect.
The for LOOP in for (pa=a.begin(), i=0; pa != a.end(); ++pa) has a little trouble executing because of the i=0 part of the syntax. Also, I had to prefix the other for loop syntaxes to read for ( int i .....) with the int before the i. However, I don't know how to fix the int i=0 in this line: for (pa=a.begin ( ), i=0; pa != a.end ( ); ++pa). Please help me out.
for ( int i = 0; pa != a.end(); ++pa)
*pa = ++i;
for (int i=0; i<10; i++)
std::cout << "a[" << i << "]=" << a[i] << std::endl;
// int i; // note that this will work, but I do not want this extra line.
for (pa=a.begin(), i=0; pa != a.end(); ++pa)
std::cout << "a[" << i++ << "]=" << *pa << std::endl;
An extra declaration outside the for loop is the only sensible way to have two iteration variables of unrelated types in C++98 and later versions of the language. The initialiser can either be a single expression or a single declaration, and a declaration can't declare variables of multiple unrelated types.
If you really want a one-liner in this situation, then you could use this monstrosity:
for (int i = ((pa = a.begin()), 0); pa != a.end(); ++pa, ++i)
If you do that sort of thing regularly, then make sure that no-one who maintains your code knows where you live.
No, you can declare only variables of one type inside the for. If your problem is scope then you may enclose the loop inside a block (for some nice examples look boost source code for loop macros):
for ( int i = 0; pa != a.end(); ++pa)
*pa = ++i;
for (int i=0; i<10; i++)
std::cout << "a[" << i << "]=" << a[i] << std::endl;
{
int i = 0;
for (pa=a.begin(); pa != a.end(); ++pa)
std::cout << "a[" << i++ << "]=" << *pa << std::endl;
}
If you simply want to make it more nice then the answer is no, you can't.
EDIT
The best trick I saw to do what you need and to keep it clear is on this answer on SO. Instead of multiple variables you can use an unnamed struct declared inline:
for (struct { int i; iterator it; } d = { 0, pa.begin() }; d.it != a.end(); ++d.i, ++d.it )
std::cout << "a[" << d.i << "]=" << *d.it << std::endl;
It's a little bit more prolix (so I wonder if what you save with the extra line is re-payed) but you make clear your intent and you keep code readable (moreover you can use it to pack any number and any type of variables).
Related
So I did the next exercise, just with while loop:
Write a program that prompts the user for two integers.
Print each number in the range specified by those two integers.
Here is the code:
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The numbers between " << v1 << " and " << v2 << " are: " << std::endl;
while (v2 < v1 && ++v2 < v1)
{
std::cout << v2 << std::endl;
}
while (v1 < v2 && ++v1 < v2)
{
std::cout << v1 << std::endl;
}
}
Now I have to do it with the for loop, which I did like this:
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int a, b;
std::cin >> a >> b;
std::cout << "The numbers between " << a << " and " << b << " are: " << std::endl;
for (; a < b && ++a < b; a)
{
std::cout << a << std::endl;
}
for (; b < a && ++b < a; b)
{
std::cout << b << std::endl;
}
}
It looks almost the same, but it works.
My questions is: I'm I missing something about the for loop, could I do it simpler?
PD: Just for loop, I'm not in the If chapter yet, I want to go step by step on the "C++ Primer 5th edition".
for is specified in terms of while, you aren't missing anything.
for (init-statement conditionopt;
iteration-expressionopt) statement
produces code equivalent to:
{ init-statement while (condition) { statement
iteration-expression; } }
Except that
Names declared by the init-statement (if init-statement is a declaration) and names declared by condition (if condition is a
declaration) are in the same scope (which is also the scope of
statement).
continue in the statement will execute iteration-expression
Empty condition is equivalent to while(true)
from cppreference
You don't need anything in iteration-expression for(;;) is equivalent to while(true)
it would be more normal to increment in the iteration-expression, and not repeat almost the same test.
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int a, b;
std::cin >> a >> b;
std::cout << "The numbers between " << a << " and " << b << " are: " << std::endl;
for (; a < b; ++a)
{
std::cout << a << std::endl;
}
for (; b < a; ++b)
{
std::cout << b << std::endl;
}
}
The for loop is intended to loop between two numbers. The use of your for loops unreadable for it's intentions. Take a look at this
int end = 10;
for (int begin = 0; begin < end; ++begin){/*do something*/}
This is the standard structure of a for loop. Now for your example you will get the following
#include <algorithm>
if (a > b) std::swap(a, b);
for (int begin = a; begin <= b; ++begin){
std::cout << begin << std::endl;
}
There is no need on using something like a < b && ++a < b since a < b is contained in ++a < b condition. So just using ++a < b you will get the same results.
Now about the for you should write it like this just to make your code a bit clear:
for (; a < b; ++a)
{
std::cout << a << std::endl;
}
I am not using the initialization sentence as you have already initialized your variables, however I encorage you to initialize a in the for sentence
In general terms, the for is divided in three sections:
for (<initialization sentence>; <condition sentence>; <post-execution sentence>)
The initialization only runs when the for sentence is reached, and the loop is running while the condition is met. The post-execution it is normally used to increase or change state of the variables involved in the condition criteria. The only constraint you have is that condition must be a boolean sentence.
None of those sections should be an assigment, a common comparison or a variable increment. You could use whatever fits your requirements and met the for constraints.
To sum up, a for sentence is a 'wrapped' structure of a while. You could get the same results with both. The difference is on a cleaner image of your code and a better understanding of the algorithms.
The code in the question is somewhat confusing, because it tries to do several things at once. I'd separate them.
Instead of writing two loops, I'd just change the limits:
if (v2 < v1)
std::swap(v2, v1);
Now it's easy:
while (++v1 < v2)
std::cout << v1 << '\n';
Same thing for the for loop. After adjusting the limits, just do it:
for ( ; ++a < b; )
std::cout << a << '\n';
I have two double pointer array, which I want to print
but somehow I am not able to do it..
double *noise_feature = new double[5];
double *basic_feature = new double[39];
noise_feature_extraction(sig, len, noise_feature);
basic_feature_extraction(sig, len, basic_feature);
cout << "\n";
printf("Noice features are");
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
cout << *i << " ";
cout << "\n";
printf("Basic features are");
for (auto i = basic_feature.begin(); i != basic_feature.end(); ++i)
cout << *i << " ";
cout << "\n";
This gives error like this
Pan_Tompkins.cpp:992:29: error: member reference base type 'double *' is not a structure or union
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
~~~~~~~~~~~~~^~~~~~
Pan_Tompkins.cpp:992:57: error: member reference base type 'double *' is not a structure or union
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
I tried printing this way
printf("%g",noise_feature);
printf("%g",basic_feature);
This does not give error but also does not print anything.
How can I print this two double array to see their value?
You request a raw array on the heap and discard the info how many elements it has. Recall that
double *noise_feature = new double[5];
declares nothing but a pointer to double. The fact that you know it's a contiguous array of length 5 can be used in different way. Either you keep that magic number literal in your code;
for (auto value = noise_feature; value != noise_feature + 5; ++value)
// not maintainable, but works: ^^^^^^^^^^^^^^^^^
cout << *value << " ";
Or you go with a raw array on the stack. Here, the length is baked into the type and hence not lost. You could use a range-based for loop to iterate over it, for example.
double noise_features[5];
// ...
for (double value : noise_features)
std::cout << value << ' ';
However, the preferred solution is using either std::vector if the size of your sequence is only known at runtime, or std::array if it's a fixed-length sequence.
You declared two pointers
double *noise_feature = new double[5];
double *basic_feature = new double[39];
Pointers are scalar objects that do not have the member functions begin and end.
So you have to use the magic numbers 5 and 39 to output the allocated arrays pointed to by the pointers.
For example
cout << "\n";
printf("Noice features are");
for ( size_t i = 0; i < 5; ++i )
cout << noise_feature[i] << " ";
cout << "\n";
printf("Basic features are");
for ( size_t i = 0; i < 39; ++i )
cout << basic_feature[i] << " ";
cout << "\n";
The same can be done using pointers as for example
cout << "\n";
printf("Noice features are");
for ( auto p = noise_feature; p != noise_feature + 5; ++p )
cout << *p << " ";
cout << "\n";
printf("Basic features are");
for ( auto p = basic_feature; p != basic_feature + 39; ++p )
cout << *p << " ";
cout << "\n";
Pay attention to that instead of "manually" allocating dynamically arrays you could use the standard container std::vector as for example
#include <vector>
//...
std::vector<double> noise_feature( 5 );
//...
cout << "\n";
printf("Noice features are");
for ( const auto &item : noise_feature )
cout << item << " ";
cout << "\n";
//...
Arrays defined with statements like array_name[element_count] are not objects of any class!
Arrays are actually pointers to continuous memory. So, they don't have any methods and member functions. So your code will fail to compile. So instead of this:
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
Use this:
for (auto i = noise_feature; i != noise_feature + 5; ++i)
Or this:
for (auto i = std::begin(noise_feature); i != std::end(noise_feature); ++i)
Or you can store it in a std::vector<double> object. Also, why you used printf when C++ provides std::cout ?
I am trying to make an ArrayList class in C++ as a learning experience. Similar to the Java ArrayList class it is a dynamic array, the internal array is called 'content'. Unlike in Java I wanted my ArrayList to be able to take pointers and non-pointers. But I am getting a problem, I am using std::is_pointer::value to check whether the generic type is a pointer within a number of functions. If it is a pointer the function will need to preform differently to if it was not a pointer. My example below shows my printAll() function which is meant to print every element in the array on separate lines. If the generic type is a pointer the method needs to dereference each element in the array before printing them.
int main() {
ArrayList<int> a = ArrayList<int>();
a.add(1);
a.add(2);
a.add(3);
a.printAll();
cin.ignore();
}
#pragma warning(push)
#pragma warning(disable : 2100)
template<class T>
void ArrayList<T>::printAll() {
if (std::is_pointer<T>::value) {
for (int i = 0; i < this->occupiedSize; i++) {
cout << "[" << i << "] " << *this->content[i];
cout << endl;
}
} else {
for (int i = 0; i < this->occupiedSize; i++) {
cout << "[" << i << "] " << this->content[i];
cout << endl;
}
}
}
#pragma warning(pop)
On the line:
cout << "[" << i << "] " << *this->content[i];
I am getting warnings:
C2100: illegal indirection and
C2088: '<<': illegal for class
I'm assuming this is because the list is not of a pointer type and therefore cannot be dereferenced with *. But in a non-pointer list, std::is_pointer::value should return false and the code in that block is never executed anyway so it shouldn't be a problem. Disabling the warning doesn't seem to help.
If I do:
int main() {
ArrayList<int*> a = ArrayList<int*>();
a.add(new int(1));
a.add(new int(2));
a.add(new int(3));
a.printAll();
cin.ignore();
}
It works totally fine. Any ideas how I can solve this problem or how I can better implement this functionality?
I am using windows 10, Microsoft Visual Studio (latest version I believe).
This issue here is that even though you would never enter
if (std::is_pointer<T>::value) {
for (int i = 0; i < this->occupiedSize; i++) {
cout << "[" << i << "] " << *this->content[i];
cout << endl;
}
}
If T is a non pointer type the compiler will still compile that block of code. Since it has illegal syntax you get a compiler warning.
In the upcoming C++17 you can use constexpr if which will remove the code from the compilation if the condition is not true.
If you do not have access to a compiler that supports that feature then you will have to use SFINAE and have two overloads of the function. One for if T is a pointer type and one for when T is not a pointer type. That would look like
template<class T, std::enable_if_t<typename std::is_pointer<T>::value>* = nullptr>
void ArrayList<T>::printAll() {
for (int i = 0; i < this->occupiedSize; i++) {
cout << "[" << i << "] " << *this->content[i];
cout << endl;
}
}
template<class T, std::enable_if_t<typename !std::is_pointer<T>::value>* = nullptr>
void ArrayList<T>::printAll() {
for (int i = 0; i < this->occupiedSize; i++) {
cout << "[" << i << "] " << this->content[i];
cout << endl;
}
}
If I declare the following variables:
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
Then, this loop:
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
gives me different output ( a different set of addresses ), to this code:
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
Why? Aren't they semantically equivalent?
EDIT:
Well, my apologies to everyone that answered this one, I don't have the original code, it was a test that I did at home and it turns out that I deleted that code from my project. ( my broadband is not yet connected, so I waited till I got to work to post this ). Anyway - I am pretty sure that I was forgetting to initialise p. But the question of "aren't they semantically equivalent?" has been answered. Thanks.
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
p = array;
std::cout << '\n';
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
std::cout << '\n';
Gives me the same addresses. Did you accidentally forget p = array; in between?
If you remember to reset p before the second loop, they give the same result.
reset the pointer p's position.
The order of precedence is '++' first, then '*' and finally '&'.
So p++ will output the adresse of array[0] and &*p++ will first increment p, but this is postfix ! So the value of p (and not the value of p+1) will be given to * and then to &, so these are the same
Example:
std::cout << p << std::endl; // Output the adress of p
std::cout << &*p++<<std::endl; // p is increment but it is postfix, so value of p is used and printed
std::cout << &*++p<<std::endl; // p has been increment before and is then incremented again
std::cout << p++ << std::endl; // p has been incremented before, but here p is used first, then incremented
How to do the following in more stylish/short way?
for(i=container.begin(); i!=container.end(); ++i) {
if (i!=container.begin()) {
cout << ", ";
}
cout << *i;
j=i;
if (++j==container.end()) {
cout << "!" << endl;
}
}
Solutions like foreach are acceptable (actions on first and last elements need to be configurable, though).
P.S.
There are many answers that are handling first element, but not last. Here is what I mean by handling last element:
for(i=container.begin(); i!=container.end(); ++i) {
j=i;
if (i==container.begin()) {
cout << "[" << *i << "]" << endl;
} else if (++j==container.end()) {
cout << ", (" << *i << ")" << "!" << endl;
} else {
cout << ", " << *i;
}
}
Don't you think it's very easy to handle first element outside the cycle body? The real problem is the last one! I'm sorry for not being able to clarify the important point asking the question. I think I'll just accept the top ranked answer eventually.
Boost has next / prior which can sometimes help in such situations.
for(i=container.begin(); i!=container.end(); ++i) {
if (boost::next(i) == container.end()) {
std::cout << "!" << std::endl;
}
}
Although for this specific case, I'd simply output the first element, loop from second till last while always outputting the ',' and then output the '!' after the loop has ended. (as others have suggested already)
I don't see the point in moving the special cases inside the loop, and then checking inside the loop for them....
My advice here would be: there is no point in detecting anything within this loop !
Since your special cases are at the beginning and the end of your container, it is easy to remove their processing from within the loop.
The following function will print the contents of any container class whose elements can be <<'ed to an std::ostream:
template < class Container >
void print(Container const & container)
{
typename Container::const_iterator current = container.begin();
typename Container::const_iterator const end = container.end();
if (current != end)
{
std::cout << *current;
for (++current; current != end; ++current)
{
std::cout << ", " << *current;
}
std::cout << "!" << std::endl;
}
}
In your code,
if (i==container.end()) {
cout << "!" << endl;
}
will never happen.
My own approach would be to use the container size (I think size() is now constant time for all Standard Library containers). Maintain a count in the loop and you are at the end when count == size() - 1, and at the beginning when count == 0, obviously.
As container is not defined by you, I used the simplest - vector
template <class T>
string vector_join( const vector<T>& v, const string& token ){
ostringstream result;
for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); i++){
if (i != v.begin()) result << token;
result << *i;
}
return result.str();
}
//usage
cout << vector_join( container, ", " ) << "!";
Shift the ++i a bit:
i = container.begin();
while(i != container.end()) {
if (i != container.begin()) {
cout << ", ";
}
cout << *i;
if (++i == container.end()) {
cout << "!" << endl;
}
}
template < class TContainerType>
void print(TContainerType const & i_container)
{
typename TContainerTypeconst ::const_iterator current = i_container.begin();
typename TContainerTypeconst ::const_iterator const end = i_container.end();
if(current != end)
{
std::cout << *current++;
while(current != end)
std::cout << ", " << *current++;
}
std::cout << "!" << std::endl;
}
Take the second part out of the loop.
for(i=container.begin(); i!=container.end(); ++i) {
if (i != container.begin()) {
cout << ", ";
}
cout << *i;
}
cout << "!" << endl;