I want to make a program that stores inputed words into a 2D array (it can be as many as you want) and once you input word 'END', program should get out of the while loop. But for now user can input max. 5 words, and once he do that, program should reallocate 2d array with more rows. But there's something wrong with reallocation and I dont know what.
Here's a code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
char** allocate(int n, int m) {
char** arr = (char**)malloc(sizeof(char*) * n);
for (int i = 0; i < n; i++)
arr[i] = (char*)malloc(sizeof(char) * m);
return arr;
}
void printList(char** polje, int n, int m) {
for (int i = 0; i < n; i++) {
printf("%s\n", polje[i]);
}
}
int main() {
int n = 5;
int index = 0;
char** list = allocate(5,MAX);
char input[MAX];
while (strcmp("END", input)) {
scanf(" %s", input);
if (index % 5 == 0) {
n += 5;
list = (char**)realloc(list, sizeof(char*) * n);
for (int i = 0; i < n; i++)
list[i] = (char*)realloc(list[i], sizeof(char) * MAX);
}
if (strcmp("END", input) != 0) {
strcpy(list[index], input);
index++;
}
}
printList(list, index, MAX);
return 0;
}
The problem is that realloc is being called with an invalid pointer.
After:
n += 5;
list = (char**)realloc(list, sizeof(char*) * n);
list[n - 5], list[n - 4], list[n - 3], list[n - 2], and list[n - 1] contain invalid pointer values. So in the subsequent:
for (int i = 0; i < n; i++)
list[i] = (char*)realloc(list[i], sizeof(char) * MAX);
The realloc is being passed invalid pointers when i is in the range n - 5 to n - 1.
Related
I have a task to shift an array of real numbers to the right by n elements, what I have succesfully done, bu then I noticed that I was supposed to use only addresses and pointers.
I tried to rewrite code with addresses but it seems to not work, can someone please help me with it.
So here is the code which is working, but it uses indexes method, hope you can help me because i'm dumb and can't rewrite it properly(
#include <stdio.h>
#include <math.h>
#define N 5
void main() {
double ar[N] = {1.2, 2.2, 3.3, 4.4, 5.5};
int n;
int save;
printf_s("Enter an n:");
scanf_s("%d", &n);
int length = sizeof(ar) / sizeof(ar[0]);
while (n) {
save = ar[N - 1];
for (int i = N - 1; i > 0; i--)
ar[i] = ar[i - 1];
ar[0] = save;
n--;
}
for (int i = 0; i < length; i++) {
printf("%f; ", ar[i]);
}
}
You should find lots of references to pointer incrementing for arrays. Here is one for your reference Pointer Arithmetic.
Using that for a reference, here is a tweaked version of your program replacing array indices with a pointer that gets incremented and decremented.
#include <stdio.h>
#include <math.h>
#define N 5
int main()
{
double ar[N] = {1.2, 2.2, 3.3, 4.4, 5.5};
double * loc = ar; /* Pointer to reference elements in the array */
int n;
float save;
printf("Enter an n: ");
scanf("%d", &n);
int length = sizeof(ar) / sizeof(ar[0]);
while (n)
{
save = *(loc + N - 1); /* Store the value currently stored in the last array element */
for (int i = N - 1; i > 0; i--)
{
*(loc + i) = *(loc + i - 1);
}
*loc = save;
n--;
}
for (int i = 0; i < length; i++)
{
printf("%f; ", ar[i]);
}
printf("\n");
return 0;
}
Testing this out resulted in the following terminal output.
#Dev:~/C_Programs/Console/Shift/bin/Release$ ./Shift
Enter an n: 2
4.400000; 5.500000; 1.200000; 2.200000; 3.300000;
#Dev:~/C_Programs/Console/Shift/bin/Release$ ./Shift
Enter an n: 3
3.300000; 4.400000; 5.500000; 1.200000; 2.200000;
Give that a try and see if that meets the spirit of your project.
Swapped ar[x] with *(ar + (x)) and it worked.
#include <stdio.h>
#include <math.h>
#define N 5
void main() {
double ar[N] = { 1.2, 2.2, 3.3, 4.4, 5.5 };
int n; //кількість позицій
double save;
printf_s("Enter n");
scanf_s("%d", &n);
int length = sizeof(ar) / sizeof(ar[0]);
while (n) {
save = *(ar + N - 1);
for (int i = N - 1; i > 0; i--)
*(ar + i) = *(ar + i - 1);
*(ar + 0) = save;
n--;
}
for (int i = 0; i < length; i++) {
printf("%f; ", ar[i]);
}
}
Here is the implementation based on your code,
#include<stdio.h>
void pointer_shift(int *a, int n)
{
int temp;
temp = a[n -1]; /* store the last element in the temp variable */
for(int i =n -1; i>0; i--)
{
*(a+i) = *(a+i-1);
}
*a = temp;
}
void displayArr(int *a, int size)
{
printf("\nDisplay array element: ");
for(int i = 0; i<size; i++)
{
printf("%d ", a[i]);
}
}
int main()
{
int a1[] = {100, 101, 102};
size_t size = sizeof(a1)/sizeof(a1[0]);
displayArr (a1, size);
pointer_shift(a1, 3);
displayArr (a1, size);
return 0;
}
Output:
Display array element: 100 101 102
Display array element: 102 100 101
I have an array 0 1 2 4 5 6 7 8 9.
I want to insert 3 between 2 and 4.
Length stays the same after calling the function, even though I have added an value, why?
printf("%d,", feld[9]); gives me the right value, code works - but I get a warning.
How can I insert a value even though I initialize with int feld[9] = {0,1,2,4,5,6,7,8,9}; or int feld[] = {0,1,2,4,5,6,7,8,9}; ?
nt insertArray(int* array, int length, int value, int pos)
{
int i;
if (pos < length)
{
for (i = length; i > pos; i--)
{
array[i] = array[i - 1];
}
array[i] = value;
length++;
}
else if (pos == length)
{
array[pos] = value;
length++;
}
return length;
}
int main()
{
int feld[9] = {0,1,2,4,5,6,7,8,9};
size_t length = sizeof(feld) / sizeof(int);
insertArray(feld, length, 3, 3);
length = sizeof(feld) / sizeof(int);
for (int i = 0; i < length; i++)
{
printf("%d,", feld[i]);
}
printf("\n");
printf("%d,", feld[9]);
return 0;
}
Per C syntax, It isn´t allowed to modify the length of an static allocated array after its definition. Any attempt to do so invokes undefined behavior.
Instead, Allocate dynamic memory with malloc(), use pointer offsets to access certain pseudo-elements and use realloc() to resize the memory.
Copy the content of the elements 4 to 9 to the elements 5 to 10. Now you can store 3 in the 4th element.
One demonstrative example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 9
#define ELEM_TO_CH 4
int main(void)
{
int* feld_ptr = malloc(sizeof(int) * SIZE);
if(!feld_ptr)
{
fprintf(stderr,"Memory could not be allocated for feld_ptr!");
return 1;
}
for(int i = 0; i < SIZE; i++)
{
if (i > (ELEM_TO_CH - 2))
feld_ptr[i] = i + 1;
else
feld_ptr[i] = i;
}
printf("Before:\n\n");
for(int i = 0; i < SIZE; i++)
{
printf("feld_ptr[%d] = %d\n", i, feld_ptr[i]);
}
printf("\n\n");
feld_ptr = realloc(feld_ptr, SIZE + 1);
if(!feld_ptr)
{
fprintf(stderr,"Error at resizing memory pointed by feld_ptr!");
return 1;
}
memcpy(&feld_ptr[ELEM_TO_CH], &feld_ptr[ELEM_TO_CH-1], sizeof(int) * ((SIZE + 1) - ELEM_TO_CH));
feld_ptr[ELEM_TO_CH-1] = 3;
printf("After:\n\n");
for(int i = 0; i < (SIZE + 1); i++)
{
printf("feld_ptr[%d] = %d\n", i, feld_ptr[i]);
}
free(feld_ptr);
return 0;
}
Output:
Before:
feld_ptr[0] = 0
feld_ptr[1] = 1
feld_ptr[2] = 2
feld_ptr[3] = 4
feld_ptr[4] = 5
feld_ptr[5] = 6
feld_ptr[6] = 7
feld_ptr[7] = 8
feld_ptr[8] = 9
After:
feld_ptr[0] = 0
feld_ptr[1] = 1
feld_ptr[2] = 2
feld_ptr[3] = 3
feld_ptr[4] = 4
feld_ptr[5] = 5
feld_ptr[6] = 6
feld_ptr[7] = 7
feld_ptr[8] = 8
feld_ptr[9] = 9
You need to use the heap instead of the stack for your task.
As said in the comments below your post, in case you declare the array it will have a fixed size. Of course, you can edit it and add another value but remember you are allocating some additional space in the memory that does not correspond to your array, thus destroying some of the other variables in the stack (maybe) which is not safe.
You can use malloc() to reserve a required amount of memory in heap then realloc() function to change the initial size.
Remember to free() the memory at the end of your program.
As the comments above, you can not extend the size of array. In this case, i propose two solutions:
Using the pointer in the insert function. In this case you have to allocate for this pointer with size = length of old array + 1. The insert function becomes as:
int * insertArray(int* arr, int length, int value, int pos)
{
int * array = malloc(sizeof(int) * (length + 1));
if(!array) {
return NULL;
}
for(int i = 0; i < length; i++) {
array[i] = arr[i];
}
int i;
if (pos < length)
{
for (i = length; i > pos; i--)
{
array[i] = array[i - 1];
}
array[i] = value;
length++;
}
else if (pos == length)
{
array[pos] = value;
length++;
}
return array;
}
Then in main function:
int main()
{
int feld[9] = {0,1,2,4,5,6,7,8,9};
size_t length = sizeof(feld) / sizeof(int);
int * array = insertArray(feld, length, 3, 3);
for (int i = 0; i <= length; i++)
{
printf("%d,", array[i]);
}
free(array);
return 0;
}
Using pointer in main function instead of array, then reallocate pointer in the insert function.
void insertArray(int* array, int length, int value, int pos)
{
array = realloc(array, sizeof(int) * (length + 1));
if (!array)
return;
...
}
In the main function:
int main()
{
int *feld = malloc(sizeof(int) * 9);
if(!feld)
return -1;
for(int i = 0; i < 9; i++) {
if(i<3)
feld[i] = i;
else
feld[i] = i+1;
}
insertArray(feld, 9, 3, 3);
for (int i = 0; i <= 9; i++)
{
printf("%d,", feld[i]);
}
free(feld);
return 0;
}
Can someone tell me why do I get this segmentation fault?
Is it because I have set a pointer to NULL and passed it to a function?
Should I use arrays or pointers when I want to send an array to function?
#include <stdlib.h>
#include <stdio.h>
int* ComputeFibo(int _size);
void PrintFibo(int* _arr, int _size);
int main (int argc, char* argv[])
{
int* arr = NULL;
int n = 0;
printf("Please enter Fibonacci size:");
scanf("%d", &n);
arr = ComputeFibo(n);
PrintFibo(arr, n);
return 0;
}
int* ComputeFibo(int _size)
{
int sum = 0;
int indx = 0;
int* arr = NULL;
arr[indx] = 1;
for (indx = 1; indx < _size; ++indx)
{
arr[indx] = arr[indx - 1] + sum;
sum = arr[indx - 1];
}
return arr;
}
void PrintFibo(int* _arr, int _size)
{
int indx = 0;
for (; indx < _size; ++indx)
{
printf("%d\t", _arr[indx]);
}
}
I would love to get an answer with a good explanation for that.
The problematic statement is:
int* arr = NULL;
where arr is pointing at NULL and then you assign values to arr as if it's pointing to valid memory location.
You could fix it with:
int* arr = malloc(_size * sizeof *arr);
if (arr == NULL) { /* error *}
and then call free() on the returned pointer later.
arr = ComputeFibo(n);
PrintFibo(arr, n);
free(arr);
Also be aware that int can only represent limited values in C. So, for example, if you try to calculate upto 100 Fibonacci numbers, you are likely to run into integer overflow.
You tried to access index of a null pointer.
int* ComputeFibo(int _size)
{
int* arr = NULL;
arr[indx] = 1; //SIGF
...
}
I fixed your code if you want a reference.
#include <stdlib.h>
#include <stdio.h>
void compute_fibo(int *_arr, int _size);
void print_fibo(int *_arr, int _size);
int main(int argc, char *argv[]) {
int n = 0;
printf("Please enter Fibonacci size:");
scanf("%d", &n);
int *arr = (int *) malloc(sizeof(int) * n);
if (arr == NULL) return 1;
compute_fibo(arr, n);
print_fibo(arr, n);
free(arr);
return 0;
}
void compute_fibo(int *_arr, int _size) {
_arr[0] = 1;
_arr[1] = 1;
for (int index = 2; index < _size; index++) {
_arr[index] = _arr[index - 1] + _arr[index - 2];
}
}
void print_fibo(int *_arr, int _size) {
for (int index = 0; index < _size; ++index) {
printf("%d\t", _arr[index]);
}
}
output:
Please enter Fibonacci size:10
1 1 2 3 5 8 13 21 34 55
I am having trouble with assigning a return value of a function in heap part of the program. When I tried it in main, it gives an error "Segmentation fault". I believe it is because of the size of my array, which is the return value that I mentioned earlier because when I make my max_size smaller, the code works correctly (I think up to 45000). When I call the function in main, it uses the memory of stack, which is much smaller than memory of heap. Therefore I tried to call the function in heap and make the assignment in there but the compiler gave an error
deneme.c:6:15: error: initializer element is not constant
int *primes = listPrimes(1000000, &size);
After that I did some research and found out that stack is 8 MB memory, which is around 8000000 bytes. Then I estimated my array size as using the prime number theorem (up to 1000000, there are approximately 200000 primes) and sizeof(int) = 4 bit value so it gives 100000 bytes, which is much less than 8 MB. Therefore I have two questions in mind:
1. Why the compiler gives segmentation fault error although my array size is not too large?
2. How can I make the assigment in heap instead of main in order to avoid this problem?
Here is my code:
#include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int *listPrimes(int max_size, int *size) {
*size = 1;
int *result = malloc(*size * sizeof(int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc(max_size*sizeof(int));
for (i = 0; i < max_size; i++) {
nums[i] = i;
}
result[0] = 2;
int j = 2;
while (j < max_size) {
int k = j;
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
if (j == 2) {
j++;
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
else {
j += 2;
if (nums[j] != 0) {
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
}
}
return result;
}
and main function:
#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"
int size = 0;
int *primes = listPrimes(1000000, &size);
int main() {
printf("size = %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %d\n", i+1, primes[i]);
}
free(primes);
return 0;
}
Use unsigned int for j, k and max_size in listPrimes and it works properly . Below is the tested code:
// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int size = 0;
int *
listPrimes (unsigned int max_size, int *size)
{
*size = 1;
int *result = malloc (*size * sizeof (int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc (max_size * sizeof (int));
for (i = 0; i < max_size; i++)
{
nums[i] = i;
}
result[0] = 2;
unsigned int j = 2;
while (j < max_size)
{
unsigned int k = j;
while (j * k <max_size)
{
nums[j * k] = 0;
k++;
}
if (j == 2)
{
j++;
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
else
{
j += 2;
if (nums[j] != 0)
{
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
}
}
free(nums);
return result;
}
int
main ()
{
int *primes = listPrimes (1000000, &size);
printf ("size = %d\n", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %d\n", i + 1, primes[i]);
}
free (primes);
return 0;
}
nums is allocated to have max_size elements, so the index of its last element is max-size-1.
This loop:
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
may access an element with index j*k that equals max_size, thus writing beyond the end of the array. The loop should be limited to j*k < max_size.
Regarding your second question, the size of the result array is determined while finding the primes and is not readily calculable in advance, so it cannot easily be allocated prior to calling listPrimes. It could be done by evaluating the prime-counting function, but that is likely more than you want to do for this project.
I want to create random data for testing. I want to fill an array with 100 strings of random length with the letter 'A'.
example:
array[0] = "AAAAA"
array[1] = "AAAAAAAA"
array[2] = "A"
...
char **create_string()
{
char **array = malloc(sizeof(**array));
srand((unsigned int)time(NULL));
int random = 0;
int i, j;
for(int i=0; i<100; i++)
{
random = rand() % 100;
for(j=0; j < random; j++)
{
array[i] = // some sort of string append that would be cheap.
}
}
}
I was looking at this C string append and they use strcat. Is there a better way to solve my problem? Since I will be running in a loop to create those random size strings.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char **create_string(size_t n) {
char **array = malloc(sizeof(char*) * n);
int i, j;
for(i=0; i<100; i++)
{
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
for(j=0; j < sz; j++) {
array[i][j] = 'A';
}
array[i][sz] = 0;
}
return array;
}
int main() {
char **array;
size_t i;
srand((unsigned int)time(NULL));
array = create_string(100);
for (i = 0; i < 100; i++)
printf("%s\n", array[i]);
return 0;
}
Alternatively, you can create a template string and copy required number of characters into each random string:
char **create_string(size_t n) {
char template[101];
char **array = malloc(sizeof(char*) * n);
int i;
for (i = 0; i < 100; i++)
template[i] = 'A';
template[100] = 0;
for(i = 0; i < n; i++) {
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
strncpy(array[i], template, sz);
array[i][sz] = 0;
}
return array;
}
This will depend on the distribution of string lengths that you want. This is a uniform distribution of string lengths, from 0 to 200.
int n = rand() % 200 * sizeof(*array);
array[i] = malloc(n + 1);
memset(array[i], 'A', n);
array[i][n] = '\0';
But you could have a Gaussian distribution, a Poisson distribution, etc.
char **create_string()
{
char **array = malloc(sizeof(char *) * 100);
srand((unisgned int)time(NULL));
int i;
for (i = 0; i <100;i++)
{
int random = rand() % 100;
array[i] = malloc(random);
memset(array[i],'A',random-1);
array[random-1] = '\0';
}
return array;
}
Problem for you to fix: what happens if random is 0? Also the random numbers will not be equaly distributed. Only modulo by a power of 2 will achieve that.
Here's an approach that doesn't put an upper bound on any individual string, but does put an exact bound on the total length of all strings. It also only calls malloc twice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TOT_SIZE (5000) /* adjust to taste */
#define TOT_STRS (100)
char **create_strings()
{
char **array = (char**) malloc(TOT_STRS * sizeof(char *));
char *str = (char*) malloc(TOT_SIZE);
int zeros = 1;
int i;
memset(str, 'A', TOT_SIZE - 1);
str[TOT_SIZE - 1] = 0;
while (zeros < TOT_STRS)
{
int pos = rand() % TOT_SIZE;
if (str[pos] != 0)
{
str[pos] = 0;
zeros++;
}
}
array[0] = str;
for (i = 1; i < TOT_STRS; i++)
{
array[i] = array[i - 1] + strlen(array[i - 1]) + 1;
}
return array;
}
And a short test program:
int main()
{
char **a = create_strings();
int i;
for (i = 0; i < TOT_STRS; i++)
{
printf("%3d: %s\n", i, a[i]);
}
return 0;
}
This code assumes that all the random strings need to be non-overlapping. If they can overlap in memory, you only need one string, and an array of pointer to different starting points in that one string.
You do not have to allocate the real 100 strings. Firstly you just declare a long enough array char long_array[100]. and then you use random = rand() % 100; get the random. Secondly you just pass the long_array and the random to your function. Then your problem is solved.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char **create_string(const size_t array_size,
const size_t string_size,
const unsigned char chr)
{
srand((unsigned)time(NULL));
char ** array = malloc(array_size * sizeof (char *));
size_t t;
for (t = 0; t < array_size; ++t) {
array[t] = malloc(string_size * sizeof(char));
array[t][string_size] = '\0';
memset(array[t], chr, (rand() % string_size) + 1);
}
return array;
}
main() {
char ** randstring = create_string(10, 7, 'A');
int t = 0;
for (; t < 10; ++t)
printf("%s\n", randstring[t]);
return 0;
}
Possible output
AAAAAA
AAAAA
AAAAAA
AAA
AAAAA
AAAAAA
AAAAAA
AAAAAAA
AAAA
AAAA