Array size redefinition - c

So basically according to definition of array we cannot change array size. But if I am adding element to a same array by shifting other elements to the right of array, so the array size is going to increase.
How this is possible?
#include<stdio.h>
int main() {
int n, j, k, item;
printf("Enter size of array:\n");
scanf("%d", &n);
printf("Enter element to insert and position of element:\n");
scanf("%d,%d", &item, &k);
int a[n];
for (j = 0; j < n; j++) {
printf("Enter a[%d] element:\n", j);
scanf("%d", &a[j]);
}
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j];
j = j - 1;
}
a[k - 1] = item;
for (j = 0; j <= n; j++) {
printf("%d\n", a[j]);
}
}

Shifting the contents of the array to the right will not resize the array. If the array was not already large enough to hold the result of the shift, then you have overrun the array object, and have induced undefined behavior.
There is no way to dynamically increase the size of a variable with static or auto duration (e.g., global or local variables), and this includes arrays. If your compiler supports variable length arrays (VLAs), changing the value of the expression controlling the dimension of the array does not affect the array's size.
int main (void) {
int n = 3;
int v[n];
printf("%zu\n", sizeof(v));
++n;
printf("%zu\n", sizeof(v));
}
The program above will print the same value twice.

I am not entirely sure what you're asking, but for any readers interested in knowing how to dynamically change the size of an array in C: if an array is declared in stack memory, its size cannot change. However, a block of memory intended to be used as an array is declared on the heap (i.e. with malloc or calloc), can be reallocated with a different size if necessary:
int *data = malloc(10 * sizeof(int)), *data2 = NULL;
int i;
if(data == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
data[i] = i;
}
data2 = realloc(data, 11 * sizeof(int));
if(data2 == NULL)
{
free(data);
perror("realloc");
exit(EXIT_FAILURE);
}
else
{
data = data2;
}
data[10] = 10;
for (i = 0; i < 11; i++)
printf("%d ", data[i]);
free(data);
data = NULL;
Shifting elements in an array down one element will not change its size.

If you declare an array as
T a[N]; // assume N is a constant expression
then a can only ever hold N elements of type T - no more, no less. You cannot add extra elements to the array, nor can you remove elements from the array.
However...
C does not force any bounds checking on array subscripting, so it's possible that you can read or write past the end of the array such as
a[N + 2] = x;
The behavior on doing so is undefined - your program may work as expected, or it may crash immediately, or you may corrupt other objects in the program. The runtime environment will (most likely) not throw an IndexOutOfBounds-type exception.
There is a thing called a variable-length array that was added in C99, where the array size is not a constant expression:
size_t size = some_value();
T a[size];
Variable length arrays are only variable length in the sense that their size isn't determined until runtime - however, once defined, their size is fixed throughout their lifetime, and like regular arrays, they cannot grow as new items are added.
If you dynamically allocate a chunk of memory using
T *a = malloc( sizeof *a * some_size );
then you can grow or shrink that chunk of memory using realloc:
T *tmp = realloc( a, sizeof *a * (some_size * 2) );
if ( tmp )
{
a = tmp;
some_size *= 2;
}

.... array we cannot change .. But if I (do something special) ... the array size is going to increase.
How this is possible?
Undefined behavior
Arrays cannot change size once defined.
Code attempts to assign a[j + 1] with j = n-1 and that is a[n]. This is outside array a[] and so undefined behavior. Rest of code is irrelevant for at that point anything is possible, code crash, error report, even apparent successful array expansion, etc.
int a[n];
...
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j]; // To attempt access to `a[n]` is UB

Related

What should I do with unhandled exception

I tried a lot of things to do but it still show me the same, that there is unhandled exception: access violation writing location in VS. But it doesn't happen when i sorting 1d array. What can I try next?
int main(void) {
static int a[3][4]{}, ab[3][4]{};
int i, j, k, N, M;
int* a1=nullptr;
printf("Matrica mora da ima velicinu 3 sa 4\n");
printf("Enter the order \n\n\t");
scanf_s("%d%d",&N ,&M);
for (i = 0;i < M;++i)
{
for (j = 0;j < N;++j)
{
scanf_s(" %d", &a[i][j]);
ab[i][j] = a[i][j];
}
printf("\n");
}
for (i = 0;i < M;++i) {
for (j = 0;j < N;++j) {
printf(" %d", a[i][j]);
}
printf("\n ");
}
//classic sorting
for (i=0; i < M; ++i)
{
for (j = 0;j < N;++j)
{
for (k = j + 1;j < N;++k)
if (a[i][j] > a[i][k])
{
*a1 = a[i][j]; // there is exception thrown
a[i][j] = a[i][k];
a[i][k] = *a1;
}
}
}
First off, there is a problem with static allocation of arrays, but there is no sanitization of N and M after the user inputs them. That means that you allocate only a matrix of 3x4, but the user can input and write to a matrix of any dimensions (e.g. 10x10), which could lead to access violation.
I'd recommend either having sanitation of the input values, e.g.
// It's always better to have limits as constant.
const int MAX_N = 3;
const int MAX_M = 4;
static int a[MAX_N][MAX_M];
...
scanf_s("%d%d",&N ,&M);
// Check if the dimensions can be fitted into the statically allocated array.
if(N > MAX_N || N <= 0 || M > MAX_M || M < 0)
{
// indicate invalid dimensions, either by returning from main with -1
// or calling exit(-1), or throwing an exception.
return -1;
}
In case the input didn't exceed 3x4, another thing that could be problematic - i goes from 0 to M, not N (what I would expect), which could also be problematic. The way matrix addressing works in C/Cpp is that the matrix is linearized into an array, and accessing it with a[i][j] leads to accessing the array with a[i*MAX_J + j]. In your case, the array has 12 elements (3x4), and MAX_J=4, so accessing it with a reverse set of indexes a[4][3] will access a[4*4+3]=a[19], which will access memory from outside of the array.
On the access violation writing problem, a1 isn't allocated, so when you try do execute *a1= ... you are writing to nullptr, which is a protected address, hence the access violation when writing. The way to solve this is either to:
have a1 be a int variable (not a pointer)
first allocate memory for a1 by executing a1 = malloc(sizeof(int)); and then freeing it after use with free(a1) (but since it's only a single element, I'd recommend converting a1 to int instead)
assign the address of the matrix element like a1=&a[i][j], but that would not be valid logically in your case (after that, you write into the location the pointer is pointing to, so the original value will be lost).
The reason why it's not happening for the 1d array is probably because of the inverted dimensions - the matrix would probably be 1x4, but you will be accessing it as 4x1, and you are sorting all the values with j index from 0 to 1, and since there is only one value you would not enter the k loop.

How do I fill an array with natural numbers in c?

This is my code:
int i=1 , j=1 ,k=0, n=1;
printf("\nPut in number n which is the upper limit: ");
scanf("%d", &n);
bool *eratos = malloc(sizeof(n));
for (int m = 1; m<=n; m++) {
printf("%d,", m);
eratos[m] = m;
printf("%d,", eratos[m]);
}
For some reason it does not fill up the eratos[m] array with numbers from 1 to 50 but only withs ones.
This is my output:
1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,1,11,1,12,1,13,1,14,1,15,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,1,28,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,45,1,46,1,47,1,48,1,49,1,50,1
The first line of printf() is to check whether its counting up correctly, which it does obviously. But the array gets only filled up with ones and not with [1,2,3…50].
First of all, a bool cannot hold anything apart from a 0 and 1. To have values other than that, use int type.
That said, the next problem is in the memory allocation, you need to allocate appropriate amount of memory, i.e., the amount (value) held by n, not equal to the size of the variable n itself.
int *eratos = malloc(n * sizeof(*eratos));
Finally, you need to correct your for loop to avoid off by one error, like
for (int m = 0; m < n; m++) { // C arrays use 0-based-indexing
printf("%d,", m+1); // still counts from 1, for sake of printing
Another issue apart from the issue pointed out by SouravGosh is you have taken the bool array.
bool *eratos = malloc(sizeof(n));
eratos[m] = m;
Any non zero value is true in case of bool.
And anther issue is that array indexes start at 0, not at 1. Do:
for (int m = 0; m < n; m++)
For starters this memory allocation
bool *eratos = malloc(sizeof(n));
does not make a sense. The expression sizeof( n ) is equal to the expression sizeof( int ) and does not depend on the value stored in the variable n.
You declared an array with the element type bool that is an alias for the type _Bool. Any non-zero value is converted to the value 1.
Also this loop
for (int m = 1; m<=n; m++) {
printf("%d,", m);
eratos[m] = m;
printf("%d,", eratos[m]);
}
invokes undefined behavior because the valid range of indices for an array with n elements is [0, n).
It seems what you need is the following
unsigned int n = 1;
printf("\nPut in number n which is the upper limit: ");
scanf("%u", &n);
unsigned int *eratos = malloc( n * sizeof( unsigned int ) );
for ( unsigned int i = 0; i < n; i++ )
{
printf("%u,", i + 1 );
eratos[i] = i + 1;
printf("%u,", eratos[i]);
}
You have multiple problems in your code.
First you say that eratos is a pointer to bool when you seem to want an array of int.
This is solved by changing the type to pointer to int:
int *eratos = ...;
Then since n is an int, sizeof(n) is the same as sizeof(int), which is typically equal to 4. That is, you only allocate four bytes for your array.
You need to allocate n elements, which is n multiplied by the size of each element (which would be sizeof *eratos):
int *eratos = malloc(n * sizeof *eratos);
Lastly, remember that array indexes in C are zero based, which means an array of n elements will have indexes from 0 to n - 1 (inclusive). Which means eratos[m] will go out of bounds (when m == n).
This can be solved in two ways:
Either subtract 1 for the array index:
for (int m = 1; m <= n; ++m)
{
eratos[m - 1] = m;
}
Or loop from 0 to n - 1 and add 1 to m to get the "natural number":
for (int m = 0; m < n; ++m)
{
eratos[m] = m + 1;
}
On an unrelated note, if you're only supposed to print the numbers between 1 and n (inclusive) then you don't need the array, only a single printf statement in the loop:
for (int m = 1; m <= n; ++m)
{
printf("%d,", m);
}

Integer increment (++) crashes application

I am trying to write a small program in C but I am stuck trying to increment an int.
#include<stdio.h>
#include<string.h>
char * compress(char *input, int size){
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input);
int i = 0;
int counter;
int j;
while(i < size){
counter = 1;
j = i;
while (inputCopy[j] == inputCopy[j + 1] && j < size){
j++;
printf("same! \n");
counter++; // When this line is commented out it works.
}
if (i != j){
i = j;
}else{
i++;
}
}
return inputCopy;
}
main(){
char test[10] = "aaaaaaasdd";
printf("%s \n", compress(test, 10));
printf("%s", test);
return 0;
}
The counter++ line for some reason is making my program crash.
I know it is probably something simple, but can someone point out to me why this is not working?
You need to check j < size first, and strengthen it to j + 1 < size else you run the risk of an out-of-bounds array access, which is undefined behaviour:
while (j + 1 < size && inputCopy[j] == inputCopy[j + 1]){
(The right hand argument of && is only evaluated if j + 1 < size is 1.)
And where is the memory allocated for inputCopy?
You're not allocating data for snprintf. inputCopy is uninitialized, so it's probably writing over the memory used by counter. Make sure you allocate the necessary memory.
Unrelated to this crash, but you have a potential for invalid reads (inputCopy[j + 1]). Switch j < size to (j + 1) < size and move it to the beginning of the while so you'll short circuit.
valgrind (or Clang's address sanitizer) can help catch both of these issues if you're on a Linux system.
Here you define test as an array of length 10:
char test[10] = "aaaaaaasdd";
Then you pass it to compress with 10 as the size:
printf("%s \n", compress(test, 10));
This conditional will remain true while i is 0 through 9:
while(i < size){
And same for j:
j = i;
And when j is equal to 9, this line will try to access element j + 1, which is 10, of your array, which is out of bounds:
while (inputCopy[j] == inputCopy[j + 1] && j < size){
This will cause undefined behavior. Most likely this is the source of your crash, and the thing with counter is incidental.
EDIT: Aaaaaand you're also not allocating any memory for inputCopy on this line, which will also lead to undefined behavior:
snprintf(inputCopy, size, "%s", input);
It is illegal to write to inputCopy. It points to random memory:
char *inputCopy;
char compressedString[100];
snprintf(inputCopy, size, "%s", input); // !? memory not allocated for the inputCopy

C programming Pointer and String operations

So I have an assignment where I need to change certain functions by substituting pointer operations for array operations, and by substituting string operations for character operations. Now I have a basic understanding of pointers, arrays, strings, etc. but I cant understand what it is I have to do, and how I should go about doing it. Here is the code:
#include <stdio.h>
#pragma warning(disable: 4996)
// This program exercises the operations of pointers and arrays
#define maxrow 50
#define maxcolumn 50
char maze[maxrow][maxcolumn]; // Define a static array of arrays of characters.
int lastrow = 0;
// Forward Declarations
#define triple(x) x % 3 == 0
void initialization(int, int);
void randommaze(int, int);
void printmaze(int, int);
void initialization(int r, int c) {
int i, j;
for (i = 0; i < r; i++){
maze[i][0] = 'X'; // add border
maze[i][c - 1] = 'X'; // add border
maze[i][c] = '\0'; // add string terminator
for (j = 1; j < c - 1; j++)
{
if ((i == 0) || (i == r - 1))
maze[i][j] = 'X'; // add border
else
maze[i][j] = ' '; // initialize with space
}
}
}
// Add 'X' into the maze at random positions
void randommaze(int r, int c) {
int i, j, d;
for (i = 1; i < r - 1; i++) {
for (j = 1; j < c - 2; j++) {
d = rand();
if (triple(d))
{
maze[i][j] = 'X';
}
}
}
i = rand() % (r - 2) + 1;
j = rand() % (c - 3) + 1;
maze[i][j] = 'S'; // define Starting point
do
{
i = rand() % (r - 2) + 1;
j = rand() % (c - 3) + 1;
} while (maze[i][j] == 'S');
maze[i][j] = 'G'; // define Goal point
}
// Print the maze
void printmaze(int r, int c) {
int i, j;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++)
printf("%c", maze[i][j]);
printf("\n");
}
}
void main() {
int row, column;
printf("Please enter two integers, which must be greater than 3 and less than maxrow and maxcolomn, respectively\n");
scanf("%d\n%d", &row, &column);
while ((row <= 3) || (column <= 3) || (row >= maxrow) || (column >= maxcolumn)) {
printf("both integers must be greater than 3. Row must be less than %d, and column less than %d. Please reenter\n", maxrow, maxcolumn);
scanf("%d\n%d", &row, &column);
}
initialization(row, column);
randommaze(row, column);
printmaze(row, column);
//encryptmaze(row, column);
//printmaze(row, column);
//decryptmaze(row, column);
//printmaze(row, column);
}
Here are the questions I am struggling on:
Rewrite the function randommaze(row, column) by substituting pointer operations for all array operations. You may not use indexed operation like maze[i][j], except getting the initial value of the pointer.
Rewrite the function printmaze(row, column) by substituting string operations for all character operations.
If someone could please explain to me what I should be doing and how I should be doing it I would really appreciate it. Thanks!
Question 2.:
An array can be used as a pointer to it's first member. So, for example, array[0] and *array return the same thing - the value of the first element of the array. Since arrays are contiguous blocks of memory, if you increment (or add an offset to) a pointer that's pointing to the beginning of an array, you point to the next element of the array. That means that array[1] and *(array + 1) are the same thing.
If you a have a for loop that iterates indexing an array, you could just as well write it using pointer increments. Example:
/* Loop indexing an array */
int my_array [10];
int i = 0;
for(; i < 10; ++i) {
my_array[i] = 0;
}
/* Loop by offsetting a pointer */
int my_array [10];
int i = 0;
int *ptr = my_array; /* Make it point to the first member of the array*/
for(; i < 10; ++i) [
*(ptr + i) = 0;
}
/* Looping by incrementing the pointer */
int my_array [10];
int *ptr = my_array; /* Make it point to the first member of the array */
int *end_ptr = my_array + 10; /* Make a pointer pointing to one past the end of the array */
for(; ptr != end; ++ptr) [
*ptr = 0;
}
All these code examples do the same thing. Assign 0 to all members of the array. If you a have a multidimensional array, just remember that it's still just a contiguous block of memory.
Question 3.:
This question is not so clear to me, so my interpretation of what you're expected to do may be a bit off, but since you're just using printf to print single chars, I'm guessing that you should use a function to output a single char instead. Something like putchar.
Hopefully, this will steer you in the right direction.
It sounds as though you are engaged in a data structures course. The first challenge is to build an array mapping function. For example:
int main(int argc, char **argv)
{
int values[20][40];
values[0][0] = 1;
values[10][10] = 20;
/* Let's print these two ways */
printf("0,0: %d 10,10: %d\n", values[0][0], values[10][10]);
printf("0,0: %d 10,10: %d\n", *((*values) + (sizeof(int) * 0) + sizeof(int) * 0)), *((*values) + (sizeof(int) * 10) + sizeof(int) * 10)));
}
What we are doing is obtaining the address of the very first byte of memory in the 2d array (*values) and then adding a raw number of bytes as an offset to it to locate the value from the "array" that we'd like to access.
One of the main points of an exercise like this is to show you how the language actually works under the hood. This his how array mapping functions work generally and can be used as the basis, for example, for a language or compiler design course later, in addition to fast implementations of far more complex memory structures.
As to the second piece, I'm not super clear on this since there are no actual "string" operations built into C. I'd need a bit more detail there.

How to insert an element into an array on malloc?

say we are going to insert an element into an array on malloc. I know where and how to insert, but I'm having trouble shuffling every succeeding element down by 1. What would be the technical approach for this? Thanks
| x x x x x x x x x x x | original array
| x x x x x 0 x x x x x x | new array
Suppose the "memmove" function is not available to us...
Yes, if you need to do this without memmove, you can do it with a simple loop. Note that you might also need to use realloc first, to expand the size of the allocated array so that it can fit the new element.
The trick to this is having the loop move each element one forward, starting from the last one. A moment's reflection should tell you why this is necessary.
The basic principle is the same whether the array is dynamically allocated, statically allocated or automatically allocated. The main difference is that if there is insufficient room in a dynamically allocated array, you can reallocate it with more space (subject to some system-imposed limits. Assuming there is enough space in the array, you could use memmove() to copy the section of the array after target location up one space, and then set the target location to the inserted value. Or you could write a loop to do the job.
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
Now insert at position n = 2:
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
That's a bulk move, an assignment, and increment the counter because there's one more element in the array.
Since the question was edited to disallow memmove(), here is a solution with simple array indexing, assuming that the same initialization sequence is used:
int i;
int n = 2;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
Complete example code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void print_array(int *a, int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
}
int main()
{
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
int i;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
return(0);
}
As Don suggested, memmove() will allow moving part of this array, in order to make room for the new element.
Depending on the size of the elements in the array, you may also consider storing only pointers, in the array, allowing easier/faster re-shuffling of the array, at the cost of a extra indirection when accessing individual elements. (and also at the cost of having to manage individual element-sized memory blocks). Deciding on this type of approach depends on the amount of reorganization of the array elements, as well as their size.
Alert: in view of the added "picture" in the question, memmove(), or indeed any operation, may be impossible, if the memory move implies writing past the size of memory originally allocated!
If this is really what is desired, the idea of an array of pointers may be more appropriate as this allows allocating an over-sized memory block initially (for the array proper) and to allocate (or dispose of) individual elements as needed.
Edit: "We're not allowed to use memmove()" indicates some form of homework. (BTW do tag it as such !!!)
To better help you we need to understand the particular premise of the question. Here's what appears to be the situtation:
1) we readily have an array, containing say N elements.
2) the array on the heap, i.e. it was allocated using malloc() (or related
functions)
3) the effective size of the malloc-ated block of memory is bigger than that of
the array.
Is #3 true ?
4) Depending on #3 we need to either allocate a new memory block (a bigger one)
and copy the array. We expect this copy would be done in 3 steps
- copy the elements that precede the new element
- copy the new element
- copy the elements that are after the new element
or... (if we have enough room), we'd require two steps
- "shift" the elements that are supposed to be after the new element
This can be done one element at a time, if we wish to avoid memcopy
- copy the new element.

Resources