I'm a noob so don't be hard on be.
Instead of something like this;
char string[NUM OF STRINGS][NUM OF LETTERS];
Is it possible to dynamically allocate how many strings will be in the array with malloc just like when you dynamically allocate memory for char pointer? Something like this:
int lines;
scanf("%d", &lines);
char *string[NUM OF LETTERS]
string = malloc(sizeof(char) * lines);
I tried it but it doesn't work; There must be something I'm doing wrong.
The other solution I thought of was:
int lines;
scanf("%d", &lines);
char string[lines][NUM OF LETTERS];
but I want to know if that's possible using malloc.
You can also use malloc for each word, like this
char **array;
int lines;
int i;
while (scanf("%d", &lines) != 1);
array = malloc(lines * sizeof(char *));
if (array != NULL)
{
for (i = 0 ; i < lines ; ++i)
{
int numberOfLetters;
while (scanf("%d", &numberOfLetters) != 1);
array[i] = malloc(numberOfLetters);
}
}
where numberOfStrings and lengthOfStrings[i] are integers that represent the number of strings you want the array to contain, an the length of the ith string in the array respectively.
You have two methods to implement this.
First is more complicated, cause it requires the allocation of memory for array of pointers to strings, and also allocation of memory for each string.
You can allocate the memory for entire array:
char (*array)[NUM_OF_LETTERS]; // Pointer to char's array with size NUM_OF_LETTERS
scanf("%d", &lines);
array = malloc(lines * NUM_OF_LETTERS);
. . .
array[0] = "First string\n";
array[1] = "Second string\n";
// And so on;
A disadvantage of the second method is that NUM_OF_LETTERS bytes are allocated for each string. So if you has many short strings, the first method would be better for you.
In case you want contiguous memory allocation:
char **string = malloc(nlines * sizeof(char *));
string[0] = malloc(nlines * nletters);
for(i = 1; i < nlines; i++)
string[i] = string[0] + i * nletters;
For more detailed explanation: Read FAQ list · Question 6.16.
int lines;
scanf("%d", &lines);
char (*string)[NUM OF LETTERS]
string = malloc(sizeof(*string) * lines);
char **ptop;
int iStud;
int i;
printf("Enter No. of Students: ");
scanf("%d",&iStud);
ptop=(char **) malloc(sizeof(char)*iStud);
flushall();
for(i=0;i<iStud;i++)
{
ptop[i]=(char *) malloc(sizeof(char)*50);
gets(ptop[i]);
}
for(i=0;i<iStud;i++)
{
puts(ptop[i]);
}
free(ptop);
Related
is there a simple one liner I can use in C to allocate arrays in (pointer of arrays)
This line creates 10 pointers of arrays
char *out[10];
I can't do this
char *out[100]=(char[10][100])malloc(sizeof(char)*10*100);
error: cast specifies array type
same error with
char *out[10]=(char*[10])malloc(sizeof(char)*10*100);
do I need to do it in loop like this
int main()
{
char *out[10];
int x=0;
while(x<10)
{
*(out+x)=malloc(sizeof(char)*100);// is this line correct?
x++;
}
*out[0]='x';
printf("%c\n",out[0][0]);
free(out);
return 0;
}
but this cause warning that
req.c:75:3: warning: attempt to free a non-heap object ‘out’ [-Wfree-nonheap-object]
75 | free(out);
so do I need to allocate and free each array in (array of pointers) in loop
Can't I do allocation and free arrays in array of pointer in one line instead of loop?
or is there anything thing in my loop wrong too
To allocate an array of pointers to strings, you need to do:
char** out = malloc(sizeof(char*[10]));
The whole point of using this form is that each pointer in that array of pointers can be allocated with individual size, as is common with strings. So it doesn't make sense to allocate such with a "one-liner", or you are using the wrong type for the task.
In case you don't need individual sizes but are rather looking for a char [10][100] 2D array with static size, then the correct way to allocate such is:
char (*out)[100] = malloc(sizeof(char[10][100]));
You can allocate the full array in one single step and have pointers inside that array:
char *out[10];
data = malloc(100); //sizeof(char) is 1 by definition
for (int x=0; x<10; x++) {
out[i] = data + x * 10;
}
*out[0] = 'x';
printf("%c\n",out[0][0]);
free(data); // you must free what has been allocated
int i;
char** out = (char**)malloc(sizeof(char*)*10);
for(i = 0; i<10;i++)
out[i] = (char*)malloc(sizeof(char)*100);
out[1][1] = 'a';
OR with same dimensions
#include <stdio.h>
#include <stdlib.h>
void main()
{
int r = 10, c = 100; //Taking number of Rows and Columns
char *ptr, count = 0, i;
ptr = (char*)malloc((r * c) * sizeof(char)); //Dynamically Allocating Memory
for (i = 0; i < r * c; i++)
{
ptr[i] = i + 1; //Giving value to the pointer and simultaneously printing it.
printf("%c ", ptr[i]);
if ((i + 1) % c == 0)
{
printf("\n");
}
}
free(ptr);
}
#include<stdio.h>
int main(){
char *msg[10];
scanf("%s", msg[0]);
scanf("%s", msg[1]);
scanf("%s", msg[2]);
scanf("%s", msg[3]);
}
When I try to run this code, it gives errors. Am I doing something wrong? I'm still a beginner in C language.
char *msg[10];
Here msg is array of 10 char pointer and they are not initialized. If you want to store something into them, first allocate the memory dynamically.
for(int i = 0; i < 10; i++) {
msg[i] = malloc(MAX_NO_OF_BYTES); /* MAX_NO_OF_BYTES is the no of bytes you want to allocate */
scanf("%s",msg[i]); /* store the data into dynamically allocated memory */
}
print it & do the operation as you wanted
for(int i = 0; i < 10; i++) {
printf("%s\n",msg[i]);
/** operation with array of char pointer **/
}
Once work is done, free the dynamically allocated memory using free() for each char pointer as
for(int i = 0; i < 10; i++) {
free(msg[i]);
}
I hope it helps.
The trouble is that char *msg[10] is a array of 10 char pointers for which you need to explicitly allocate memory or use a static array instead.
Option-1:
for (i=0; i<10; i++)
{
msg[i] = malloc(sizeof(char) * 100)
}
Option-2
char msg[10][100]
I am new to C and trying to initialise a 2D array. I need both columns of the array to be char *, as they will contain string values.
I have it working with the array storing ints but for some reason, when I try to store string values when it prints it displays (null). Below is the code for how I am initialising and storing the data as an int (This appears to be working).
int **array;
int row = 0;
array = malloc(2 * sizeof(int*));
int i;
for (i = 0; i < 2; i++)
{
array[i] = malloc(2 * sizeof(int));
}
array[0][0] = i;
array[0][1] = i;
printf("array[0][0]: %i\n", array[0][0]);
Below is how I am doing the above but using string values instead.
char **array;
int row = 0;
array = malloc(2 * sizeof(char*));
int i;
for (i = 0; i < 2; i++)
{
array[i] = malloc(2 * sizeof(char*));
}
array[0][0] = "Test[0][0]";
array[0][1] = "Test[0][1]";
printf("array[0][0]: %s\n", array[0][0]);
Thanks for any help you can provide.
You have the wrong level of pointer indirection, which is over-complicating things.
I think it would be easier for you if you thought of the array as an array of structures, each structure holding two pointers:
struct row {
char *column1;
char *column2;
};
then it's (hopefully) clearer that once you've allocated an array of struct row, you have two pointers in each row, you don't need to allocate room for the pointers themselves.
const size_t num_rows = 1;
struct row * rows = malloc(num_rows * sizeof *rows);
if(rows != NULL)
{
rows[0].column1 = "row 0, column 1";
rows[0].column2 = "row 1, column 2";
}
Note that this uses string literals, otherwise you might need to allocate room for the strings to be stored, depending on where the data comes from.
The num_rows value could of course come from anywhere in your program, I'm just trying to illustrate what controls the number of rows memory is allocated for.
Save yourself the trouble and don't use 2D arrays in C. It's more convenient to use 1D arrays.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const int nstrings = 2;
const int width = 20; //width of maximum string.
char* array = (char*)malloc(sizeof(char)*nstrings*width);
strcpy(&array[0*width],"Test[0][0]");
strcpy(&array[1*width],"Test[1][0]");
printf("string 0: %s\n", &array[0*width]);
printf("string 1: %s\n", &array[1*width]);
free(array);
}
I want to allocate dynamic an array of chars. So i ve the above code
void initialize(char **document_table, int size){
int x, i, j, M;
printf("how many words every line: "); scanf("%d", &M);
document_table = malloc(sizeof(char) * size);
for(x = 0; x < size; x ++) {
document_table[x] = malloc(sizeof(char) * M);
}
for(i=0; i<N; i++){
for(j=0; j<N; j++){
scanf("%c",&document_table[i][j]);
}
}
}
but it seems that after the allocation of the memory the function stop working.
The declaration document_table = malloc(sizeof(char) * size); should have sizeof(char*), since a 2D array is an array of pointers to 1D arrays.
Issue 1: char** document_table is itself passed by value. This means that calling code such as:
char** document_table = 0;
initialize(document_table,2);
/* document_table still 0 here */
will not initialise the passed parameter. Likely want to make the document_table the return value, or pass in its address.
Issue 2: N should be size?
Issue 3: scanf("%c") is inconsistent with the definition of M being "words". %c represents single characters. Also, the text every line implies line oriented input, but again this is not what the scanning looks for. If the document stores "words" then:
a document is an array of lines
a line is a array of words
a word is an array of characters
So a document is actually a 3D array of characters.
You should allocate pointers in your array:
document_table = malloc(sizeof(char*) * size);
Notice the char* in the sizeof() operator
I am still new with C and I am trying to empty a 2d char array. Here is the declaration:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = (char*) calloc (strlen(buf), sizeof(char*));
}
Here is where I try to empty it:
void make_empty(char **arg_array)
{
int i;
for(i = 0; i <= BUFSIZ; i++)
{
arg_array[i][0] = '\0';
}
return;
}
Any help is appreciated
So, am I doing it right because this seems to give me segfaults when I try to add data to the array again and then print it?
Empty is just to have it empty - how can I explain more? lol
Try this:
void make_empty(char **arg_array, int rows, int cols)
{
int i,j;
for(i = 0; i <rows; i++)
{
for(j=0; j<cols;j++)
{
arg_array[i][j] = '\0';
}
}
return;
}
Where rows is number of rows and cols number of cols of your array.
P.S. This function clears the whole array as you should always do. As I commented before, putting '\0' as a first char in string does not clear the whole row, it only makes the rest of it ,,invisible'' for functions like printf. Check this link for more information: http://cplusplus.com/reference/clibrary/cstdio/printf/
There is no need to empty it. Often in C, memory allocation is done with malloc which simply returns to you a block of memory which is deemed owned by the caller. When calloc is called, as well as returning you a block of memory, the memory is guaranteed to be initialized to 0. This means for all intents and purposes it is already 'empty'.
Also I'm not quite sure if your code does what you are intending. Let me explain what it does at the moment:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
This line is simply wrong. In C, there is no need to cast pointers returned from calloc because they are of type void *, which is implicitly casted to any other pointer type. In this case, you are storing it in a char type which makes no sense. If you do this:
char ** arg_array = calloc(strlen(buf), sizeof (char**));
Then it allocates an array of pointers of strlen(buf) length. So if buf is "hello" then you have now allocated an array which can store 5 pointers.
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = calloc (strlen(buf), sizeof(char*));
}
Again, I have removed the redundant cast. What this does is populates the array allocated earlier. Each index of the array now points to a char string of strlen(buf) * sizeof(char *) length. This is probably not what you want.
Your question is more clear to me now. It appears you want to remove the strings after populating them. You can do it two ways:
Either free each of the pointers and allocate more space later as you did before
Or set the first character of each of the strings to a null character
To free the pointers:
for(i = 0; i<(strlen(buf)); i++)
{
free(arg_array[i]);
}
To set the first character of each string to a null character:
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i][0] = '\0';
}
That is the same code as what you have originally and should be fine.
As proof, the following code will run without errors:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char * buf = "hello";
char ** arg_array = calloc(strlen(buf), sizeof (char**));
unsigned int i;
for(i = 0; i < strlen(buf); i++) {
arg_array[i] = calloc(strlen(buf),
sizeof(char *));
}
for(i = 0; i < strlen(buf); i++) {
arg_array[i][0] = '\0';
}
for(i = 0; i < strlen(buf); i++) {
free(arg_array[i]);
}
free(arg_array);
return EXIT_SUCCESS;
}
If your code is segfaulting, the problem is coming from somewhere else. Did you overwrite the arg_array variable? Are you sure BUFSIZE is equal to strlen(buf)?