three dimensional character array in C - c

I want to declare a three dimensional array of strings
where each row has two strings.
Here I am able to declare it:
char *szArray[][2] = {
{"string1", "string2"},
{"string3", "string4"},
{"string5", "string6"},
{0, 0}
};
I want to do the same thing but number of rows are dynamically allocated.
Here you can assume 1st dimension is dynamically decided.
2nd dimension is 2,
3rd dimension is 25.
Tried in many ways no luck :(.
Thanks in advance !

First what you have in your question is not a 3-dimensional array of char but a 2-dimensional array of pointers to char. In C, pointers and arrays are not the same thing.
To answer your question, the simplest way in modern C, C99, is to use variable length arrays, VLA, for your purpose. For a 3-dimensional array you'd do
char szData[x][y][z];
where x, y and z are variables or expressions that are only determined at run time when you hit that declaration.
The inconvenience of VLA are that you have to be careful that they don't become too large for your stack, and that you have to initialize them by assignment to the individual entries (here by a nested for-loop).
To stay with your example of 2-d array of strings
char* szData[x][y];
and then you'd have to assign either individual strings to each of the pointers or to set them to 0.
for (size_t i = 0; i < x; ++i)
for (size_t j = 0; j < y; ++j)
szData[i][j] = 0;

int n = 0 ;
printf("Enter the number of rows\n");
scanf("%d",&n);
char *** szData = (char *** )malloc(n * sizeof(char ** )) ;
//Allocate memroy for each row
for(int i = 0 ; i < n ; i++ )
{
szData[i] = (char ** ) malloc(2 * sizeof(char * )) ;
for ( int j = 0 ; j < 2 ; j++ )
{
szData[i][j] = (char *) malloc (25 * sizeof(char));
}
}
//Assign some data
for( int i = 0 ; i < n ; i++ )
{
sprintf(szData[i][0],"string%d", i);
sprintf(szData[i][1],"string1%d", i);
}
//print all the elements
for( int i = 0 ; i < n ; i++ )
{
printf("%s\n",szData[i][0]);
printf("%s\n",szData[i][1]);
}
//free memory here
for(int i = 0 ; i < n ; i++ )
{
for ( int j = 0 ; j < 2 ; j++ )
{
delete szData[i][j];
}
}
for(int i = 0 ; i < n ; i++ )
{
delete szData[i];
}
delete szData;

I didnt get any error:
#include <stdio.h>
int main(){
char *szArray[][2] = { {"string1", "string2"}, {"string3", "string4"}, {"string5", "string6"}, {0, 0} };
printf("%s\n", szArray[0][0]);
printf("%s\n", szArray[2][0]);
}
Here is the output:
$ gcc test.c
$ ./a.exe
string1
string5
But you cannot print szArray[3][0][0] because it is 0, if you want to initialize the value to whatever, you can set to "\0" instead of just 0

Ok, no compiler here to double check, but you can do this a number of ways. The most straight forward would be to declare a Vector of char[25][3] and let c++ do it for you. Something like Vector foo and then just push_back your dynamic elements. Without a compiler though, I'm not 100% certain that this would work as there are funky rules when it comes to multi-dimensional arrays. You can always undimensionalize your array as a first pass just to get it working as well - something like a Vector and start adding how ever you want. You can also do the vector of vector of char approach and have jagged arrays of chars where and of the 3 dimensions can be dynamic, and this would probably even be more memory efficent. Lots of choices here.

Related

Variable sized array in C

For some reason, the first output my program is giving, is garbage value, while the second output is correct.
This is a problem from HackerRank.
I know this question has already been asked by someone else. I just want to know what the problem is in my code.
#include <stdio.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
int A[index][b];
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
return 0;
}
If the input is:
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
Then the output should be:
5
9
But instead, my output is:
garbage
9
Disclaimer
I didn't even click the link, so I do not know if the solution is correct, but assuming that you got the logic right..
The problem
is that you populate in stages a local to the body of the for loop 2D array, which at the end of your processing, you expect to have it accessible (I mean the complete matrix, populated from every single iteration of the for loop).
Instead, you get only the last's iteration declared array, that's why you get only the A[1][3] element right, and not the A[0][1], since the 2nd row is populated in the last (2nd iteration), while the 1st row is populated in the first iteration (of the firstly declared A), which goes out of scope as soon as the first iteration terminates.
The fix
So, what you need to fix this is to dynamically allocate memory for your matrix, and every time a new dimension for the columns is inputed, resize it with realloc().
I believe that the explanation I have in 2D dynamic array (C) will help you, since what you want is the number of rows fixed, and the number of columns adjustable on every iteration.
Below is an illustration based on the link I shared above, which visualizes what exactly is your matrix (a 1D array of pointers), and shows how the code below manipulates it:
Full code example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index,query;
int count1 = 0;
scanf("%d%d",&index,&query);
// An array of `index` (e.g. 2) pointers to integers
int *A[index];
// Initialize all the pointers to NULL
for(int k = 0; k < index; ++k)
A[k] = NULL;
for(int i=0;i<index;i++)
{
int b;
scanf("%d",&b);
// Replaced your 'int A[index][b];' with the following:
// Every time a new number of columns (that's 'b') is read,
// we need to adjust the numbers of columns our matrix ('A') has.
// That means, that for every pointer (row), we need to re-allocate
// the number of columns it points to, which is basically a 1D array, of dimension 'b'
for(int k = 0; k < index; ++k)
A[k] = realloc(A[k], b * sizeof(int) );
for(int j=0;j<b;j++)
{
scanf("%d",&A[i][j]);
}
count1 ++;
if(count1<index)
{
continue;
}
int count2=0;
while(count2<query)
{
int d,e;
scanf("%d%d",&d,&e);
printf("%d\n",A[d][e]);
count2++;
}
}
// Free the dynamically allocated memory
for(int k = 0; k < index; ++k)
free(A[k]);
return 0;
}
Output (for the input provided):
5
9
Pro-tip: The typical methodology of calling realloc() is to use a specific pointer for the reallocation, test that pointer and, if everything worked out ok, change the old pointer, as explained in Does realloc overwrite old contents?, which I didn't do in that post for the sake of being "laconic".
The C VLA is not suitable here. It seems you need to allocate memory dynamically. The only VLA that can be used is an array of pointers to other arrays. All other arrays should be allocated dynamically.
Something like the following.
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
size_t number_of_arrays;
size_t number_of_queries;
scanf( "%zu%zu", &number_of_arrays, &number_of_queries );
int **a = malloc( number_of_arrays * sizeof( int * ) );
for ( size_t i = 0; i < number_of_arrays; i++ )
{
size_t size;
scanf( "%zu", &size );
a[i] = malloc( size * sizeof( int ) );
for ( size_t j = 0; j < size; j++ ) scanf( "%d", &a[i][j] );
}
for ( size_t i = 0; i < number_of_queries; i++ )
{
size_t array_index;
size_t element_index;
scanf( "%zu%zu", &array_index, &element_index );
printf( "%d\n", a[array_index][element_index] );
}
for ( size_t i = 0; i < number_of_arrays; i++ ) free( a[i] );
free( a );
}
If to input
2 2
3 1 5 4
5 1 2 8 9 3
0 1
1 3
then the program output will be
5
9
As for your code then it is invalid. For example the variable b is not initialized so the declaration of the array has undefined behavior.
int b;
scanf("%d",&b);
int A[index][b];
^^^
Hint : Variable sized arrays need to be dynamically allocated, here's how to it in C
int rows;
scanf("%d",&rows);
//2D array
int**A = malloc(sizeof(int*)*rows); //allocate number of rows
//for each row allocate number of colums
for(int i = 0; i < rows; i++)
{
int cols;
scanf("%d",&cols);
A[i] = malloc(sizeof(int)*cols);
}

Accessing specific elements in a multi-dimensional array of pointers in C

How do I access elements 0-K in a 2D array of pointers with i rows and j columns?
I was unable to see how using nested for loops to index out the desired element would work, because it is unknown if K is smaller or larger than either i or j.
So, I was thinking that it was necessary to provide for different conditions:
if (K < j) {
//index through the first row
}
while (K > j) {
//do some manipulations to determine how many rows to index through
}
But this just seems unnecessarily complex. Is there a way with using pointers and derefencers to get the value of element K out of a 2D array of pointers?
Say, for example, I want to get the value 7 out of this array:
(Note: This image does not accurately reflect how a 2D array of pointers looks...I know that is, in essence, an array of 1D arrays.)
If I have understood you correctly then you need the following.
First of all you can reinterpret a two-dimensional array as a one-dimensional array. And you can split sequential indexes into rows and columns.
In the demonstrative program below there are shown the both approaches.
#include <stdio.h>
#define M 3
#define N 4
int main(void)
{
int a[M][N];
int *p = ( int * )a;
for ( size_t i = 0; i < M * N; i++ )
{
p[i] = i;
}
for ( size_t i = 0; i < M * N; i++ )
{
printf( "%2d ", a[ i / N ][ i % N ] );
if ( ( i + 1 ) % N == 0 ) putchar( '\n' );
}
return 0;
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11

How to store the sum of two integers into a long variable in C?

I created a matrix of ints for example have {1 , 2 , 3 , 4 , 5}
and then I'm trying to store the sum of the matrix into a long variable:
#include<stdio.h>
#define m 5
int main (){
int i;
int matrix[m];
long matrix_sum;
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
for(i = 0; i < m ; i++) //adding ints to long
matrix_sum += matrix[i];
printf("%lo \n",matrix_sum);
return 0;
}
when I run this code I have "17" on output instead of "15" !!
Think about what happens on the first iteration of this loop:
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
Notice that you'll be reading from index -1 of this array (oops!) This leads to undefined behavior, which means that in principle anything can happen. Your program could get garbage data, get the wrong answer, or even outright crash!
It's up to you to decide how to avoid this case. Consider changing the loop indices so that you start at a higher index.
Also, look at the remaining variables in main. Are they initialized? If not, adding values to them will again result in undefined behavior and pretty much anything can happen to them.
Finally, look at how you're printfing things:
printf("%lo \n",matrix_sum);
The %lo specifier means "the argument is a long, and it should be printed in octal (base-8)." This means that you're not printing the value in decimal, so even if you'd expect to get the value 15dec, you'd instead see 17, the octal representation of the number.
I have not seen a matrix. It seems you mean an array or a vector.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
The variable matrix_sum was not initialized.
In this loop
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
^^^^
there is an attempt to access memory beyond the array when the variable i is equal to 0.
And it looks like you wanted to use the conversion specifier %ld in this statement
printf("%lo \n",matrix_sum);
^^^
Otherwise the output will be as an octal number.
I think you mean the following. At least the program output is exactly equal to 15.:)
#include <stdio.h>
#define N 5
int main(void)
{
int a[N];
int i;
long sum;
for ( i = 0; i < N ; i++ ) a[i] = i + 1;
sum = 0;
for ( i = 0; i < N ; i++ ) sum += a[i];
printf( "%ld\n", sum );
return 0;
}

Declaration for a two dimensional array and finding sizeof: C programming

Write a declaration for a two dimensional array A that has 5 rows and 10 columns and in which each element is a character string of length 20. What is the sizeof A?
Part II: Write statements to set each element in the array to a string of blanks.
This is first year programming so everything is very basic. This is in C.
Thanks for any help.
Here's my attempt for part I
char c[5][10][20];
Here's my attempt for part II
int x,y;
for (x=0;x<5;x++) {
for (y=0;y<10;y++) {
c[x][y]=" "; }}
I don't know if I'm misreading your question or whether it really is as straight forward as finding the size of your 5 * 10 * 20 character array? The sizeof type char is 1-byte per-char. Thus 5 * 10 * 20 = 1000 (as compared to say a type int which would normally be 4-bytes per-int).
To determine the size within the scope where the array is statically declared you can use the sizeof operator, for example:
#include <stdio.h>
int main (void) {
char c[5][10][20];
printf ("\n sizeof c : %lu\n\n", sizeof c);
return 0;
}
Use/Output
$ ./bin/sizeof_3d
sizeof c : 1000
To set each element in the array to ' ' (space), you have a couple of options (1) a loop over each element in the array; or (2) using memset. To use a loop:
size_t i, j, k;
...
for (i = 0; i < 5; i++)
for (j = 0; j < 10; j++)
for (k = 0; k < 20; k++)
c[i][j][k] = ' ';
If you need a literal string of blanks you will need to add a nul-terminating character as the final character in each string. When using the loop above, that can be accomplished by replacing c[i][j][k] = ' '; with the following that uses a ternary operator to write a nul-character (zero) as the final character in each string:
c[i][j][k] = k + 1 == 20 ? 0 : ' ';
To use memset (don't forget to #include <string.h>):
memset (c, ' ', sizeof c);
To null terminate following the use of memset, an abbreviated loop can be used:
size_t i, j, k;
...
memset (c, ' ', sizeof c);
for (i = 0; i < 5; i++)
for (j = 0; j < 10; j++)
c[i][j][19] = 0;
Let me know if you have further questions.
First declare a type for your 20 character strings.
typedef struct mystring {
char str[20];
} mystring;
Then you can declare your variable A LIKE THIS:
mystring A[5][10];
So, A is a variable of type 5 string which has 5 rows and 10 columns. Each element in the array is of type mystring which as a string that can hold 20 characters. The maximum length of a string that a mystring can hold is of course 19 characters since you need to reserve one character for the null terminator.
An array A that has 5 rows and 10 columns and in which each element is a character string of length 20.
What is the sizeof A?
The size of array A we get by multiplying its columns by its rows and the result of it multiplying by the size of the elements of the array. In this case they are strings of 20 characters length. Assuming your machine's char implementation is 1 byte, then array A occupies total size of:
5 x 10 x 20 = 1000 bytes or 1MB.
To define such an array in C++, you write within your main, avoiding magic numbers:
size_t rows_number = 5;
size_t columns_number = 10;
size_t element_size = 20;
char c[rows_number][columns_number][element_size];
To initialize its elements to particular value, you could use for loops for each index of the array:
char initial_value = ' ';
for (i = 0; i < row_number; i++) {
for (j = 0; j < column_number; j++) {
for (k = 0; k < element_size; k++) {
c[i][j][k] = initial_value;
}
}
}

how do you swap two rows in a matrix (in C)?

for example, given a matrix:
1 2 3
4 5 6
7 8 9
if you are goint to swap row[0] and row[1], resulting matrix would be:
4 5 6
1 2 3
7 8 9
can you guys help me get a code in C for this?
The answer depends entirely on how your "matrix" is implemented, because the c language has no notion of such a thing.
Are you using two dimensional arrays?
double m[3][3];
Or something else?
Two dimensional arrays
You will have to move individual elements by hand.
for (i=0; i<ROWLENGTH; ++i){
double temp;
temp = m[r2][i];
m[r2][i] = m[r1][i];
m[r1][i] = temp;
}
(here r1 and r2 are ints that have been set to the two row you want to swap) or see James' memcpy implementation which may well be faster but requires a whole rows worth of temporary memeory.
Ragged Arrays
If this operation is very common and profiling reveals that it is consuming a lot of time, you might consider using a ragged array implementation of the matrix. Something like this:
double **m;
m = malloc(sizeof(double*)*NUMROWS);
/* put error checking here */
for (i=0; i<NUMROWS; ++i){
m[i] = malloc(sizeof(double)*ROWLENGTH);
/* error checking again */
}
The fun part about this structure is that you can still access it with the [][] notation, but the row swap operation becomes
double *temp;
temp = m[r2];
m[r2] = m[r1];
m[r1] = temp;
Ragged arrays have two disadvantages from your point of view (well, three 'cause of the memory management hassle): they require extra storage for the row pointers, and you can't use inline initialization.
Row-as-astructure
C does not support array assignments of the form;
double r[3], q[3] = { 1, 2, 3 };
r = q; /* ERROR */
but it does support by-value assignment semantics for structures. Which gives you the implementation that several people have suggested without explaining:
typedef struct { double r[ROWLENGTH] } row;
row m[NUMROWS] = { {1, 2, 3}, {4, 5, 6}, {7, 8 9}};
row temp = m[2];
m[2] = m[1];
m[1] = temp;
which is slick. It requires a whole row of memory, but if the compiler is any good is probably fast. The big disadvantage is that you can not address individual matrix elements with the [][] syntax anymore. Rather you write m[i].r[j];
Others
There are many, many other ways to implement a "matrix" in c, but they are mostly much more complicated and useful only in specialized situations. By the time you need them you'll be able to answer this questions for yourself in the context of each one.
typedef int Row[3];
Row Matrix[3];
Row Temp;
memcpy(Temp, Matrix[0], sizeof(Row));
memcpy(Matrix[0], Matrix[1], sizeof(Row));
memcpy(Matrix[1], Temp, sizeof(Row));
I'd probably swap one element at a time to avoid using a lot of extra storage. If you're working primarily with things like graphics transforms where the matrices are typically 3x3 or 4x4, James Curran's approach is probably a bit better. If you are (or might be) working with really large matrices, this will save memory, and quite possibly run faster:
int x[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
for (int i=0; i<3; i++) {
int temp = x[0][i];
x[0][i] = x[1][i];
x[1][i] = temp;
}
solve this your homework?
typedef struct {int m[3];} Row;
typedef int RowAccess[3];
main()
{
Row tmp,row[]={{1,2,3},{4,5,6},{7,8,9}};
RowAccess *rowa=row;
tmp=row[0];
row[0]=row[1];
row[1]=tmp;
/* easy access to matrix here: (is this what you want?) */
rowa[0][0]=0;
rowa[0][1]=1;
...
return 0;
}
Hy! this is my first post on stack overflow, I know it's pretty long, hope I won't get banned!
Probably one of the most elegant approaches would be using a function that swaps the two received arguments - using it to swap matrix components. Let's say somethig like swap(a,b).
As many have already said, we should consider using a auxiliary variable
auxiliary = a ;
a = b ;
b = auxiliary ;
Recently, I picked up a new method, which I found impressing, using bitwise XOR operation (http://en.wikipedia.org/wiki/Xor) thus a auxiliary is not needed
a ^= b ;
b ^= a ;
a ^= b ;
You can easily use this operation to swap two elements ( a and b ) - I belive this is off topic, but I insisted on this idea because I found it pretty interesting.
Finally, answering your question, you could use let's say
int swap (int *a , int *b){
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
return 0;
}
while having a matrix declared as
#define ROW_COUNT 5
#define COLUMN_COUNT 5
....
int a[ROW_COUNT][COLUMN_COUNT];
You can use your the XOR way the swap the rows, firstly identifyng the elements needed to be swapped ( according to row index, as you already said )
printf("\nSwap Row: "); scanf("%d", &swp1) ; // first row index
printf("With Row: "); scanf("%d", &swp2); // second row index
for (j = 0 ; j < COLUMN_COUNT ; j++){
swap( &a[swp1][j] , &a[swp2][j] );
}
I hope this will be usefull in your further practice.
Also try this example, I'm sure you'll understand the whole idea much better afterwards (don't forget matrix index starts at 0 !)
#include "stdio.h"
#include "conio.h"
#define ROW_COUNT 5
#define COLUMN_COUNT 5
int swap (int *a , int *b){
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
return 0;
}
int main(){
int i, j ;
int swp1, swp2 ;
int a[ROW_COUNT][COLUMN_COUNT];
// Create ( ROW_COUNT X COLUMN_COUNT ) random matrix
for (i = 0 ; i < ROW_COUNT ; i++ )
for (j = 0 ; j < COLUMN_COUNT ; j++ ) a[i][j] = rand();
// Display matrix before row swap
for (i = 0 ; i < ROW_COUNT ; i++ ){
for (j = 0 ; j < COLUMN_COUNT ; j++ ) printf("%d\t",a[i][j]);
printf("\n");
}
// Elements to be swapped
printf("\nSwap Row: "); scanf("%d", &swp1) ; // first row index
printf("With Row: "); scanf("%d", &swp2); // second row index
// Swapping right here
for (j = 0 ; j < COLUMN_COUNT ; j++){
swap( &a[swp1][j] , &a[swp2][j] );
}
// Display once again
printf("\n");
for (i = 0 ; i < ROW_COUNT ; i++ ){
for (j = 0 ; j < COLUMN_COUNT ; j++ ) printf("%d\t",a[i][j]);
printf("\n");
}
getch();
return 0;
}
temprow = row[1];
row[1] = row[0];
row[0] = temprow;
There is a function called swap:
#include <algorithm>
int A[][] = {{1,2,3},{4,5,6},{7,8,9}};
swap(A[0],A[2]); //swaps first and last row

Resources