I am reading C++ primer book and completely don't understand one line:
using int_array = int[4];
typedef int int_array[4]; // This line
for (int_array *p = ia; p != ia + 3; ++p) {
for (int *q = *p; q != *p + 4; ++q)
cout << *q << ' '; cout << endl;
}
Ok typedef is same as using. Does it mean int[4][4] is now int and how to understand that? And what type is int_array in for loop?
Thanks
TL;DR
Both are doing the exact same thing: Defining int_array as an alias of an array of 4 ints
Making Sense of the Syntax
using has a nice A = B notation that is generally much easier to understand.
using alias = type;
typedef's notation is not quite backward. For a simple typedef
typedef type alias;
but more complicated typedefs tend to sprawl. I suspect the syntax was modeled after how one would define a variable, but I can't find where I packed my copy of the old K&R C programming book and can't look that up at the moment.
int int_array[4];
would define int_array to be an array of 4 ints. Slapping typedef on the front
typedef int int_array[4];
makes int_array a type alias instead of a variable.
Another example,
int * intp;
Defines intp to be a pointer to an int.
typedef int * intp;
Defines intp to be an alias to the type pointer to an int.
This gets ugly with more complicated data types as the name of the typedefed alias may be buried somewhere in the middle of the definition. A typedefed function pointer for example:
typedef void (*funcp)(param_t param1, param_t param2, ...);
vs using
using funcp = void (*)(param_t param1, param_t param2, ...);
Making a 2D Array
If you want a 2D array you could
using int_array2D = int[4][4];
or you could define an array of int_array
using int_array2D = int_array[4];
And of course that means you can
using int_array3D = int_array2D[4];
and keep on going until the cows come home or you've packed on so many dimensions that The Doctor's brain melts.
This line does nothing as it is redundant
The lines
using int_array = int[4];
and
typedef int int_array[4];
do the same thing. See reference for using and typedef. You can leave one or the other out and the behaviour is the same. It is not an error to have two different declarations, as they are not conflicting (they do the exact same thing).
The first way of doing it (using the using keyword) was introduced with C++11 and is in my opinion easier to read, so I prefer it over the typedef version.
Both type aliases are the same:
Type alias, alias template (since C++11):
Type alias is a name that refers to a previously defined type (similar to typedef):
using identifier attr(optional) = type-id ;
so you may use:
typedef int int_array[4];
or you may just use (it is the same as above):
using int_array = int[4];
When you need to address the memory with 4*sizeof(int) steps, e.g. if the system int size is 4 bytes, then the memory step size is 4*4=16 bytes. even you may use int_array *p; in this case ++p advances p by one memory step e.g. 16 bytes.
see:
1- working sample with using int_array = int[4];:
#include <iostream>
using std::cout; using std::endl;
int main()
{
int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
// a range for to manage the iteration
// use type alias
using int_array = int[4];
for (int_array& p : ia)
for (int q : p)
cout << q << " ";
cout << endl;
// ordinary for loop using subscripts
for (size_t i = 0; i != 3; ++i)
for (size_t j = 0; j != 4; ++j)
cout << ia[i][j] << " ";
cout << endl;
// using pointers.
// use type alias
for (int_array* p = ia; p != ia + 3; ++p)
for (int *q = *p; q != *p + 4; ++q)
cout << *q << " ";
cout << endl;
return 0;
}
output 1:
0 1 2 3 4 5 6 7 8 9 10 11
0 1 2 3 4 5 6 7 8 9 10 11
0 1 2 3 4 5 6 7 8 9 10 11
2- working sample using typedef int int_array[4];:
#include <iostream>
using std::cout; using std::endl;
int main()
{
int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
// a range for to manage the iteration
// use type alias
typedef int int_array[4];
for (int_array& p : ia)
for (int q : p)
cout << q << " ";
cout << endl;
// ordinary for loop using subscripts
for (size_t i = 0; i != 3; ++i)
for (size_t j = 0; j != 4; ++j)
cout << ia[i][j] << " ";
cout << endl;
// using pointers.
// use type alias
for (int_array* p = ia; p != ia + 3; ++p)
for (int *q = *p; q != *p + 4; ++q)
cout << *q << " ";
cout << endl;
return 0;
}
output 2(same):
0 1 2 3 4 5 6 7 8 9 10 11
0 1 2 3 4 5 6 7 8 9 10 11
0 1 2 3 4 5 6 7 8 9 10 11
Ref: https://github.com/Mooophy/Cpp-Primer/blob/master/ch03/ex3_44.cpp
Note: use -std=c++11 for compile/link.
Related
I am writing a simple C++ program that should combine all elements of an integer array to form one number. Eg. {4,5,6} --> should be 456. But my output is one less than the original number. i.e instead of 456, I am getting 455. Sometimes my program works fine and sometimes not. Can someone please explain to me what is causing this unpredictible behaviour? Thank You!!
Please take a look at my code:
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int main()
{
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = A[x]*pow(10,lengthA-1-x) + num;
}
printf("%d\n", num ); // My O/P is 45677
}
As mentioned by Bob__, pow is a function for doubles and other floating-point types. For this specific algorithm, instead, we can do this:
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = num*10 + A[x];
}
At each step, this multiplies the previous number by 10, and makes the digit correct at that place.
E.g.
Step 1: num = 0*10 + 4 == 4
Step 2: num = 4 * 10 + 5 == 40 + 5 == 45
Step 3: num = 45 * 10 + 6 == 450 + 6 == 456
Step 4: num = 456 * 10 + 7 == 4560 + 7 == 4567
Step 5: num == 4567 * 10 + 8 == 45670 + 8 == 45678
From this simple problem you can already learn quite a bit to improve your C++ code.
Example :
// #include <bits/stdc++.h> // NO : https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h
// using namespace std // NO : https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
#include <iostream> // include only what you need for std::cout
int main()
{
int values[]{ 4,5,6,7,8 }; // no need for an =
int num{ 0 };
// prefer range based for loops
// they will not run out of bounds
// https://en.cppreference.com/w/cpp/language/range-for
for (const int value : values)
{
num *= 10;
num += value;
}
// avoid printf, use std::cout with C++20 std::format for formatting
// https://stackoverflow.com/questions/64042652/is-printf-unsafe-to-use-in-c
// https://en.cppreference.com/w/cpp/utility/format/format
std::cout << "num = " << num << "\n";
return 0;
}
Here is another way for this problem. You can use string to convert this numbers as you need.
With this loop, we convert each number to string and pase it to end of the num string. At the end, you have the number as you need as string. If you need that number as integer, you can conver it back at the end of the loop. To conver string to int you can check this :Converting String to Numbers
#include <iostream> //include to use cout
#include <string> // include to use string
using namespace std;
int main() {
int A[5] = {4,5,6,7,8}; // input array
int lengthA = sizeof(A) / sizeof(A[0]); // size of array
std::string num = "";
for(int i=0; i<lengthA; i++){
num += std::to_string(A[i]);
}
std::cout << "Number : " << num;
}
In addition to jh316's solution;
#include <iostream>
using namespace std;
int A[] = {4,5,6,7,8};
int num = 0;
int main()
{
for(int i: A){
num = num * 10 + i;
}
cout << num;
}
Description of the code:
Initial state of the variable: num = 0
For each iteration the num variable is:
1. num = 0 * 10 + 4 = 4
2. num = 4 * 10 + 5 = 45
3. num = 45 * 10 + 6 = 456
4. num = 456 * 10 + 7 = 4567
5. num = 4567 * 10 + 8 = 45678
Here when you call pow;
pow(10,lengthA-1-x)
your code is probably calling the following overload of std::pow:
double pow ( double base, int iexp );
And as can be seen, it returns a floating-point value which might have a rounding error. I ran your code on my system and the results were correct. However, your code might generate different results on different platforms. And it seems that this is the case in your system.
Instead, you can do this:
#include <cstdio>
#include <array>
#include <span>
constexpr int convertDigitsToNumber( const std::span<const int> digits )
{
int resultNum { };
for ( const auto digit : digits )
{
resultNum = resultNum * 10 + digit;
}
return resultNum;
}
int main( )
{
constexpr std::size_t arraySize { 5 };
// use std::array instead of raw arrays
constexpr std::array<int, arraySize> arrayOfDigits { 4, 5, 6, 7, 8 };
constexpr int num { convertDigitsToNumber( arrayOfDigits ) };
std::printf( "%d\n", num );
return 0;
}
As a result of using constexpr keyword, the above function will be evaluated at compile-time (whenever possible, which is the case in the above code).
Note regarding constexpr: Use const and constexpr keywords wherever possible. It's a very good practice. Read about it here constexpr (C++).
Note: If you are not familiar with std::span then check it out here.
I'm trying to use Eigen::Map to convert a pointer to raw data to a matrix and then free the original data, but keep getting some weird results as if the data in the Eigen::Map itself is deleted. I thought Eigen::Map performed a deep copy, though maybe this only happens after you convert the Eigen::Map to a matrix?
Here is some test code:
#include <Eigen/Dense>
int main(int argc, char const *argv[])
{
double* data = new double[4];
data[0] = 1;
data[1] = 2;
data[2] = 3;
data[3] = 4;
Eigen::Map<Eigen::Matrix<double, 2, 2, Eigen::RowMajor>> M(data);
Eigen::Matrix<double, 2, 2, Eigen::RowMajor> N = M.matrix();
std::cout << M << std::endl;
std::cout << N << std::endl;
delete[] data;
std::cout << M << std::endl;
std::cout << N << std::endl;
return 0;
}
Which results in this for me:
1 2
3 4
1 2
3 4
0 4.67506e-310
3 4
1 2
3 4
Is there something I'm doing wrong to get this behaviour from M in my example? Or are you supposed to convert it to N, like I've done? And is this inefficient, or does Eigen handle the assignment N = M.matrix() in some smart way?
I am using gcc compiler on ubuntu 16 , when I am printing value garbage value is getting displayed
#include <bits/stdc++.h>
int Arrayprint(int r, int l, unsigned int* q)
{
r = 3;
l = 4;
for (int i = 0; i < r; i++) {
for (int j = 0; j < l; j++) {
cout << *(q + sizeof(unsigned int) * (i * l + j)); //Garbage getting diplay
cout << *(q + i + j); //this working
cout << "\t";
}
}
cout << "size of unsigned int : " << sizeof(unsigned int); //4
cout << "size of int : " << sizeof(int); //4
}
int main()
{
unsigned int image[R][L] = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 } };
unsigned int* q = (unsigned int*)image;
Arrayprint(R, L, q);
}
From what I can tell, you understand at a low level that the address of the ith element of an array of T is base + sizeof(T) * i. That's correct, and it's good that you know that.
However, C and C++ handle this for you already. When you say q + i or q[i], it's actually compiling that into q + sizeof(T)*i anyway (with the latter also dereferencing the result).
So when you say q[sizeof(int)*i], that's actually compiling into *(q + sizeof(int)*sizeof(int)*i), which is clearly not what you wanted.
Thus, the index in the array you actually access is off by a factor of sizeof(int) and results in an out of bounds error, which is where your strange numbers are coming from.
I am using gcc compiler on ubuntu 16 , when I am printing value
garbage value is getting displayed
Instead of trying to fix what's broken in your raw array arimethics, consider using the standard containers:
#include <iostream>
#include <array>
constexpr size_t R = 3;
constexpr size_t L = 4;
using image_t = std::array<std::array<unsigned int, L>, R>;
void Arrayprint(const image_t& q) {
// range based for loops for convenience
for(auto& row : q) { // get references to each row
for(unsigned int colval : row) { // get the column values
std::cout << colval << "\t"; // print the values
}
std::cout << "\n";
}
}
int main() {
image_t image = {{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}};
Arrayprint(image);
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12
I am trying to grasp come concepts related to pointers and references. In the code snippet below, I call function shifting() several times from a for loop while iterating a linked list. With each iteration, int *ptr and int count are changed and passed to the function shifting(). Also, some other pointers and integer variables are passed by reference.
Doubts:
can I assign pointer references like shown in shifting() function? Same question for integer val references.
What is going on in the background? I read that references cannot be re-assigned. Is this not the case here every time shifting() is called?
please note, *ptr and count are NOT passed by reference. They are only to be read.
void shifting(int const * ptr, int const * &ptr6, int const * &ptr7, int const * &ptr8,
int count, int &val6, int &val7, int &val8)
{
ptr8 = ptr7; val8 = val7;
ptr7 = ptr6; val7 = val6;
ptr6 = ptr; val6 = count;
}
int main()
{
int const *ptr6 = NULL; int val6 = 0;
int const *ptr7 = NULL; int val7 = 0;
int const *ptr8 = NULL; int val8 = 0;
int count = 0;
// myList: a linked-list
// front(): gives first element of list
// back(): gives last element of list
// nextElement(): gives next element of list
for (int *ptr = myList.front(); ptr != myList.back(); ptr = nextElement();)
{
count++;
shifting(ptr, ptr6, ptr7, ptr8, count, val6, val7, val8);
}
}
EDIT: I tried the above example (after posting here) with only integer part as shown below:
#include <iostream>
using namespace std;
void shifting( int i, int &val6, int &val7, int &val8 )
{
val8 = val7;
val7 = val6;
val6 = i;
}
int main()
{
int val6 = 0;
int val7 = 0;
int val8 = 0;
for (int i = 1; i <= 10; i++)
{
shifting(i, val6, val7, val8);
cout <<"i: "<<i<<" val6: "<<val6<<" val7: "<<val7<<" val8: "<<val8<<endl;
}
return 0;
}
I got this output as below. How come references are being re-assigned??? I read they are not supposed to reassign.
i: 1 val6: 1 val7: 0 val8: 0
i: 2 val6: 2 val7: 1 val8: 0
i: 3 val6: 3 val7: 2 val8: 1
i: 4 val6: 4 val7: 3 val8: 2
i: 5 val6: 5 val7: 4 val8: 3
i: 6 val6: 6 val7: 5 val8: 4
i: 7 val6: 7 val7: 6 val8: 5
i: 8 val6: 8 val7: 7 val8: 6
i: 9 val6: 9 val7: 8 val8: 7
i: 10 val6: 10 val7: 9 val8: 8
can I assign pointer references like shown in shifting() function? Same question for integer val references.
Yes. But when you do so, you are assigning to the referent, not the reference.
What is going on in the background?
This is what's (effectively) going on in the background. That is to say, if you wanted to achieve the same effect without references, you might do this:
void shifting(int const * ptr, int const ** ptr6, int const ** ptr7, int const ** ptr8,
int count, int* val6, int *val7, int *val8)
{
*ptr8 = *ptr7; *val8 = *val7;
*ptr7 = *ptr6; *val7 = *val6;
*ptr6 = ptr; *val6 = count;
}
And at the place where you call it:
shifting(ptr, &ptr6, &ptr7, &ptr8, count, &val6, &val7, &val8);
I read that references cannot be re-assigned.
That is correct. Although I prefer the term re-bound. You can do what looks like an assignment to a reference. But that is actually an assignment to the referent. In fact, after a reference is created, thereafter, its name acts as an alias to the referent. Any operation on the reference (with the exception of decltype) is as if done on the referent.
Is this not the case here every time shifting() is called?
No. When you use the assignment operator on a reference, you are actually assigning to the referent, not the reference.
Your example is extremely convoluted, perhaps something simpler will clear things up.
int a = 0;
int b = 77;
int& ra = a; // ra is a reference to a, and always will be
int& rb = b; // rb is a reference to b, and always will be
ra = b; // ra is still a reference to a, but now a == 77
ra = 999; // now a == 999
rb = ra; // rb is still a reference to b, but now b == 999
To further clarify, the above example is exactly equivalent to this:
int a = 0;
int b = 77;
a = b;
a = 999;
b = a;
Or this example using pointers:
int a = 0;
int b = 77;
int* pa = &a; // pa is a pointer to a, this can change, but won't in this example
int* pb = &b; // pb is a pointer to b, this can change, but won't in this example
*pa = b; // pa is still a pointer to a, but now a == 77
*pa = 999; // now a == 999
*pb = *pa; // pb is still a pointer to b, but now b == 999
I think you may partly be confusing yourself by re-using variable names between the function and the caller: For example, within shifting val6 is a local variable, bound to whatever it was called with, which just happens to be an external variable with the same name.
#include <iostream>
void test(int& i) {
std::cout << "test/i = " << i << '\n';
}
int main() {
int i = 1;
int j = 42;
test(i);
test(j);
}
This outputs (see http://ideone.com/lRNINP)
test/i = 1
test/i = 42
The significance of being a local reference is that it goes away at the end of the function iteration and is reformed with the new arguments at the next iteration.
I got this output as below. How come references are being re-assigned???
They aren't, the values are simply shifting as your function appears to aim to do: (see http://ideone.com/oCmOPk)
#include <iostream>
int main() {
int i = 0;
int& ir = i; // not an assignment, a binding
ir = 1; // pass '1' thru 'ir' to 'i'.
std::cout << "ir " << ir << ", i " << i << "\n";
int j = 0;
int& jr = j;
jr = 42; // pass '42' thru 'jr' to 'j'
std::cout << "jr " << jr << ", j " << j << "\n";
ir = jr; // pass the *value* of 'jr' thru 'ir' to 'i'
j = 99;
// if ir is rebound to jr, both of these will be 99.
std::cout << "ir " << ir << ", i " << i << "\n";
std::cout << "jr " << jr << ", j " << j << "\n";
}
Output:
ir 1, i 1
jr 42, j 42
ir 42, i 42
jr 99, j 99
I would like to know what the most efficient c++ implementation of the following matlab idiom is.
Suppose I have 3 vectors in matlab, x, y and idx.
x = [13,2,5.5,22,107]
y = [-3,100,200]
idx = [1,2,5]
I want to replace positions 1,2 and 5 of x with the contents of y. In matlab I do
x[idx] = y
What is the best way to do this in c++?
The Armadillo library probably comes closest as one of its goals is to make things easy for folks used to Matlab.
Here is a short example (and uvec is a typdef for vector of unsigned ints)
// set four specific elements of X to 1
uvec indices;
indices << 2 << 3 << 6 << 8;
X.elem(indices) = ones<vec>(4);
Obviously, the right-hand side could be any other vector of the same dimension as the index.
But there are few language-imposed constraints you cannot overcome:
zero-based indexing at the C++ level (which you could alter, but few C / C++ programmers will consider it a good idea)
certain operators, including [
A loop seems simple enough, although it can be made simpler with a helper function.
// helper function to get the size of an array
template<typename T, size_t S>
constexpr size_t size(T (&)[S])
{
return S;
}
// loop
for (size_t i = 0; i < size(idx); ++i) x[idx[i]] = y[i];
Of course, here you should check that y is large enough:
If you want it in pretty basic C++ (with no prizes for elegance) try this:
double x[] = { 13.0, 2.0, 5.5, 22.0, 107.0 };
double y[] = { -3.0, 100.0, 200.0 };
size_t idx[] = { 1, 2, 5 };
for ( size_t i = 0; i < sizeof(x)/sizeof(double); ++i )
cout << x[i] << " ";
cout << endl;
// Make a mutable copy of x
double x1[ sizeof(x)/sizeof(double) ];
std::copy( x, x + sizeof(x)/sizeof(double), x1 );
// The transformation
for ( size_t i = 0; i < sizeof(idx)/sizeof(double); ++i )
x1[idx[i]] = y[i];
for ( size_t i = 0; i < sizeof(x)/sizeof(double); ++i )
cout << x1[i] << " ";
cout << endl;
Note exactly pretty, but it does give the following:
13 2 5.5 22 107
-3 100 5.5 22 200
(Note that I've assumed that the indexing starts from 1 rather than 0 in idx)