I am playing with some code in C and also I am trying to understand relationship between pointers and arrays. As you probably know, when I want to make array it could be done like this:
char * arr = "abc";
or
char arr[] = {'a','b', 'c'};
But when I want to do 2D array. It must be done like this
char arr[3][10];
Why declaration like this crashes when I try to load string to that.
char * names[3];
for ( int i = 0; i < 3; i++ ) {
printf("Enter name %d: ", i+1 );
scanf("%s", names[i]);
}
// print names
printf("\nEntered names are: \n");
for ( int i = 0; i < 3; i++ ) {
printf("%s\n", names[i] );
}
It should be 2D array right? Because array is basically pointer.
Could you please explain that?
Thanks.
char * names[3];
Is not a 2D array, it's an array of three pointers to char, if you want to store char arrays in it you must allocate memory to each individual pointer, something like:
for(size_t i = 0; i < 3; i++){
names[i] = malloc(/*length your array of chars*/);
}
You can then store char arrays, using you example:
for(size_t i = 0; i < 3; i++){
printf("Enter name %ld: ", i + 1 );
scanf("%29s", names[i]); //for a malloc size of 30
}
Note that you must be careful with scanf, if the inputed string is longer then the memory allocated to store it you will have stack smashing, i.e. for names[i] with size of 30, you should use %29s specifier, instead of %s. Though this approach is not whitout its issues, namely possible characters left in stdin buffer, it's definitely safer.
Alternatively you can assign them string literals (in this case it's best to declare the array as const, otherwise if you try to edit one or more characters it'll result in a segfault):
const char* names[3];
for(size_t i = 0; i < 3; i++){
names[i] = "My string literal";
}
You can also make them point to existing char arrays:
char arr[3][10];
char* names[3];
for(size_t i = 0; i < 3; i++){
names[i] = arr[i];
}
char * names_1[3];
It's not a pointer. It's an array of pointers.
char names_2[3][10]={"one", "two", "three"};
char (*p_names_2)[10]=names_2;
Now it's a pointer to your 2D-Array. Just define a function and try to use it with your "pointers" as parameters.
void print_names(char names[][10], const int row){
for(int i=0; i<row; i++)
puts(names[i]);
}
Now call it with:
print_names(names_2, 3);
print_names(p_names_2, 3);
print_names(names_1, 3); //WRONG
And you'll see the difference.
char* names[3] is not strictly a 2D array (they don't exist in C or C++); it's an array of arrays. So each element of names contains simply a char*, which has not been initialised.
Note also that a c-style string is a null-terminated array of chars, so your original arr is not a c-style string. To make it a c-style string you would need:
char arr[] = {'a','b','c',0};
making it an array of length 4, not 3.
Missing off the null-terminator will mean that most functions will run off the end of the allocated memory, because they won't know when the string stops.
pointer is a type of variable, which can only contain an address of another variable. It can't contain any data. You can't store data into a pointer.Pointers should point at memory location.
So to use a pointer in the right way ,it must always point at a valid memory location in stack or memory dynamically allocated in heap.
this char * names[3] is an array of pointers ,so you need to reserve memory for it and then initialize it.You need to use some thing like this:
char *name[3];
for(int i=0;i<3;i++)
{
name[i]=malloc(strlen(string)+1);
}
also you should allocate memory for char *arr too.
char *arr=malloc(strlen(data)+1)
then initialized it.
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);
}
beginner here
This is absolutely infuriating me, how do I create an array that holds strings where the length / amount of strings are unknown? I essentially want to create a dictionary where
array[0] = "word"
array[1] = "word2"
array[2] = "word3"
and so on
I tried :
array** = malloc(INIT); where init was defined as 10
memset(array, '\0', 10)
then, under a loop
array[i] = malloc(INIT)
array[i] = string from another source ( array2[i] ) (array2 is a char*)
but that just gives errors / junk text and I have no clue how to assign strings to the array
I'm having a hard time understanding pointers / jargon in general, I've looked at all the similar questions and can't understand any of the answers.
Try doing this -
int main(){
int i;
char *arr[10];
for(i=0;i<10;i++){
char str[1000];
scanf("%s", str);
arr[0] = (char*) malloc(strlen(str));
strcpy(arr[0], str);
}
return 0;
}
You can dynamically create an array of pointers to strings and in that way keep it flexible:
char** array = malloc(sizeof(char*)*n); // allocates an array of char* pointers
if you later need to extend the array use realloc
char** newarray = realloc(array,sizeof(char*)*(n+1));
if (newarray != NULL)
{
array = newarray;
...
}
You must also remember to allocate space for where the pointers point to for storing your strings
array[i] = strdup("blabla");
or
array[i] = malloc(strlen("blabla")+1);
strcpy(array[i], "blabla" );
I'm trying to create and store a char* array.
So, first I tried this:
int main() {
char* values[3];
values[0] = "Hello";
values[1] = "Mew meww";
values[2] = "Miau miau =3";
for(int i=0; i<sizeof(values); i++)
printf("%s", values[i]);
}
it works with this OUTPUT:
Hello
Mew Mew
Miau miau =3
If i try:
printf("%s", "Tamaño del diccionario: ");
int tam;
scanf("%i", &tam);
char* dic[tam];
Word words[tam];
for(int i=0; i<tam; i++)
{
printf("Palabra %d: ",(i+1));
scanf("%32s", &dic[i]);
}
for(int i=0; i<tam; i++)
{
printf("%s",dic[i]);
printf("\n");
}
Show non-legible stuff like "0xassdfsdf"
What can I do to store it right in memory?
#include <stdio.h>
#include <stdlib.h>
int main(){
char* values[3];
values[0] = "Hello";
values[1] = "Mew meww";
values[2] = "Miau miau =3";
for(int i=0; i<sizeof(values)/sizeof(*values); i++)
printf("%s\n", values[i]);
printf("%s", "Size for dictionary: ");
int tam;
scanf("%i", &tam);
char *dic[tam];
for(int i=0; i<tam; i++){
printf("Palabra %d: ",(i+1));
dic[i] = malloc(33);
scanf("%32s", dic[i]);
}
for(int i=0; i<tam; i++){
printf("%s\n", dic[i]);
free(dic[i]);
}
return 0;
}
One problem is
scanf("%32s", &dic[i]);
which should be
scanf("%32s", dic[i]);
because the array contains pointers to storage, not storage itself, and what you should pass to scanf is this pointer. Indeed, a char* is just a 4-byte pointer. The array char* dic[tam] contains some such pointers, so that dic[0] is a 4-byte pointer to char, and &dic[0] is the address of this pointer. Then your
scanf("%32s", &dic[i]);
just overwrites this pointer plus corrupts memory after it.
Another problem is that you do not initialize the array, so it does not point to any storage.
char* dic[tam];
here the array contains pointers to random places in memory.
scanf("%32s", &dic[i]);
most probably this fails at all. So in your printf you print pointers to random places in memory.
A (bad) solution is:
for(int i=0; i<tam; i++)
{
printf("Palabra %d: ",(i+1));
dic[i] = new char [1000]; // here you assign it some storage
scanf("%32s", dic[i]); // NOT &dic[i]
}
or (slightly better)
for(int i=0; i<tam; i++)
{
printf("Palabra %d: ",(i+1));
char buffer [1000]; // temporal storage arguably large enough
scanf("%32s", buffer);
dic[i] = new char [strlen (buffer) + 1]; // storage of the right size to hold the string
strcpy (dic[i], buf); // copy the data to this new storage
}
The key thing to understand for both of your examples is that a char * value stores the address of a byte in memory. By convention, C strings are represented as a pointer to the first byte of the string, with a null byte marking the end. When you assigned constant strings into your array, the compiler allocated the necessary memory and placed the pointers into your array, but when you are not using constants it is your responsibility to allocate the buffer to store the string, and then store that pointer in the array yourself.
In your second example you have allocated storage for several pointers to char, but you have not made those pointers refer to valid buffers, so accessing them with either return garbage or crash the program. There are (at least) two ways to address this: either allocate a fixed-size buffer on the stack and store your data there, or dynamically allocate memory from the heap using malloc.
The former has the advantage of handling the deallocation of the buffers automatically, but requires you to decide at compile time how much memory to allocate for each string:
char* dic[tam];
char buf[tam * 32]; // allocate 32 bytes per element.
for (int i = 0; i < tam; i++) {
// Make the pointers in ``dic`` refer to 32-byte offsets into the buffer.
dic[tam] = &(buf[tam * 32]);
}
You can also allocate dynamically using malloc. You could actually allocate one big tam * 32 buffer this way too, but for the sake of example here's how to allocate a separate buffer for each element:
char* dic[tam];
for (int i = 0; i < tam; i++) {
// Allocate 32 bytes per element.
// (This value can be decided at runtime, if you want.)
dic[tam] = malloc(32);
}
But since this uses malloc you need to be sure to clean up this memory before you return to avoid a memory leak. e.g. at the end of your routine:
for (int i = 0; i < tam; i++) {
// de-allocate the buffer we allocated earlier
free(dic[tam]);
}
(This method of calling malloc multiple times in a loop may also cause memory fragmentation if you do it a lot, but that's an advanced topic not worth worrying about for a small program.)
How to allocate a 2-d array of strings............By that I mean if t[][] is the array
{char t[0][0]} should store a string,
{ char t[0][1] } should store a string etc........Can we use {char ***t } to accomplish this ..If so how should I approach it?? Or can we also go about doing it like
{ char **t[10] } , where 10 is the maximum length of any string I am going to enter in the array...
well first of all you said: By that I mean if t[][] is the array {char t[0][0]} should store a string, { char t[0][1] } , if t[0][1] would store a string then it's not a 2D array you want but rather a 3D array , in a 2D array it's t[0] that stores the string (because a string is an array , and 2D arrays are arrays of arrays) , having said that I'm going to show you how to Dynamically allocate memory for a 2D array and you can use the principle to create a 3D one.
char **matrix = NULL;
int i ;
matrix = malloc(sizeof(char) * ROWS);
for(i = 0 ; i < COLUMNS ; i++)
matrix[i] = malloc(sizeof(char));
and there you have it , just don't forget to use free after you're done with that array
Edit :
to free a dynamically allocated 2D array you need to free the last thing you malloced first , like this :
for(i = 0 ; i < COLUMNS ; i++)
free(matrix[i]);
free(matrix);
Edit:
To do this you will have to specify the cardinal of the second dimension and the maximum lenght of the string. Then use the name of the array with sizeof and the number of strings you want to allocat for:
#include <stdio.h>
#include <string.h>
int main(void) {
/* 10 is the lenght of each string and 1 for the '\0'
10 is the number of strings per each 2D array
5 is the number of 2D arrays */
char (*array)[10][10+1] = malloc(5*sizeof(*array));
// Exemple
strcpy(array[0][0], "hello, world");
printf("%s\n", array[0][0]);
return 0;
}
Live Demo
You have to allocate an array of pointers to pointers to char, which is:
char ***array = (char ***)malloc(sizeof(char**)*ARRAY_X);
Then, you have to allocate each single array of pointers to chars:
for(int i = 0; i < ARRAY_X; i++){
array[i] = (char **) malloc(sizeof(char *)*ARRAY_Y);
}
Finally you have to allocate strings:
for(int i = 0; i < ARRAY_X; i++){
for(int j = 0; j < ARRAY_Y; j++){
array[i][j] = (char *) malloc(sizeof(char)*ARRAY_Z);
}
}
ARRAY_X and ARRAY_Y and ARRAY_Z are int indicating the dimension of the 2-d array of strings (which is a 3-d array of chars).
I have char * lines[1000] string that can hold 1000 characters. How to create 100 arrays of that string. I get error with this code down.
char * lines[1000];
lines = (lines*)malloc(100 * sizeof(lines));
main.c:19:20: error: expected expression before ')' token
The simplest way is:
char lines[100][1000];
Alternatively:
char* lines[100];
int i;
for (i = 0; i < 100; i++) {
lines[i] = malloc(1000);
}
...
for (i = 0; i < 100; i++) {
free(lines[i]);
}
The latter is a bit more flexible in that -- with minor modifications -- it permits you to allocate a different amount of memory for every string.
It looks like you want an array strings, each string holding at most 1000 characters. There are some issues with your code.
You've declared an array of char *s but what you really want is a pointer to an array of chars. For that, your declaration should be
char (*lines)[1000];
On the other hand, you shouldn't forget about the NULL bytes at the end of strings, and should probably instead declare
char (*lines)[1001];
To set the pointer, you'll want to use
lines = (char (*)[1001]) malloc(100 * sizeof(char[1001]));
or
lines = (char (*)[1001]) malloc(100 * sizeof(*lines));
the latter working because, with lines a pointer to an array of chars, *lines is a char[1001]. Remember to make sure you didn't get a NULL pointer back.
At the end, you should free the memory you've malloced with
free(lines);
You can write a for-loop as:
char * lines[1000];
int i = 0;
for (i = 0; i < 1000; i++)
{
lines[i] = (char*)malloc(100 * sizeof(lines));
}
Don't forget to free-up the memory pointed by all the pointers
for (i = 0; i < 1000; i++)
{
free(lines[i])
}
Why don't you create a 2 dimensional array?