C - writing and reading a dynamical array - arrays

I'm trying to create a 2D array for storing names (with max 50 characters each). I have written a code, but it isn't working properly, where's the problem? (I can do this with statics arrays, however at the beginning my program won't know how many names I will want to store in the array). Here's my code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n=5;
int size=51;
char *a_name=(char*)malloc(n*size*sizeof(char));
for(int i=0;i<n;i++){
scanf("%s",&a_name[i]);
}
for(int i=0;i<=n;i++){
printf("%s\n",a_name[i]);
}
return 0;
}

What you need is not an array of char but an array of char *.
Try this:
int n = 5, size = 51;
char **name_array = (char **)malloc(sizeof(char *) * n);
for (int i = 0; i < n; ++i) {
name_array[i] = (char *)malloc(sizeof(char) * size);
// You may initialize the array first.
scanf("%s\n", name_array[i]);
}
Remember to release the memory when you no longer need the names.

Related

How to initialize and access array member allocated using this method

I have 2D array allocated dynamically using this method:
How do we allocate a 2-D array using One malloc statement
#include <stddef.h>
int main() {
size_t i;
unsigned int nrows=2;
unsigned int ncolumns=3;
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
int * const data = array + nrows;
for(i = 0; i < nrows; i++) {
array[i] = data + i * ncolumns;
printf("%x\n", data + (i * 3));
}
}
I understand that array[0] points to 1st 1D array (of 2D array) and array[1] points to 2nd 1D array, but now how to initialize (and access) others member of this 2D array, for instance a[0][1] can be access like?
array[0] + (char *)1
It would great, if I may ask for some graphical view of it.
The main problem is that you read a lot of harmful answers in that other post. You are making everything needlessly slow and complicated. Instead study Correctly allocating multi-dimensional arrays (which has the requested graphical view as "ASCII art").
Fixed code printing some hex data as example:
#include <stdlib.h> // include this!
#include <stdio.h>
int main()
{
// memory in C is laid out in rows, so ideally use rows as inner index
unsigned int col=4;
unsigned int row=8;
int (*array)[row] = malloc(sizeof(int[col][row]));
int count=0; // some data
for(size_t i=0; i<col; i++)
{
for(size_t j=0; j<row; j++)
{
array[i][j] = count++;
printf("%.2X ", array[i][j]);
}
printf("\n");
}
free(array); // call this!
}

dynamically create multiple character array at runtime

I need to create character array at runtime because question input goes like this:
1. The first line contains , N the number of strings.
2. The next N lines each contain a string.
I tried creating 2-D array but it didn't work.
int main() {
int n,count;
scanf("%d",&n);
for(int i=0; i<n; i++){
char* arr[i]= char*(malloc(sizeof(char)));
}
return 0;
}
Do something like this:
#define STRINGSIZE 30;
int main() {
int n,count;
scanf("%d",&n);
char **arr;
arr = malloc(sizeof(char*) * n);
for(int i=0; i<n; i++){
arr[i]= malloc(sizeof(char) * STRINGSIZE);
}
return 0;
}
Explanation:
In C, you have pointers to access array. For a multidimensional array with variable lengths, its common to have pointer to pointers. So char **arr; arr = malloc(sizeof(char*) * n); means that you're creating an array of pointers to char. Then you need to call malloc for each of these pointers to allocate memory for each string.
Of course, you do not need to use a constant for string sizes. You can use a variable instead, and you can use different sizes for each string.
Note:
To avoid problems in the future if you want to change the array to an int array instead, do like this and you do not have to worry about changing on more places:
char **arr;
arr = malloc((sizeof a[0]) * n);
for(int i=0; i<n; i++){
arr[i]= malloc((sizeof a[0][0]) * STRINGSIZE);
}
Also, do not cast malloc
And as kkk pointed out in the comments. Check return values.
arr = malloc(sizeof(char*) * n);
if (NULL == arr) {
perror("Could not allocate memory");
exit(EXIT_FAILURE);
}

Sorting array of strings with qsort

This program takes an integer value which then determines the amount of strings that can be inputted, once the user has entered the amount of strings that they specified they may input another integer and then input those amount of strings. Once done the program sorts the strings based on their lengths in descending order. However the qsort doesn't work, it ends up outputting how the order of when the strings were originally entered.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sort(const void * a, const void * b){
size_t fa = strlen((const char *)a);
size_t fb = strlen((const char *)b);
return (fa < fb) - (fa > fb);
}
int main(void){
char pointer[100];
int n;
scanf("%d", &n);
char** strings = malloc(n * sizeof(char*));
int i;
for (i = 0; i < n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int m;
scanf("%d", &m);
strings = realloc(strings, (n + m) * sizeof(char*));
for (i = n; i < m + n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
for (g = 0; g < k; g++){
printf("%s", strings[g]);
printf("\n");
}
}
You're not calling qsort correctly at all.
The 2nd parameter is the number of elements in the "array" that you are sorting. You're currently passing it a which as others have pointed out isn't set to anything. Compiling your code with the "-Wall" option will show you those kinds of errors.
The 3rd parameter is the size of one of the elements in the "array", but you've confused this with the size of an unrelated variable pointer? You could write it like sizeof(strings[0]).
The finished call should look like qsort(strings,k,sizeof(strings[0]),sort);.
But that still won't work because your sort() function is being passed two pointers to elements in your "array" (char **) and you're treating them as two elements of the "array" (char *). So you'd want something like
size_t fa = strlen(*(char **)a);
Well, this:
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
makes no sense at all, a has no value so this is undefined behavior.
Also sort() is broken, it should just be strcmp().

Using scanf to fill out a multidimensional array (C language)

I was wondering how to properly use scanf to fill out a multidimensional array.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int n; //number of rounds
int* sArray; //multidimensional array that holds the scores of both players
int i;
scanf("%d", &n);
sArray = (int*) calloc (n * 2, sizeof(int));
for(i=0; i<n; i++) {
scanf("%d %d", &sArray[i][1], &sArray[i][2]);
}
return 0;
}
It gives me an error, "Subscripted value is not an array, pointer, or vector." Any help would be much appreciated!
A two dimentional array is defined as follows: int sArray[N][M], but since you wanted to work with the dynamic memory I offer you to take a look at a pointer to pointer at int:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int **sArray;
sArray = (int **)malloc(n * sizeof(int *));
int i;
for(i = 0; i < n; i++)
{
sArray[i] = (int *)malloc(2 * sizeof(int));
scanf("%d %d", &sArray[i][1], &sArray[i][2]);
}
return 0;
}
Don't forget to clean-up after you are done with the array.
As mentioned in the commentaries, You don't need to cast the result of malloc if you work with pure c. I did this because my c++ compiler refused to compile it without this cast.
You might need to check errors during a dynamic allocation of the array. Read more here
There are already a lot of good answers here on how to define your dynamic 2D array. But this variant was not yet mentionned, so I put it for the records.
As the last dimension of your array is fixed, you could define your 2D array as follows:
int (*sArray)[2]; //multidimensional array that holds the scores of both players
...
sArray = (int(*)[2]) calloc (n, sizeof(int)*2); // self explaining
In this way, all the elements will be stored contiguously (each n element of the allocated array, is 2 contiguous integers), without the need for an array to arrays.
The rest of your code remains identical. Except that you shoud address sArray[i][0] and ..[1] instead of [1] and [2] and free memory at the end. In C array indexing starts always from 0 and goes to size-1.
Of course, this approach is strictly limited to 2D arrays where the last dimension is fixed.
Live demo with addressing
Usually to fill a bidimensional array you will use two nested for loops.
For example :
int array[2][3] = {0};
for (i = 0; i < 2; i++)
for (k = 0; k < 3; k++)
scanf("%d", &array [i][k]);
You could do this too:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int n; //number of rounds
int** sArray = malloc(2 * sizeof(int*)); //multidimensional array that holds the scores of both players
scanf("%d", &n);
sArray[0] = (int*)calloc(n , sizeof(int));
sArray[1] = (int*)calloc(n , sizeof(int));
int i;
for (i = 0; i < n; i++) {
scanf("%d %d", &sArray[0][i], &sArray[1][i]);
}
free(sArray[0]);
free(sArray[1]);
free(sArray);
return 0;
}

Declaring global variable (array) inside a function in C

I need to declare a global two-dimensional array in C.
The size of the array is determined by the width and height of a given picture.
So I first have to load the picture, and only then create the array. But if I want a variable (in this case, my array) to be global, I have to declare it at the top of the file and not inside a function.
So how can I declare a array as global when I only know its size after the execution of the main() function?
EDIT:
(I've also tried the other solutions so this comments refers to all of them)#Mimisbrunnr
First, thanks for the quick response!
I've tried but I can't see to make it work. I'm probably missing something stupid, but how does "array" becomes global? It says on test() that 'array' is undeclared
int *buffer;
int main() {
int i;
int x_size=100;
int y_size=100;
int * buffer = malloc(sizeof(int)*x_size*y_size);
int ** array = malloc(sizeof(int*)*y_size);
for(i = 0; i<y_size; i++) {
array[i]=&buffer[i*x_size];
}
array[0][1] = 5;
test();
return 0;
}
void test(){
printf("%d",array[0][1]);
}
create a global pointer and then malloc the space into it.
char * buffer;
int main(void) {
buffer = malloc( /* Width * Height */ );
}
I didn't actual execute this code, but this should get you started.
int x_size = 100;
int y_size = 100;
int ** array;
array = malloc(sizeof(int *)*y_size);
for(int i = 0; i<y_size; i++)
array[i] = malloc(sizeof(int)*x_size);
larsmans made a good point.
what about this?
int x_size = 100;
int y_size = 100;
int * buffer = malloc(sizeof(int)*x_size*y_size);
int ** array = malloc(sizeof(int *)*y_size);
for(int i = 0; i<y_size; i++)
array[i] = &buffer[i*x_size];
It looks like you might need some basic C tutorial.
int *buffer;
int **array;
int main()
{
int x_size=100;
int y_size=100;
int i;
/*int * */ buffer = malloc(sizeof(int)*x_size*y_size);
/*int ** */ array = malloc(sizeof(int*)*y_size);
for(i = 0; i<y_size; i++)
array[i]=&buffer[i*x_size];
array[0][1] = 5;
test();
return 0;
}
void test()
{
printf("%d",array[0][1]);
}
use a static variable (pointer) and allocate the array dynamically using malloc.

Resources