"Direction" of bidimensional arrays in C - c

as a C newcomer I'm a bit confused about bidimensional arrays.
If I want to represent a matrix of 3 rows and 5 columns, I guess the correct declaration is:
char a[3][5];
So, is this an array of 3 pointers to 5 arrays of chars or what?
How come whenever I try to cycle through it like the following it seems to read the wrong results?
int x, y;
for( x=0; x<3; x++ ){
for( y=0; y<3; y++ ){
printf( "%c", a[x][y] );
}
}
Are the following equivalent and correct ways to initialize it?
char a[3][5] = {
{1,0,0,0,1},
{1,0,0,0,1},
{1,0,0,0,1},
};
char a[3][5] = {1,0,0,0,1,
1,0,0,0,1,
1,0,0,0,1};
Thanks for any eventual upcoming explanation.
EDIT
Sorry the typos, the code is not copied. By the way, I keep on having them read like they where read in a vertical way, not in a horizontal one.
Also in the example in this tutorial http://www.cplusplus.com/doc/tutorial/arrays/ it reads the array in a way that is not streight-forward to me as it seems to work on a 5x3, HeightWidth, yx, colsrows structure instead of a 3x5, WidthHeight, xy. rowscols one:
#define WIDTH 5
#define HEIGHT 3
int jimmy [HEIGHT][WIDTH];
int n,m;
int main ()
{
for (n=0;n<HEIGHT;n++)
for (m=0;m<WIDTH;m++)
{
jimmy[n][m]=(n+1)*(m+1);
}
return 0;
}

Just for what it is and what not.
char a[3][5];
There are no pointers involved. A multi dimensional array like that is an array of arrays of .... and so on. In your case, you have an array of 3 arrays of 5 characters. It becomes clearer when you do it with typedefs.
typedef char T[5];
T a[3];
No pointers are involved whatsoever. If you want to access the first array of those 3 ones, you can do so:
a[0];
And it will give you back an object of type char[5]. Normally, you don't notice that because normally you index all dimensions. So the array that's returned by a[0] is subscript by the next index, for example a[0][1]. The [1] will be applied to the array that was returned by a[0], which as we have figured out earlier has type char[5].
So, is this an array of 3 pointers to 5 arrays of chars or what?
Let's create that type and see how it's different to the above. Creating it is simple, once you get the basic declarators:
Creating a pointer: *D
Creating an array: D[N]
D is just an existing another declarator. So now let's go on. First you say array of 3 pointers to 5 arrays of chars.... I think you meant array of 3 pointers to arrays of 5 chars. First, array of 5 is created like
D1[5]
Now, let's replace D1 by a pointer to declarator:
(*D2)[5]
We had to insert parentheses, because the subscript operator [N] binds better than the dereference operator *, and it would otherwise be read as *(D2[5]) which isn't what we want. Now we have pointer to array of 5.
Now let's do the array of 3. Replacing D2 by D3[3] yields this:
(*D3[3])[5]
Great, now we have got a array of 3 pointer to array of 5. Just putting the base type that that declarator appertains to yields the complete declaration:
char (*D3[3])[5];
That's of course a complete different thing :) You could use it to store pointers to your other array which was of type array of 3 arrays of 5 char. Let's store a pointer to the first sub-array of a into D3[0]. We figured out earlier that a[0] has type char[5]. We can store a pointer to that array into D3[0], because D3 is an array of pointers to char[5], what a coincidence!
D3[0] = &a[0]; // works!
I hope this little exercise has shown you some of the relations between pointers and arrays. Cheers!

I see a couple of problems with your code. First (copied from above):
int x, y;
for( x=0; x<3; x++ ){
for( x=0; x<3; x++ ){
printf( a[x][y] );
}
}
In your inner-loop, it looks like you want to use y instead of x, and you want y to go from 0..5. Currently, you are repeating the variable x. Also, you have a problem with your printf() statement. Here's some corrected code:
int x, y;
for( x=0; x<3; x++ ){
for( y=0; y<5; y++ ){
printf("%d\n", a[x][y] );
}
}
Second, when you initialize your array, your code is almost correct. Here's the corrected version:
char a[3][5] = {
{1,0,0,0,1},
{1,0,0,0,1},
{1,0,0,0,1}
};
(I removed the , after the very last "row" of data - that was a syntax error.)
The 2nd syntax you posted is incorrect (the one with no curly braces).

You've got wrong results because you're using x twice (looks like a copy/paste error). Try
int x, y;
for (x = 0; x < 3; x++) {
for (y = 0; y < 5; y++) {
printf("%c", a[x][y]); // Emil H says "%d" might be more useful
}
}
Edit: I'm not sure what's confusing about that tutorial. It's precisely equivalent to your code, except instead of printing the array, it's setting each element to (row*column) (where both row and column are one-based, hence the +1's).

The image that is in the tutorial is a great representation of the data:
alt text http://www.cplusplus.com/doc/tutorial/arrays/bidimensional_arrays3.gif
From the example, the nested for loops traverses across (left -> right) the array row by row and fills in a value for each column.

The small errors like using "%c" when you probably want "%d" and such are not what you really want to get answered I humbly think. You say you are a bit confused about arrays and also mentions that you expect to see pointers as the array-elements of the array containing arrays. You
The last comma in your definition of the array-of-arrays is NOT a syntax error. It is permitted as of C99.
What really will clear up things is to know that arrays are not pointers. It is true that an array name may be used as a constant pointer (to the first element) and that pointers can be indexed like they were arrays. This does not mean, however, that arrays and pointers are the same. They are not.
You ask about what the symbol "a" in your program actually is. It is an array of arrays. The memory layout may be visualized like a long line cut in three parts but still on a continuous line. Then cut each of these in five parts in the same manner. When addressing one element you must use two indexes; first for which five-element-array you want and then for which fifth of this element you want.
The memory layout is not like a grid of rows and columns. The memory is addressed by one scalar, so its linear. Pointer arithmetic may be the next thing you could look into, and see how an increment on a pointer works.

int x, y;
for( x=0; x<3; x++ ){
for( x=0; x<3; x++ ){
printf( a[x][y] );
}
}
You need to change the 2nd for loop to refer to 'y' instead of 'x'.
hope that helps.

You're using printf in the wrong way. Try:
printf("%d", a[x][y]);
I'm not sure whether you'll want to use %c or %d. If you want to print the number, use %d. If you want to print an actual character, use %c.

char a[3][5];
So, is this an array of 3 pointers to
5 arrays of chars or what?
Yes, that's what it is. Although you could also manipulate it as a consecutive set of 15 chars.
By convention, most people would think of it as representing a matrix with 3 rows and 5 columns (I think), but there's nothing about the data structure itself that requires that. You could just as easily use it to represent 5 rows and 3 columns. Or 3 sets that each include 5 elements but have no meaningful relationship to each other at all.
A particular library for doing matrix manipulation would have a convention for this.

Related

I'm not able to find what is causing the segmentation error in my C++ code

I have a C++ program where I have to rotate the array clockwise according to the given number of elements to be rotated (x). For example if the input array is
[1,2,3,4,5]
given that 2 elements (denoted as x) must to rotated.
The output array should be
[3,4,5,1,2]
Code:
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,x;
cin>>n>>x;
int a[n],b[x];
for(int i=0;i<n;i++){
cin>>a[i];
}
copy(a,a+x,b);
copy(b,b+x,a+n);
n=n+x;
for(int i=x;i<n;i++){
cout<<a[i]<<" ";
}
}
return 0;
}
What I'm doing here is that I copy the given number of elements to a new array. Later copy them back to the original array starting from 'n'. So my array will look like [1,2,3,4,5,1,2].
Later I'm printing out the array starting from the index 'x'. So that my array will look like [3,4,5,1,2].
I'm able to compile the program and I'm getting the output. But while submitting the code in a website called GeekforGeeks its complier is throwing out a Segmentation Fault (SIGSEGV).
This
int a[n],b[x];
is not standard c++. See here for details: Why aren't variable-length arrays part of the C++ standard? . Use std::vector for dynamic arrays.
Then here:
copy(a,a+x,b);
you use x but the size you used for a was n not x. Depending on your input this may acces the array out-of-bounds.
Next, here:
copy(b,b+x,a+n);
you try to copy to a+n but already a+n is beyond the last element of a. Arrays have fixed size, also n=n+x; wont help to change that.
To rotate elements of an array (or std::vector) you can use std::rotate.
Problem 1
The line
copy(a,a+x,b);
does not do what you want to do. It copies the first x elements of a to b, without an offset. If x is 2, that is equivalent to:
b[0] = a[0];
b[1] = b[1];
You need something that will do:
b[0+x] = a[0];
b[1+x] = a[1];
...
b[n] = a[n-x-1];
To achieve that, you need to use:
std::copy(a, a+(n-x), b+x);
Problem 2
The line
copy(b,b+x,a+n);
is notright.
You want to copy from a to b, not from b to a.
Using a+n immediately results in accessing the array using out-of-bounds indices, which causes undefined behavior.
The offsets used in that call don't make sense at all.
After the first line of std::copy is executed, you need something what will do the following:
b[0] = a[n-x];
b[1] = a[n-x+1];
...
b[x-1] = a[n-1];
To achieve that, you need to use:
std::copy(a+(n-x), a+n, b);
Arrays must have determined size
some compilers accept your code but other don't
so try to use pointers instead

Last element of a struct array - C

I'm a bit confused about a thing :
If I have an array of structs: table whith a length of X and I want to access the last element of it: table[X] or table[X-1]. If it's table[X-1], what table[X] contains ?
The indexing of array in C starts with zero, i.e. the first element will be in table[0], the second in table[1], the third in table[2] ... and the last on in table[X-1].
table[X] is outside of the arrays bounds. C does not have bounds checking, so compiler allows accessing it, but this is an undefined behaviour, i.e. you will never know what happens. Reading it can give back memory garbage or can lead to an OS exception like segmentation fault.
The answer is the same for any kind of array. If you have one with the size
X :
int a[5];
struct my_struct ms[10];
...
you specify the amount of elements in that array. Because the 1st element is element 0, the last element is always X - 1.
If you try to access the element a[X] you will get undefined behavior.
Structs work in memory the same way that an integer or some other basic data type would in this instances. Your array would just be separated by sizeof(struct) instead of sizeof(the basic data type).
It'd still start at 0, and end at X - 1. The type of arrays usually just really defined 2 things:
The amount of bytes per index, and how to treat the data.
Picture an array of size 3 with structs that contain 5 bytes of data. Your array would just be set as follows:
-----|-----|-----|????|
s1 |s2 |s3 |????|
Just because it exists, doesn't mean our program knows what it is. the 4th [3] index (????) would be an index out of bounds of our array. It is possible however you could get some meaningful value here, but very unlikely. Most of the time it will either be garbage, or cause an error.
Arrays in C use zero indexing, meaning they start with 0 and end with n-1. Not to be confused with array declarations, where you write the size expressed in number of items. The syntax for accessing an array and declaring one looks similar, which is why this can be confusing for beginners.
Example:
int main (void)
{
int array[5]; // allocate an array with 5 elements
array[0] = 0; // access first element
array[4] = 0; // access last element (index 4)
array[5] = 0; // BAD, accessing the array out of bounds: index 5 gives item number 6
}
And this is why the canonical way to write for loops in C is this:
for(int i=0; i<n; i++)
where n is the size of the array, and the iterator i will have the values from 0 to n-1.

3rd Array element does not print out when using a pointer variable to assign array element values

SO I was reading a book on C and came across a piece of code which I couldn't fully understand, so I decided to run it out and see the result for myself. Basically, I understand that an array variable acts like a pointer, in the sense, that it points to the first element of the array, for instance.
char quote[]="This is a nice cookie!"
Here quote which is an array variable, is basically a pointer to the first element of the array i.e. the letter T(Hope I am correct so far).
Building on this, when I write the below piece of code, I understand the following points.
At the declaration time, contestants is an array with 3 members in it - 1, 2 and 3
Then I use *choice as an array variable which in other words is a pointer to the first element of array contestants- which is now (1).
Now I begin dynamically assigning values to the members of the contestants array.
contestansts[2]=*choice
puts the value 0 in the 3rd member of the array i.e.: contestants[2].
So far, so good.
Now, the next for loop was not there in the book. I included it in the code myself, to see what are the elements of the array. When I run the code, as an output I get-
I will pick contestant number 2
The members of the array contestants are:
Member 0 has the value 2
Member 1 has the value 3
My question is- I do not understand how the member 1 has the value 3. According to the code, shouldn't members 1 and 2 both have the same value(2).
Any help would be highly appreciated.
I am using Sublime Text and the Mac terminal to run this(if needed).
#include<stdio.h>
int main()
{
int contenstants[]={1,2,3};
int *choice=contenstants;
contenstants[0]= 2;
contenstants[1]=contenstants[2];
contenstants[2]=*choice;
printf("\n I will pick contestant number %i\n", contenstants[2] );
//Print array members
printf(" The members of the array Contenstants are:\n");
for(int i=0;i<contenstants[2];i++)
{
printf(" Member %i\t has the value %i\t", i, contenstants[i] );
printf("\n");
}
return 0;
}
int contenstants[]={1,2,3};
int *choice=contenstants; // choice -> {1,2,3}
contenstants[0]= 2; // choice -> {2,2,3}
contenstants[1]=contenstants[2]; // choice -> {2,3,3}
contenstants[2]=*choice; // choice -> {2,3,2}
The output you get is totally logical!
In the first step you assign the value 2 to contenstants[0], which is also *choice.
The reason why you are only getting two numbers on the output is, that you loop for(int i=0;i<contenstants[2];i++), which is equivalent to for(int i=0;i<2;i++), which loops over element number 0 and element number 1.
It is 3 because you are doing
contenstants[1]=contenstants[2];
and then contenstants[1] is not modified later so it has value 3;
To answer your question in comment:
Condition in your for loop is not correct
--------------v not correct
for(int i=0;i<contenstants[2];i++)
You want
for(int i=0;i<3;i++)
Although using hardcoded 3 is also not a good idea. But it goes with your other code.

C Storing Matrix in Array of Chars and Printing

Hey all I am trying to store a matrix in an array of chars and then print it out.
My code that I have written:
#include<stdio.h>
#include<stdlib.h>
int main() {
int i;
int j;
int row=0;
int col=0;
int temp=0;
char c;
int array[3][2] = {{}};
while((c=getchar()) !=EOF && c!=10){
if((c==getchar()) == '\n'){
array[col++][row];
break;
}
array[col][row++]=c;
}
for(i=0; i<=2; i++){
for(j=0; j<=3; j++){
printf("%c ", array[i][j]);
}
printf("\n");
}
}
Using a text file such as:
1 2 3 4
5 6 7 8
9 1 2 3
I would like to be able to print that back out to the user, however what my code outputs is:
1 2 3 4
3 4 5 6
5 6 7 8
I cannot figure out what is wrong with my code, some how I am off an iteration in one of my loops, or it has something to do with not handling new lines properly. Thanks!
A few problems that I can see are:
As user3386109 mentioned in the comments, your array should be array[3][4] to match the input file.
The line array[col++][row]; does nothing but increment col, and then uselessly indexes the array and throws away the value. You can do the same thing with just col++;. However, you're not even using col at any later point in the code, so really you don't even need that. The break; all by itself does what you need. Which leads me to...
You're not populating the array like you think you are. You're incrementing col and then immediately breaking out of the loop. So how does the entire array ever get populated? Just by pure luck. As it turns out with your array declared as array[3][4], the array access array[0][4] (which isn't even technically supposed to exist) is equivalent to array[1][0]. This is because all multidimensional arrays (in C and just about any other language) are laid out in memory as flat arrays, because memory itself uses linear addressing. In C, this flattening of multidimensional arrays is done in so-called Row-major order, meaning that as you traverse the raw memory from first address to last, the corresponding multidimensional indices (i,j,k,...z, or in your case just i,j) increment in such a way that the last index will change the fastest. So, not only does col never get incremented except for right before you break out of the loop, but row never gets reset to 0, which means you're storing values in array[0][0], array[0][1], ... array[0][11], not array[0][0] .. array[0][3], array[1][0] .. array[1][3], array[2][0] .. array[2][3] as you were expecting. It was just luck that, thanks to row-major ordering, these two sets of indices were actually equivalent (and C doesn't do array bounds checking for you because it assumes you're doing it yourself).
This is just personal preference, but you will usually see arrays referenced as array[row][col], not array[col][row]. But like I said, that's just preference. If it's easier for you to visualize it as [col][row], then by all means do it that way. Just make sure you do it consistently and don't accidentally switch gears midway through your code to doing [row][col].
Your code will break and only print out part of the matrix if you accidentally put a trailing space at the end of one of your rows of numbers, because of the weird way you're checking for the end of input (doing a second getchar after each initial getchar and checking to see if the second character is \n). This method isn't wrong per se, in the sense that it will work, but it's not very robust and relies on your input data being precisely formatted and containing no trailing spaces. Anyone who has ever spent hours trying to figure out why their Makefile didn't work, only to find out that it was because they had leading spaces instead of tabs can attest to the fact that those kinds of errors can be extremely time-consuming and frustrating to track down. Precisely formatted input data is always a good thing, but your code shouldn't break in unexpected an non-obvious ways (such as only printing out half of a matrix) when it doesn't get perfect input. Edit: It only occurred to me later on that you were actually intending to do two mutually exclusive things here: increment col for the next line of input, and break out of the loop after having (presumably) detected the end of input. You need to figure out which thing you're doing here, although thanks to item #3, your code actually (and oddly) works just by taking user3386109's advice and changing array[3][2] to array[3][4].
I can only assume you used <= 2 and <= 3 in your for loops instead of < 3 and < 4, respectively, because you prefer doing it that way. That's fine, but it generally makes for easier-to-read code if your for loop conditions match up with your array dimensions. Just speculating here, but perhaps that's why you had array[3][2] when you really meant array[3][4].

Array size less than the no. of elements stored in it

Is it possible to declare an array of size 1 and be able to store 5 elements in it and then retrieve them?
I try one such code where I declared an array arr[1] and then stored 5 elements into it. It was actually possible to store 5 elements! How was it?
If this is C (or C++), you can quite easily store more elements than the array is sized for:
#include <stdio.h>
int main (void) {
int x = 0;
int a[1]; // so that a[0] is the only valid element
a[1] = 7; // write beyond end of array
printf ("x=%d, &a[0]=%p, &a[1]=%p, &x=%p\n", x, &(a[0]), &(a[1]), &x);
return 1;
}
Doing so, however, leads to undefined behaviour, probably overwriting some other piece of information, and is not really a good idea.
On my system, that code above prints:
x=7, &a[0]=0xbf9bb638, &a[1]=0xbf9bb63c, &x=0xbf9bb63c
despite the fact I set x to zero and never explicitly changed it. That's because writing beyond the end of the array has affected it (as you can see from the two identical addresses for a[1] and x).

Resources