Dynamically allocating a 2D array in C - c

I've been reading around and I've been applying what I've been reading to my code but I am not sure if I am missing something.. the 2d array is suppose to mirror sudoku.
I know the problem area is in my arrayMake function.
My professor recommended using a cast with the malloc call so:
sudoku = (int**)malloc(sudokus*sizeof(int*)); but that did not work for me.
int main(){
int sudokus;
int** sudoku;
sudokus = getUserInfo();
sudoku = arrayMake(sudokus);
/*for (int i = 0; i < (SIZE*sudokus), i++;){
for (int j = 0; j < SIZE, j++;){
printf("Numbers[%d][%d]:%d", i, j, sudoku[i][j]);
}
}*/
system("pause");
return 0;
}
int getUserInfo(){
int sudokus;
printf("How many Sudokus are you checking today?\n");
scanf("%d{^\n]\n", &sudokus);
return sudokus;
}
int** arrayMake(int sudokus){
int **sudoku;
int realsize;
realsize = 9 * sudokus;
sudoku = malloc(realsize*sizeof(int*));
if (sudoku == NULL){
printf("Memory allocation failed");
return 0;
}
for (int i = 0; i < realsize, i++;){
sudoku[i] = malloc(9 * sizeof(int));
if (sudoku[i] == NULL){
printf("Memory allocaiton failed");
return 0;
}
}
return sudoku;
}

My professor recommended using a cast with the malloc call so: sudoku = (int**)malloc(sudokus * sizeof(int*)); but that did not work for me.
To dynamically allocate for 2D array, you usually need to do two steps. Your code is not clear as you include a realsize = 9 * sudokus which doesn't make sense. Anyway, for simplicity, lets assume your sudoku is a 3x3 matrix. You'll need to:
Allocate for the pointer to pointer to int:
int **sudoku = malloc( 3 * sizeof( int * ) );
Allocate for each of the individual pointer to int:
for( int i = 0; i < 3; i++ )
sudoku[i] = malloc( 3 * sizeof( int ) );

From what I see your problem exists in your for loops where you have:
for (i = 0;i < realsize , i++)
when you really meant:
for (i = 0;i < realsize ; i++)
^
Note the change of , to ;

scanf("%d{^\n]\n", &sudokus); is a mistake.
I guess you meant the { to actually be a [ but the format string is still wrong even after that change. I think you intended to consume the rest of the input, up to and including a newline character. However, your format string does not actually do that.
Scanf'ing for \n actually means consume any amount of whitespace, so in fact this code (with the [ fix) would continue waiting for input until there was a newline, and also another non-whitespace character typed after the newline.
Better would be:
scanf("%d", &sudokus);
int ch;
while ( (ch = getchar()) != '\n' && ch != EOF ) { }
There are a few different ways to achieve the same goal. (Note that scanning for %d[^\n]%c is not one of them; that string is also broken).
Also I would suggest a different variable name than sudokus. It's confusing having two similarly-named variables sudoku and sudokus. Name it something that reflects its meaning.
For allocating your array, it would be much simpler to take out the arrayMake function and write something like:
int sudoku[9][9];
(I couldn't figure out what sudokus was supposed to mean or what realsize was going to be, but you could put your intended dimension inside the square brackets there).

Related

Import a matrix of any size in C [duplicate]

How am I supposed to use dynamic memory allocations for arrays?
For example here is the following array in which i read individual words from a .txt file and save them word by word in the array:
Code:
char words[1000][15];
Here 1000 defines the number of words the array can save and each word may comprise of not more than 15 characters.
Now I want that that program should dynamically allocate the memory for the number of words it counts. For example, a .txt file may contain words greater that 1000. Now I want that the program should count the number of words and allocate the memory accordingly.
Since we cannot use a variable in place of [1000], I am completely blank at how to implement my logic. Please help me in this regard.
You use pointers.
Specifically, you use a pointer to an address, and using a standard c library function calls, you ask the operating system to expand the heap to allow you to store what you need to.
Now, it might refuse, which you will need to handle.
The next question becomes - how do you ask for a 2D array? Well, you ask for an array of pointers, and then expand each pointer.
As an example, consider this:
int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));
if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}
for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}
if ( i != num_words )
{
/* it didn't allocate */
}
This gets you a two-dimensional array, where each element words[i] can have a different size, determinable at run time, just as the number of words is.
You will need to free() all of the resultant memory by looping over the array when you're done with it:
for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}
free(words);
If you don't, you'll create a memory leak.
You could also use calloc. The difference is in calling convention and effect - calloc initialises all the memory to 0 whereas malloc does not.
If you need to resize at runtime, use realloc.
Malloc
Calloc
Realloc
Free
Also, important, watch out for the word_size+1 that I have used. Strings in C are zero-terminated and this takes an extra character which you need to account for. To ensure I remember this, I usually set the size of the variable word_size to whatever the size of the word should be (the length of the string as I expect) and explicitly leave the +1 in the malloc for the zero. Then I know that the allocated buffer can take a string of word_size characters. Not doing this is also fine - I just do it because I like to explicitly account for the zero in an obvious way.
There is also a downside to this approach - I've explicitly seen this as a shipped bug recently. Notice I wrote (word_size+1)*sizeof(type) - imagine however that I had written word_size*sizeof(type)+1. For sizeof(type)=1 these are the same thing but Windows uses wchar_t very frequently - and in this case you'll reserve one byte for your last zero rather than two - and they are zero-terminated elements of type type, not single zero bytes. This means you'll overrun on read and write.
Addendum: do it whichever way you like, just watch out for those zero terminators if you're going to pass the buffer to something that relies on them.
While Ninefingers provided an answer using an array of pointers , you can also use an array of arrays as long as the inner array's size is a constant expression. The code for this is simpler.
char (*words)[15]; // 'words' is pointer to char[15]
words = malloc (num_words * sizeof(char[15]);
// to access character i of word w
words[w][i];
free(words);
If you're working in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 15
int resizeArray(char (**wordList)[WORD_LEN], size_t *currentSize, size_t extent)
{
int result = 1;
char (*tmp)[WORD_LEN] = realloc(*wordList,
(*currentSize + extent) * sizeof **wordList);
if (tmp)
{
*currentSize += extent;
*wordList = tmp;
}
else
result = 0;
return result;
}
int main(void)
{
char *data[] = {"This", "is", "a", "test",
"of", "the", "Emergency",
"Broadcast", "System", NULL};
size_t i = 0, j;
char (*words)[WORD_LEN] = NULL;
size_t currentSize = 0;
for (i = 0; data[i] != NULL; i++)
{
if (currentSize <= i)
{
if (!resizeArray(&words, &currentSize, 5))
{
fprintf(stderr, "Could not resize words\n");
break;
}
}
strcpy(words[i], data[i]);
}
printf("current array size: %lu\n", (unsigned long) currentSize);
printf("copied %lu words\n", (unsigned long) i);
for (j = 0; j < i; j++)
{
printf("wordlist[%lu] = \"%s\"\n", (unsigned long) j, words[j]);
}
free(words);
return 0;
}
If you intend to go for C++, STL is very useful for something dynamic allocation and is very easy. You can use std::vector ..
In modern C (C99) you have an additional choice, variable length arrays, VLA, such as that:
char myWord[N];
In principle you could also do such a thing in two dimensions, but if your sizes get too big, you may risk a stack overflow. In your case the easiest thing would be to use a pointer to such an array and to use malloc / realloc to resize them:
typedef char Word[wordlen];
size_t m = 100000;
Word* words = malloc(m * sizeof(Word));
/* initialize words[0]... words[m-1] here */
for (size_t i = 0; i < m; ++i) words[i][0] = '\0';
/* array is too small? */
m *= 2;
void *p = realloc(words, m*sizeof(Word));
if (p) words = p;
else {
/* error handling */
}
.
free(words);
This code should work (modulo typos) if wordlen is a constant or a variable, as long as you keep everything inside one function. If you want to place it in a function you should declare your function something like
void myWordFunc(size_t wordlen, size_t m, char words[m][wordlen]);
that is the length parameters must come first to be known for the declaration of words.
If the 15 in your example is variable, use one of the available answers (from Ninefingers or John Boker or Muggen).
If the 1000 is variable, use realloc:
words = malloc(1000 * sizeof(char*));
// ... read 1000 words
if (++num_words > 1000)
{
char** more_words = realloc(words, 2000 * sizeof(char*));
if (more_words) {printf("Too bad");}
else {words = more_words;}
}
In my code above, the constant 2000 is a simplification; you should add another variable capacity to support more than 2000 words:
if (++num_words > capacity)
{
// ... realloc
++capacity; // will reallocate 1000+ words each time; will be very slow
// capacity += 1000; // less reallocations, some memory wasted
// capacity *= 2; // less reallocations but more memory wasted
}
Here is a little information on dynamically allocating 2d arrays:
http://www.eskimo.com/~scs/cclass/int/sx9b.html
char ** words = malloc( 1000 * sizeof(char *));
int i;
for( i = 0 ; i < 1000 ; i++)
*(words+i) = malloc(sizeof(char) * 15);
//....
for( i = 0 ; i < 1000 ; i++)
free(*(words+i));
free(words);

character missing on using Realloc and strcat on multidimensional array?

helloeveryone. I am fairly new to programming and currently trying to learn C programming to advance further in any of my projects. I've just learned how to use malloc and realloc, and all seemed good until I attempted to use strcat to combine two given strings from multidimensional array.
I am supposed to get combination of two strings based on the user inputs, and strangely, the first character is either missing or replaced by other characters...
I'll include the source code as well as the output below. I'd really appreciate you help. Thanks in advance!! ( don't mind the Korean at the end... I am korean :P)
enter code here
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int i, j;
const int row = 3;
char *pstr[3];
char temp[100];
int k,p = 0;
printf("Type in any three characters\n");
for (i = 0; i < row; i++)
{
pstr[i] = (char *)malloc(strlen(temp) + 1); //initialize the lenght of the elements in 2 part of 2D array of char b[ROW] via length of the given string
}
for (i = 0; i < row; i++)
{
scanf("%s", temp);
strcpy(pstr[i], temp);
}
printf("\n");
for (i = 0; i < row; i++)
{
printf("%s\n", pstr[i]);
}
scanf("%d", &p);
scanf("%d", &k);
printf("%s\n", pstr[p]);
printf("%s\n", pstr[k]);
*pstr[k] = (char *)realloc(pstr[k], strlen(pstr[p])+100);
strcat(pstr[k], pstr[p]);
printf("%s", pstr[k]);
for (i = 0; i < row; i++)
{
free(pstr[i]);
}
return 0;
}
\
output::LINK IS AN INTERNATIONAL SIGN FOR , IMAGE OVER HERE!!!
Two major problems:
You use temp before it have been initialized, when its contents is indeterminate and that will lead to undefined behavior.
When you do *pstr[k] = realloc(...) you dereference the pointer in pstr[k] and gets it's first element, which is a single character. You then assign the result of the realloc call to this char element. So you basically lose the actual pointer and pstr[k] will still point to the same memory (which might now be invalid).
There are other problems, but these two are the worst.
I found these in your code
1) if k or p is greater than 2 it will give runtime error
2) *pstr[k] = (char *)realloc(pstr[k], strlen(pstr[p])+100);
but this line can give error in compile time also(mac at least) - as they are not same
so you may change like this -
*pstr[k] = *(char *)realloc(pstr[k], strlen(pstr[p])+100);
3) After realloc you will get exception in free. see this - How free memory after of realloc

Pass unknown size array of structs to functions and fill

First of, I'll admit I don't know much about C and pointers, but I've been reading up and have yet to find a solution. I have also tried some solutions found here on SO but none have worked.
The info to fill the structs, as well as the size of the array, is read from a file. So, I want to declare the array in main(), to use in further processing and pass it by reference to read_p5_info() where it is initialized and filled. 'configs' is to be filled by the configurations() function.
typedef struct pentomino_info pentomino_info;
struct pentomino_info {
char name;
int orientations;
int blocks[5][2];
int configs[8];
};
int read_p5_info(int *npieces, int *matrix_size, pentomino_info **pieces) {
// piece info is read from file
// npiece and matrix_size are also read from the file
// With file I'm testing with, npieces = 12 and matrix_size = 5
*pieces = malloc(*npieces * sizeof *pieces);
for (p = 0 ; p < *npieces ; p++) {
pieces[p] = malloc(sizeof *pieces[p]);
ret = fscanf(fp, "%c %*d %d %d %*d %*d %*f", &pieces[p]->name, &p5_rotations, &p5_flips);
pieces[p]->orientations = p5_rotations * p5_flips;
// read p5 blocks
int b = 0;
for (l = *matrix_size - 1 ; l >= 0 ; l--) {
for (c = 0 ; c < *matrix_size ; c++) {
// p5_char is a char read from the file
if(p5_char == '#' || p5_char == 'X') {
pieces[p]->blocks[b][0]=c;
pieces[p]->blocks[b][1]=l;
b++;
}
}
}
}
return 0;
}
int main() {
int npieces, matrix_size;
pentomino_info *pieces; // array of p5 pieces
int ret;
ret = read_p5_info(&npieces, &matrix_size, &pieces);
// configurations() operates on each piece individually
configurations(matrix_size, &pieces[k]);
}
The pieces I'm talking about are Pentominos. npieces is the number of pentaminos the file has information for, matrix_size is because pentamino_info.blocks has coordinates X,Y of the placement of each block in a matrix_size x matrix_size matrix.
I get segfault at the end of main(). pieces[0] seems fine but still gives me segfault, and the others are just malformed.
I tried to make the code a bit more compact by removing some parts that didn't seemed relevant, if I overdid it let me know. Thanks in advance for any help.
*pieces = malloc(*npieces * sizeof *pieces); allocates the wrong amount of memory. Should be sizeof **pieces. The pattern is P = malloc(N * sizeof *P); as a cognitive cross-check, check that there is one more star on the front of the argument to sizeof.
pieces[p]->x should be (*pieces)[p].x, you make this error in multiple places. In array notation, you wrote pieces[p][0].x but the correct indexing is pieces[0][p].x. The pointer pieces only points to one pointer, which then points to the first element of an array of infos.
If this is confusing I would recommend using "normal" pointers in your function, and then implementing the return-by-reference at the end, e.g.:
int n_pie = 12; // or whatever you read
pentomino_info *pie = malloc(n_pie * sizeof *pie);
// ...
pie[p].orientations = bla;
// ...
*npieces = n_pie;
*pieces = pie;
return 0;

Malloc affecting random integer value

I'm writing a virtual memory simulator in C, compiling on linux, and I'm getting something rather strange. It takes in a file IO, which I put into an int* plist.
I've printed this "plist" array, and it comes out to
0 100
1 200
2 400
3 300
etc
The problem is that it seems malloc or something is randomly changing plist[3] to 0. It doesn't seem like it should be that way, but I've put a print statement at every line of code to print plist[3], and
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
is where it changes. plist[3] = 300 before the line, 0 after it. And it only does this when i = 2. The first 3 rounds of the loop run fine, and on round 3, it changes the values for round 4. I have no idea why, it makes little sense that malloc would change a value in an array that's completely unrelated - is it possible I've gone over some space limit, even though I'm using the heap for basically everything? Would it just change values in random arrays if I did?
for(i = 0; i < 4; i++){
num_pages = plist[i] / P1;
tables[i].page_num = (char**) xmalloc(num_pages * sizeof(char*));
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
//initialize page numbers and valid bits
for(j = 0; j < 10; j++){
tables[i].page_num[j] = (char*) xmalloc(16*sizeof(char));
tmp = itoa(i, tmp);
strcat(tables[i].page_num[j], tmp);
strcat(tables[i].page_num[j], "p");
tmp = itoa(j, tmp);
strcat(tables[i].page_num[j], tmp);
tables[i].valid[j] = 0;
}
}
Here's the struct for tables:
typedef struct s_page_table
{
char** page_num;
char* valid;
} t_page_table;
And this is xmalloc (it's just a wrapper to make it easier):
void* xmalloc(int s)
{
void* p;
p = malloc(s);
if (p == NULL)
{
printf("Virtual Memory Exhausted");
exit(1);
}
return p;
}
EDIT: If I take out both lines referencing tables[i].valid, the problem does not exist. plist[3] stays the same. num_pages is always >= 10. I set j to be 0 to 10 just to have less output for debugging purposes.
EDIT 2: If I change valid from a char* to an int* it doesn't work. If I change it to an int, it does.
There are several possibilities, including (but not limited to):
tables[i] is out of bounds;
plist contains a dangling pointer (i.e. it's been deallocated);
plist hasn't been initialised;
plist isn't as large as you think, i.e. plist[3] is out of bounds.
If you can't figure out the problem by looking at the code, valgrind is your friend.
OK. So I believe the problem turned out to be playing with the strings before initializing everything. I'm not entirely certain the reason, maybe someone else can elaborate, but when I encapsulated JUST the initialization in its own function, like only doing mallocs, and then separately created the strings afterwards, the plist variable was unaffected.
For those interested, the encapsulated function looked like this:
t_page_table* table_builder(int* p, int x, int num_tables)
{
t_page_table* ret = xmalloc(num_tables * sizeof(*ret));
int i, tmp, j;
for(i = 0; i < num_tables; i++){
tmp = (p[i]/x);
ret[i].page_num = xmalloc(tmp * sizeof(char*));
ret[i].valid = xmalloc(tmp * sizeof(char));
for(j = 0; j < tmp; j++){
ret[i].page_num[j] = xmalloc(16 * sizeof(char));
ret[i].valid = 0;
}
}
return ret;
}

Remove char from char* and return char*

I have one char array and I want to delete chars that satisfy my condition. Example I have a char array A={1,-1,0 ,1 ,-1} and I want to delete elements that equal -1. That mean output is {1,0,1}, and I want to check how many element in the array. In my example is 3. Can you help me please?
char* delete_char(char* sourceArray, char inputChar)
{
char* out=NULL;
//Need to malloc memory. But I don't know how many size will allocate because it depends on how many element that don't equal -1
return out;
}
int sizeofArray(char* sourceArray)
{
return size;
}
You have some strategies:
Calculate the exact size before allocating.
Estimate a size.
Allocate a big size memory (you probably know maximum size in worse case).
In two later cases, you can use realloc to shrink the memory. In your code, the estimated size is strlen(sourceArray)+1 if the array is a zero-terminated string, because by deleting the result is less and equal to it.
First of all, when you are using char* as an array, you also need to provide information about the length of that array (how many items it contains). Usualy this is done by a second parameter.
In your case: delete_char(char *inputArray, char inputArraySize, char inputChar).
Then you should allocate your result array to be the size of your input array (because it can contain at most as much items as the input array).
After that, you should iterate through every item in the input array and if the item fulfills your condition, add it into the result array. Of course, you have to provide also the size of the output array (for instance in an another output parameter), so you'll be able to work with it.
And lastly, when your done with working with the resulting array, don't forget do deallocate all of its memory (that means deallocate it as it was the size of the original input array, because it actially is).
You can write own function like that.
int size(char *ptr)
{
int offset = 0;
int count = 0;
while (*(ptr + offset) != '\0')
{
++count;
++offset;
}
return count;
}
Here it is:
#include <string.h>
char* delete_char(char* sourceArray, char inputChar)
{
int iNr = 0,iSize,j = 0;
iSize = strlen( sourceArray );
for( int i = 0; i < iSize; i++ )
if( sourceArray[i] == inputChar )
iNr ++;
char *newarray = new char[iNr +1];
for( int i = 0; i < iSize; i++ )
{
if( sourceArray[i] != inputChar )
newarray[j++] = sourceArray[i];
}
return newarray;
}
int sizeofArray(char* sourceArray)
{
return strlen( sourceArray );
}
PS TESTED. It works but may not be very efficient cause you check it 2 times.
You can scan the array to determine the number of elements you are removing, then allocate and appropriate memory, then copy. For example:
int sizeNeeded = 0;
for (int i = 0; i < sizeofArray(sourceArray; i++) {
if (sourceArray[I] != inputChar) sizeNeeded++;
}
char *rv = (char *) malloc(sizeNeeded * sizeOf(char));
int j = 0;
for (int i = 0; i < sizeofArray(sourceArray; i++) {
if (sourceArray[I] != inputChar) rv[j++] = sourceArray[i];
}
I did not try to compile this code but it should convey the idea

Resources