/* program to accept and print 5 strings using pointers */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define SIZE 100
int main()
{
char **s;
int i;
s = (char *)malloc(sizeof(char)*5);
for(i=0;i<5;i++)
{
*(s+i) = (char *)malloc(sizeof(char)*SIZE);
}
printf("enter 5 strigs\n");
for(i = 0;i<5;i++)
{
fgets((s+i),SIZE,stdin);
}
//printing the strings
for(i = 0;i<5;i++)
{
puts((s+i));
}
return 0;
}
This program accepts 5 strings from keyboard and prints on screen.It works properly but shows many warnings.Is there any other ways to do same operation(using pointers only).please suggest me.
The biggest issue in your code is that you do not allocate enough memory to s:
s = malloc(sizeof(char*)*5);
// ^
// Add an asterisk here
Otherwise, it's undefined behavior.
Second biggest is that you are not freeing any of the memory that you allocated. This is a memory leak. To do it properly you need a loop that calls free on every element of s, and then on the s itself:
for(i = 0;i<5;i++) {
free(s[i]);
}
free(s);
Finally, you should not be casting the results of malloc.
As a point for style, consider defining a constant for the number of elements in s, in the same way that you defined SIZE instead of using 100 directly. It may also make sense to switch to array-style dereference, rather than doing pointer arithmetic manually, i.e. puts(s[i]); instead of puts((s+i));
int main()
{
char **s;
int i;
s = (char **)malloc(sizeof(char*)*5); //double pointer (char**)
for(i=0;i<5;i++)
{
*(s+i) = (char *)malloc(sizeof(char)*SIZE);
}
printf("enter 5 strigs\n");
for(i = 0;i<5;i++)
{
fgets(*(s+i),SIZE,stdin); // first location *(s+0)
}
//printing the strings
for(i = 0;i<5;i++)
{
puts(*(s+i)); // first location *(s+0)
}
return 0;
}
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);
}
The program should do this: write a doubleArray() function, which takes in input an array of int and its size (as a pointer to int). In the main(): ask the user to input an integer n between 1 and 4, then dynamically create an array of size n. Then start filling the array with 2048 randomly generated int: each time the array is full, call the doubleArray function; each time the function doubleArray is called, print the content of the array.
My code works until the size of array n reach a number around 250, then stops inside the for loop.
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
void doubleArray(int vect[], int *dim)
{
int n = *dim *2;
*dim = n;
vect = (int*)realloc(vect, n*sizeof(int));
}
void stampaArray(int vect[], int dim)
{
for (int i=0;i<dim;i++)
{
printf("%d ",vect[i]);
}
printf("\n");
}
int main()
{
printf("Insert a number between 1 and 4: ");
int n;
scanf("%d",&n);
if ((n<1)||(n>4))
{
printf("Number not valid, try again: '");
scanf("%d",&n);
}
int *arr = (int*) malloc (n*sizeof(int));
srand(time(NULL));
int num;
for (int i=0;i<220;i++)
{
num = rand();
if (i==n)
{
doubleArray(arr, &n);
stampaArray(arr, n);
}
arr[i]=num;
}
stampaArray(arr,n);
return 0;
}
Firstly, Change this
if ((n<1)||(n>4)) { } /* use && instead of || to scan if n if both condition are true*/
to
//scanf("%d",&n); /*remove this, use only once, in below loop */
while(1) {
scanf("%d",&n);
if ((n>=1) && (n<=4)) {
break;
}
else {
printf("Number not valid, try again: '");
}
}
And allocate memory equal to n bytes. for e.g
int *arr = malloc (n * sizeof(*arr)); /* typecasting is not required */
Also here
for (int i=0;i<220;i++) { /* some code */ }
what is the rationale behind rotating loop 220 times, doesn't it should be n times ?
As you were said in comment, your main error is that realloc is allowed to change the pointer value. If it happens, the new value is only assigned to the local copy inside the doubleArray function, but the caller still keeps the previous value which is now a dangling pointer (pointing to non allocated memory). Using it invokes Undefined Behaviour (and crashes are to be expected...)
The correct way is to return the new pointer value:
int * doubleArray(int vect[], int *dim)
{
int n = *dim *2;
*dim = n;
return realloc(vect, n*sizeof(int));
}
That is not all. best practices recommend to test allocation. In a stressed environment, the system could be unable to allocate enough memory and realloc could return NULL. Proceeding would then also involve Undefined Behaviour.
Let us go on. Controlling input is nice, but a user can type twice an error, so you should loop until you get a correct value:
int n;
for (;;) {
printf("Insert a number between 1 and 4: ");
scanf("%d",&n);
if ((n >= 1) && (n <= 4)) break;
printf("Number not valid, try again: '");
}
And please, please do not cast malloc in C language. It is useless and can hide hard to find indirection level errors.
Finally, I cannot understand why you have a loop up to 220... From your requirements it should be up to 2048.
Last point (but this one is only my opinion, not a problem): I would only display the initialized content of the array, so up to i instead of n. That way you would see the array grow while always keeping the same (initialized) values:
int *arr = malloc (n*sizeof(int));
srand(time(NULL));
int num;
for (int i=0;i<2048;i++)
{
num = rand();
if (i==n)
{
arr = doubleArray(arr, &n);
if (arr == NULL) {
perror("allocation error");
return 1;
}
stampaArray(arr, i);
printf("\n");
}
arr[i]=num;
}
stampaArray(arr,2048);
free(arr); // not required immediately before a return but good practice
New to C here and would appreciate if I could get some pointers.
I'm trying to initialise an array inside an if statement, and then print the values of the array externally - but I know the scope will be lost after the if block ends. I've tried creating the array with pointers. The reason I'm doing it inside the if statement is because the size of the array depends on a value calculated during runtime.
E.g.:
void createArray() {
int userInput;
printf("%s\n", "Please enter a value:");
scanf("%d\n", userInput);
if (userInput > 10) {
int array[userInput];
}
int i;
for (i = 0; i < userInput; i++) {
array[i] = i;
}
}
int i;
for (i = 0; i < sizeof(array)/sizeof(array[0]); i++) {
printf("%d\n", array[i]);
}
However because the array is declared inside a method, I obviously lose scope of it when it comes to the final for loop to print - thus an error occurs. I've tried creating a pointer variable int *array as a global variable, and inside the if statement, just staying array = int[10] but obviously this won't work.
This isn't my exact code, I've recreated a minimal example that shows my error so some syntax may be wrong here - apologies for that.
Any help would be appreciated.
One question you have to consider in your code is what happens if userInput is less than or equal to 10? You iterate over userInput elements of an array that was not declared.
One simple way of handling this is to make a large array at the beginning of your function and then use just the first userInput elements of it. This approach has obviously its limitations (e.g. userInput can't be larger than the size of the array, and you should make sure it won't be, otherwise bad things may happen), but is simple.
Another approach involves using dynamic memory allocation. This is done by using the malloc function:
int *array = malloc(100 * sizeof(int));
The code above allocates memory for 100 ints, basically creating an array of 100 elements. Then, you can use the array as usual. But, make sure you free it after you're done:
free(array);
Note that using this approach you'd need to declare the pointer first:
int *array;
if (userInput > 10) {
array = malloc(userInput * sizeof(int));
}
Below you can find a small proof of concept program. Note that instead of a global variable, the pointer value can be returned from the alloc function.
#include <stdio.h>
#include <stdlib.h>
int *arr;
void alloc() {
arr = malloc(10 * sizeof(int));
}
void assign() {
for (int i = 0; i < 10; i++)
arr[i] = i + i;
}
void print() {
for (int i = 0; i < 10; i++)
printf("%d\n", arr[i]);
}
int main(int argc, char *argv[])
{
alloc();
assign();
print();
free(arr);
return 0;
}
This allocates an array of int to the pointer intary. The pointer may be passed to other functions from main(). In main, userInput stores the number of int allocated.
#include <stdio.h>
#include <stdlib.h>
int *createArray( int *userInput);
int main( int argc, char *argv[])
{
int i;
int userInput = 0;
int *intary = NULL;
if ( ( intary = createArray ( &userInput)) != NULL ) {
for (i = 0; i < userInput; i++) {
intary[i] = i;
printf ( "%d\n", intary[i]);
}
free ( intary);
}
return 0;
}
int *createArray( int *userInput) {
int *array = NULL;
printf("%s\n", "Please enter a value:");
scanf("%d", userInput);
if ( *userInput > 10) {
if ( ( array = malloc ( *userInput * sizeof ( int))) == NULL) {
printf ( "could not allocate memory\n");
*userInput = 0;
return NULL;
}
}
else {
*userInput = 0;
return NULL;
}
return array;
}
You don't need some pointers, just one, (int* arr) and malloc(),a dynamic memory allocation function.
Note: You shouldn't use "array" as a variable name as it may create problems. So we'll name our variable arr.
If you're unfamiliar with it, i will explain the code too.
First add #include <stdlib.h> header file, which contains malloc().
Then declare a pointer of type int int* arr, we have named it arr in the createArray() scope.
We'll allocate the space required in the if condition with malloc() function, like :
void createArray() {
int userInput;
int* arr; // declare arr pointer
printf("%s\n", "Please enter a value:");
scanf("%d\n", userInput);
if (userInput > 10) {
arr = (int*) malloc ( userInput * sizeof(int) ); // explained below
}
int i;
for (i = 0; i < userInput; i++) {
arr[i] = i;
}
}
free(arr) // don't forget to free after using
[NOTE] This code is untested.
arr = (int*) malloc ( userInput * sizeof(int) );
This line may seem cryptic at first, but what it does is pretty simple , it allocates some memory dynamically on the heap.
The size of this memory is given by 'userInput * sizeof(int)', sizeof() function specifies the size of int on the given machine multiplied by userInput by the user,
Then, it is typecasted to int* type so that we can store the address in our int* type pointer arr.
[UPDATE] you can use arr = malloc ( userInput * sizeof(int) ); instead as suggested in comments, here is why Do I cast the result of malloc?
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)?
so I'm trying to write a function that concats a char**args to a char*args
What I have so far is":
char *concat(char **array)
{
int size = 0;
int i=0;
int j=0;
int z=0;
while (array[i]!=NULL)
{
printf(" %s \n", array[i]);
size = size + sizeof(array[i])-sizeof(char); //get the total size, minus the
//size of the null pointer
printf("%d \n",size);
i++;
}
size = size+1; //add 1 to include 1 null termination at the end
char *newCommand = (char*) malloc(size);
i=0;
while(i<sizeof(newCommand))
{
j=0;
z=0;
while (array[j][z]!='\0')
{
newCommand[i] = array[j][z];
i++;
z++;
}
j++;
}
newCommand[sizeof(newCommand)-1]='\0';
return newCommand;
}
this doesn't seem to work. Anyone know what's wrong?
I'd do it like this (untested):
int size = 0;
int count = 0;
while (array[count]) {
size += strlen(array[i]);
count++;
}
char *newCommand = malloc(size + 1);
char *p = newCommand;
newCommand[0] = 0; // Null-terminate for the case where count == 0
for (int i = 0; i < count; i++) {
strcpy(p, array[i]);
p += strlen(array[i]);
}
First, your size calculation was wrong. You wanted the size of the strings, but sizeof(array[i]) gives you the size of a single element in your array which is a pointer and thus 4 (32-bit) or 8 (64-bit). You need to use strlen instead.
Next, your manual copying was also off. It's easier to do it with a moving pointer and strcpy (which is to be avoided normally but we've calculated the sizes with strlen already so it's OK here). The use of strcpy here also takes care of null termination.
Main issue is that you keep using sizeof() with a pointer argument, whereas I think you are trying to get the size of the corresponding array.
sizeof() can only give you information that's available at compile time, such as the sizes of raw types like char and int, and the sizes of arrays with a fixed length such as a char[10]. The sizes of the strings pointed to by a char* is only computable at run time, because it depends on the exact values passed to your function.
For sizeof(newCommand) you probably need size, and for sizeof(array[i]), you probably need strlen(array[i]).