add values in a 2 dimensional array using dynamic memory allocation - c

Given this task:
Write a program that allocates the necessary amount of memory for storing the elements from two [m x n] integer matrices.
I don't know how to allocate memory to 2 Dimensional arrays.
I read some examples but I don't get it.
#define _CRT_SECURE_NO_WARNINGS
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#define DIM 10
void main()
{
int **m, *n;
int i = 0, j = 0;
int diml, dimc;;
puts("Introduceti dimensiunea matricelor(linii|coloane)");
scanf("%d%d", &diml, &dimc);
m = (int**)malloc(dimc*sizeof(int));
puts("Introduceti elementele primei matrici:");
for (j = 0;j < dimc;j++)
{
m[i] = (int *)malloc(diml*(sizeof(int)));
}
for (j = 0;j < dimc;j++)
{
for (i = 0;i < diml;i++)
{
printf("tab[%d][%d]= ", j + 1, i + 1);
scanf("%*d", m[j][i]);
}
}
_getch();
}
My program crash after I enter the first line.
Introduceti dimensiunea matricelor(linhi I coloane)
3
3
Introduceti elementele primei matrici:
ab[1][1]= 2
ab[1][2]= 1
ab[1][3]= 2
ab[2][1]=
Problema 3.exe has stopped working
A problem caused the program to stop working correctly.
Windows will closethe program and notify you if a solution is
available.

Avoid the mistake of allocating using the wrong size by allocating based on the size of the object and not the size of type. If the sizeof(int) was less then sizeof(int *), this would explain OP's problem.
// m = (int**)malloc(dimc*sizeof(int)); // Original
// m = (int**)malloc(dimc*sizeof(int *)); // corrected type
// m = malloc(dimc*sizeof(int *)); // cast not needed
m = malloc(sizeof *m * dimc); // best : sizeof object
Use correct index j vs. i #BLUEPIXY. This is certainly an issue for OP.
for (j = 0;j < dimc;j++) {
// m[i] = (int *)malloc(diml*(sizeof(int)));
m[j] = malloc(sizeof *(m[j]) * diml);
Insure compiler warnings are fully enabled - it should have caught this one.
// scanf("%*d", m[j][i]);
scanf("%d", &m[j][i]);
Suggest checking the results of malloc() and scanf().
#include <stdlib.h>
m[j] = malloc(sizeof *(m[j]) * diml);
if (m[j] == NULL && diml != 0)) {
fprintf(stderr", "Out of memory\n");
return EXIT_FAILURE;
}
if (scanf("%d", &m[j][i]) != 1) {
fprintf(stderr", "Non-numeric input\n");
return EXIT_FAILURE;
}
main() should return int.
#include <stdlib.h>
int main(void) {
...
return EXIT_SUCCESS;
}
When promoting, insure output gets printed and is not buffered. Use fflush() or end the prompt with '\n'.
printf("tab[%d][%d]= ", j + 1, i + 1);
fflush(stdout); // add
scanf(...

You should allocate like this at first:
m = (int**)malloc(dimc*sizeof(int*));
After that you allocate like that:
m[i] = (int *)malloc(sizeof(int));

Related

Expanding the size of an array of strings in c

I am trying to get strings from the user and then expand the size of the strings if they enter a long string and also expand the size of the array holding the strings if they enter more strings than expected.Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char* argv[])
{
int number_of_strings = 5;
int string_size = 5;
int count = 0;
char **array = (char**)calloc(number_of_strings, sizeof(char*));
for (int i = 0; i < number_of_strings; i++)
{
array[i] = (char*)calloc(string_size + 1, sizeof(char));
}
////////////////////////////MAIN PART///////////////////////////////////////////////
int arr_size = number_of_strings;
int str_count = 0; //Total number of input strings counter
for (int j = 0; j < arr_size; j++)
{
if (arr_size >= str_count) //Check if the number of input strings is more than expected
{
array = (char**)realloc(array, (arr_size + 1) * sizeof(char*)); //allocate memory for 1 more string
arr_size++; //Increase the loop rounds
}
int str_size = string_size;
int char_count = 0; //Total number of input characters counter
for (int h = 0; h < str_size; h++)
{
if (str_size >= char_count) //Check if the input string size is more than expected
{
array[j] = (char*)realloc(array[j], (str_size + 1) * sizeof(char)); //allocate memory for 1 more char
str_size++; //Increase the loop rounds
}
scanf(" %c", &array[j][h]); //get a single char
char_count++; //Increment the total input character count
}
str_count++; //Increment the total input string count
}
////////////////////////////////////////////////////////////////////////////////////
for (int k = 0; k < number_of_strings; k++)
{
printf("%s", array[k]);
free(array[k]);
}
free(array);
return 0;
}
Input:Thisisnot whatitlooks likebut Idon't knowwhy isthis happening
Output: Empty Stdout . Time limit exceeded
Expected Output: ThisisnotwhatitlookslikebutIdon'tknowwhyisthishappening
The program waits for user input for a long time and it doesn't stop scanning for inputs, even if the user doesn't enter any input and so eventually the program crashes.
I think the error is caused due to improper reallocation of the array. Any idea about why is this error caused and how can it be fixed is greatly appreciated. Thanks!
It is unclear what you are trying to do. Here are some problems in the code:
you purposely ignore whitespace from the input, so how can you detect string boundaries?
all of the input is clumped into a single string the inner loop never stops.
you do not check for EOF either: if the end of the input stream is encountered, the loop continues, reallocating memory until a system crash or an allocation failure...
allocation failure is not tested either, so undefined behavior in all cases.
there is no need to cast the return value of malloc and calloc in C. It is necessary in C++, but you would definitely want to use a different approach in C++. To avoid type discrepancies, you can use the type of the destination pointer instead of hard coding it: to reallocate the array, replace array = (char**)realloc(array, (arr_size + 1) * sizeof(char*)); with
array = realloc(array, sizeof(*array) * (arr_size + 1));

Problems using malloc() to delete array within for loop

I have an array of data, arr, and an array of indexes, index. My goal is to use a for loop to create new arrays of data partitioned at each of the indexes and to further find the minimum in each partitioned array. I am using malloc to create a dynamic array which I then free at the end of each loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int j;
int arr[] = {1,3,4,6,7,8,12,87,89,12,34,43,54,67,81,2,0,10,23,45,81,23,89,23,56,81,28,79};
int index[] = {1,5,9,13,19,24};
int h = 27;
int k;
int c;
for(j = 0;j < h - 1;++j)
{
int *temp_arr = malloc(10*sizeof(int));
for(k = index[j];k<(index[j+1]);++k )
{
temp_arr[k] = arr[k];
}
int local_min ;
local_min = temp_arr[0];
for ( c = 1 ; c < sizeof(temp_arr) / sizeof(temp_arr[0]) ; c++ )
{ printf("Temp array %d ", temp_arr[c]);
if ( temp_arr[c] < local_min)
{
local_min = temp_arr[c];
printf("Local min in loop %d ", local_min );
}
}
free(temp_arr);
printf("\n");
}
return 0;
}
Unfortunately, the program is crashing without giving me any error messages. I think that I may have done something fundamentally wrong using malloc. Any suggestions on how to correctly do this would be greatly appreciated.
for(j = 0;j < h - 1;++j) // Where h = 27
It means j can be max 25
for(k = index[j];k<(index[j+1]);++k ) // If j = 25
You are touching index[26], while index has 6 elements.
for ( c = 1 ; c < sizeof(temp_arr) / sizeof(temp_arr[0]) ; c++ ) // Where int *temp_arr
temp_arr is pointer and sizeof(pointer) is always 8 on 64bit or 4 on 32bit system.
for(k = index[j];k<(index[j+1]);++k )
{
temp_arr[k] = arr[k]; // Where int index[] = {1,5,9,13,19,24};
}
If k is 13 or 19 or 24 you are ouside of bounds.
You should take a look at valgrind, and debug your code, step by step, expression by expression.
It appears that you forgot to inspect the output from Valgrind, which shows exactly where you use uninitialized values and where you run off the end of temp_arr.
Note also that temp_arr is a pointer type, and sizeof temp_arr is the size of that pointer, not the size of the array it points to.

What's wrong with my C code(My output is volatile because of malloc)?

I SOMETIMES get errors when executing this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int digits(int n){
int count = 0;
while(n!=0)
{
n/=10; /* n=n/10 */
++count;
}
return count;
}
int fib(int n){
int r;
if(n == 1 || n == 0)
return 0;
else if(n == 2)
return 1;
r = fib(n-1) + fib(n-2);
return r;
}
void function(void){
char* test; //number you want to scan
int* table;
int length, length2, test2 = 0, number, l, random = 0, j = 1, buffer;
test = malloc(sizeof(test));
table = malloc(sizeof(table));
scanf("%s", test);
number = atoi(test);
length = strlen(test); //length of input test number
while(test2 < length + 1){
printf("fib(%d) = %d\n", j, fib(j));
buffer = table[j - 1] = fib(j);
test2 = digits(buffer);
j++;
}
//input size of "table" into "length2"
length2 = j - 1;
for(l = 0; l < length2; l++){
if(table[l] == number){
printf("YES\n");
random = 1;
break;
}
}
if(random == 0)
printf("NO\n");
free(table);
free(test);
}
int main(void){
int num, i;
scanf("%d", &num);
for(i=0; i < num; i++){
function();
}
return 0;
}
And this is the output:
3
2
fib(1) = 0
fib(2) = 1
fib(3) = 1
fib(4) = 2
fib(5) = 3
fib(6) = 5
fib(7) = 8
fib(8) = 13
YES
*** Error in `./Am_I_a_Fibonacci_Number': free(): invalid next size (fast): 0x08384018 ***
Aborted (core dumped)
First number is to count how much input the user wants, (in this case 3) and the 2nd(in this case, 2nd, 3rd and 4th) number is the number you want to test whether its a Fibonacci number or not.
Sorry if this is very hard-to-read code, I have a lot to learn.
You are not allocating enough memory, thus you corrupt the heap. sizeof() applied on a pointer (as in your program) usually results in 4 or 8, depending on the architecture. Obviously, this might just be enough for test, but is definitely too little for table.
You need to figure out how much memory you really need, and use this as argument in malloc.
test = malloc(sizeof(test));
table = malloc(sizeof(table));
"test" is a variable of type char*. Such a variable has typically a size of 4 or 8 bytes. So you allocate memory for 4 or 8 bytes, which is enough for 4 or 8 chars.
"table" is a variable of type int*. Again, typically 4 or 8 bytes. Allocating 4 or 8 bytes is usually enough for 1 or two int's. If you try to store more, things will go badly wrong.
Figure out how many chars and ints you want to allocate, then call for example table = malloc (required_elements * sizeof (int)).

How to read in 2d array from function in main

Alright so I'm sure this is pretty simple and all but I have no idea how to use functions. Up until now I was able to get by with everything in main but now I'm required to use functions for just about anything I do. So from my code below, how do I read in (or w.e. the proper terminology is) a function from main?
EDIT: To clarify to everyone, my question is how can I access the array I returned in main?
Code below takes in the test scores from different amount of students specified by user input.
#include <stdio.h>
#include <stdlib.h>
int** getTestData();
int main (){
///this is where I'm lost..
int (*a)[];
a = getTestData();
}
int** getTestData(){
int students, numberOfTests, testScores, i, j;
int** testScoreBank;
// reads in studens
scanf("%i", &students);
testScoreBank = (int**) malloc (sizeof(int)*students);
for(i=0; i<students;i++){
//how many number of tests there are
scanf("%i", &numberOfTests);
testScoreBank = (int*) malloc (sizeof(int)*numberOfTests);
for(j=0; j<numberOfTests; j++){
//the tests themselves
scanf("%i", &testScores);
testScoreBank[i][j] = testScores;
}
}
return testScoreBank;
}
Ok, here is an example with global variables, how to fill your array inside a function, and access it in main()
#include <stdio.h>
#include <stdlib.h>
int** getTestData();
int numberOfStudents;
int* studentTestSizes;
int main (){
int** testScoresBank = getTestData();
int i, j;
for (i = 0; i < numberOfStudents; i++) {
for (j = 0; j < studentTestSizes[i]; j++) {
printf("%d", testScoresBank[i][j]);
}
}
return 0;
}
int** getTestData() {
int** testScoreBank;
// reads in studens
scanf("%d", &numberOfStudents);
testScoreBank = malloc(sizeof(int*) * numberOfStudents);
studentTestSizes = malloc(sizeof(int) * numberOfStudents);
int i;
for (i = 0; i < numberOfStudents; i++) {
//how many number of tests there are
scanf("%d", studentTestSizes + i);
testScoreBank[i] = malloc(sizeof(int) * studentTestSizes[i]);
int j;
for (j = 0; j < studentTestSizes[i]; j++) {
//the tests themselves
int testScore;
scanf("%d", &testScore);
testScoreBank[i][j] = testScore;
}
}
return testScoreBank;
}
alternative for global variables is to make global variables local and pass pointers to them to getTestData function, example is here:
#include <stdio.h>
#include <stdlib.h>
int** getTestData();
int main (){
int numberOfStudents; // those variables are now here
int* studentTestSizes;
int** testScoresBank = getTestData(&numberOfStudents, &studentTestSizes); // passing the pointers so we can change values that are pointed to
int i, j;
for (i = 0; i < numberOfStudents; i++) {
for (j = 0; j < studentTestSizes[i]; j++) {
printf("%d", testScoresBank[i][j]);
}
}
return 0;
}
int** getTestData(int* numberOfStudentsPtr, int** studentTestSizesPtr) {
int** testScoreBank;
// reads in studens
scanf("%d", numberOfStudentsPtr); // it's already a pointer so we must omit &
int numberOfStudents = *numberOfStudentsPtr; // will be constant from now on
testScoreBank = malloc(sizeof(int*) * numberOfStudents);
*studentTestSizesPtr = malloc(sizeof(int) * numberOfStudents);
int* studentTestSizes = *studentTestSizesPtr;
int i;
for (i = 0; i < numberOfStudents; i++) {
//how many number of tests there are
scanf("%d", studentTestSizes + i);
testScoreBank[i] = malloc(sizeof(int) * studentTestSizes[i]);
int j;
for (j = 0; j < studentTestSizes[i]; j++) {
//the tests themselves
int testScore;
scanf("%d", &testScore);
testScoreBank[i][j] = testScore;
}
}
return testScoreBank;
}
In addition to the other answers, you have a number of subtle issues to consider. Two are just general helpful tips for writing/debugging your beginning applications (1) if you are taking user input, prompt for it - you can strip the prompts later, but it is much easier to enter data in response to an informative prompt than it is to wonder what the blinking cursor is doing down there -- did to program freeze?; (2) provide adequate spacing in your code - you can always delete blank lines later, but separating your code into functional blocks of logic will help you keep your logic straight.
When allocating space for numeric arrays, it is good practice to initialize all values to 0 as part of (or after) allocation. This will absolutely prevent the inadvertent read from uninitialized space. You can allocate and initialize all at once by using calloc instead of malloc. This also provides benefits when allocating arrays of pointers to char* as well.
While you may have fixed your allocation, you still have the glaring problem of knowing "How many students and tests do I have?". Here is where passing an additional pointer for the number of students and storing the number of tests in an additional array index is required. (there are other ways to do it, this is just efficient). You can declare the the number of students in main passing its pointer to getTestData. Updates to the value of students in getTestData are then available in main. But, "What if the students have a different number of scores? What then?" You are already filling an array of integers, if you just store the number of tests for the student as the first integer, you make that value available no matter where you pass the array.
Finally, you need to pay closer attention to your choice of variable types. For indexes and lengths that can never be negative, unsigned or size_t is a better choice and will allow the compiler to point out instances where you may be using that value incorrectly.
You need to validate each time you allocate memory with malloc or calloc, and you are responsible to keeping track of the address to the start of each allocation and freeing it when it is no longer needed.
That said, here is one approach to making it all work. Try it. Let me know if you have any questions:
#include <stdio.h>
#include <stdlib.h>
int **getTestData (size_t *students);
int main (void) {
int **a = NULL;
int j;
size_t i, s = 0;
if (!(a = getTestData (&s))) {
fprintf (stderr, "error: getTestData failed to return student data.\n");
return 1;
}
/* print student data */
putchar ('\n');
for (i = 0; i < s; i++)
{
printf (" Student[%2zu] scores : ", i+1);
/* adjust indexes to read no. of tests */
for (j = 1; j < a[i][0]; j++)
printf (" %3d", a[i][j]);
putchar ('\n');
}
putchar ('\n');
/* free allocated memory */
for (i = 0; i < s; i++)
free (a[i]);
free (a);
return 0;
}
int **getTestData (size_t *students)
{
size_t tests, testScores, s, t;
int **testScoreBank;
/* reads in students */
printf ("\n No. of students: ");
scanf ("%zu", students);
if (!(testScoreBank = calloc (*students, sizeof *testScoreBank))) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
return NULL;
}
for (s = 0; s < *students; s++)
{
/* how many number of tests there are */
printf ("\n No. of scores for student[%2zu]: ", s+1);
scanf ("%zu", &tests);
tests += 1; /* allow space for number of tests as [s][0] */
testScoreBank[s] = calloc (tests, sizeof **testScoreBank);
testScoreBank[s][0] = tests;
for (t = 1; t < tests; t++)
{
/* the tests themselves */
printf (" student[%2zu]-test[%2zu] score: ", s+1, t);
scanf ("%zu", &testScores);
testScoreBank[s][t] = testScores;
}
}
return testScoreBank;
}
Use/Output
$ ./bin/testdata
No. of students: 2
No. of scores for student[ 1]: 3
student[ 1]-test[ 1] score: 88
student[ 1]-test[ 2] score: 91
student[ 1]-test[ 3] score: 82
No. of scores for student[ 2]: 4
student[ 2]-test[ 1] score: 93
student[ 2]-test[ 2] score: 95
student[ 2]-test[ 3] score: 96
student[ 2]-test[ 4] score: 91
Student[ 1] scores : 88 91 82
Student[ 2] scores : 93 95 96 91
(I assume this is just a snippet of your overall code and there's more to it or else you might have other problems)
Anyway you should be able to set up your 2D array with the following modifications:
scanf("%i", &students);
testScoreBank = malloc (sizeof(int*)*students); //sizeof int* instead of sizeof int.
for(i=0; i<students;i++)
{
scanf("%i", &numberOfTests);
*(testScoreBank + i)= malloc (sizeof(int)*numberOfTests); //You forgot the * operator on testScoreBank and to iterate through it.
for(j=0; j<numberOfTests; j++)
{
scanf("%i", &testScores);
testScoreBank[i][j] = testScores;
}
}

can't figure out why I am getting a segmentation fault initializing my array

I have the following code which works fine for N=10 and C=25 but bombs with a segmentation fault if I use N=50 and C=25500
#include <stdio.h>
#include <stdlib.h>
// create table
int *table;
table = (int *) malloc(sizeof(int) * C+1 * N+1);
if(table == NULL){
printf("[ERROR] : Fail to allocate memory.\n");
}
// initialize table
for(i =0; i < N-1; i++){
for(j = 0; j < C-1; j++){
//table[i*(C+1)+j]=0;
*(table + (i*(C+1)+j))=1;
}
}
printf("table made\n");
I believe the amount of memory you are allocating is incorrect. You are allocating C*sizeof(int) + N + 1 and you want to be allocating (C+1)*(N+1)*sizeof(int)
You're just missing some parens -- http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
Assuming int = 4 so you allocate
4*50 + 1*25500 + 1 = 25701 bytes
In your loop you access (at the end):
i = 49
j = 25499
49*(25501)+25499 = 1275048(index)*4 = 5100192 (offset)
So what you need is:
table = malloc(sizeof(int) * (C+1) * (N+1));
Your loop didn't work for smaller values either, it just didn't crash. Writing outside allocated memory is undefined behaviour.
And as a sidenote, not related to your crash:
Do I cast the result of malloc?

Resources