Game of Life pointers - c

I am creating game of Life in C and I am getting this segmentation fault (core dumped) error after the program takes input from user. I recently started learning C and my understanding of pointers is basic .I have not been able to find a fix for it after looking online and trying different ways to get it right. If i dont use pointers and keep it simple everything works right.I would appreciate any help
int main() {
int maxR;
int maxC;
int generations;
int i=0;
int j=0;
int k=0;
int n; //neighbour count
char state;
char **board; //original boardfor comparison
char **newBoard; //boardto make changes to
scanf("%d %d %d",&maxR,&maxC,&generations); //take input
board= (char**)malloc(maxR * sizeof(char*)); //allocating memory
newBoard=(char**) malloc(maxR * sizeof(char*)); //allocating memory
for(i=0; i<maxR; i++) {
board[i] = malloc(maxC * sizeof (char)); //allocating memory
newBoard[i] = malloc(maxC * sizeof (char)); //allocating memory
for(j=0; j<maxC; j++) {
scanf (" %c", &board[i][j]); //getting input
}
}
for(i=0; i<=generations; i++ ) {
for (j=0; j<maxR; j++) {
for (k=0; k<maxC; k++) {
state=board[j][k];
n=countNeighbours(board,maxR,maxC,j,k);
if(state == '1') { //if the cell is alive
if(n==2 || n==3) newBoard[j][k] = '1'; //if the cell has 2 or 3 neighbours then it lives
else newBoard[j][k]='0'; //else the cell dies
} else { //else (if) the cell is dead
if(n==3) newBoard[j][k]='1'; //but has 3 neibours then the cell become alive
else newBoard[i][j]='0'; //else it dies
}
}
}
memcpy(board, newBoard,sizeof(board)); //copy the updated grid to the old one
}
printBoard(board,maxR,maxC);
deallocate(board,maxR); //deallocatethe memory
deallocate(copyGrid,maxR); //deallocatethe memory

There's one obvious problem here.
memcpy(oldGrid, copyGrid,sizeof(oldGrid)); //copy the updated grid to the old one
As oldGrid is a char** pointer, then sizeof(oldGrid) is the size of a pointer, which is probably 4 or 8 bytes depending on your platform. So, you're not copying the grid, you're only copying a few bytes of it.
If you want to copy the whole grid, you need to work out the size of the grid in bytes.
If oldGrid was declared as an array, instead of a pointer, then sizeof(oldGrid) would yield the full size of the grid as you expect. Arrays behave differently from pointers when it comes to sizeof().

Related

Why does this program crash when a dynamically allocated 2D array receive input?

I'm taking input from a user to continue with my program. Everything runs perfectly fine until I attempt to input a string into the 2D array, cityName. As soon as I input the string the program crashes.
//dynamically allocate memory for user input (integers)
int *xOfCity = calloc(numOfCities, sizeof(int));
int *yOfCity = calloc(numOfCities, sizeof(int));
//dynamically allocate memory for user input (city names)
char **cityName = (char **) calloc(numOfCities, sizeof(char *));
for (int i = 0; i < numOfCities; i++)
cityName[i] = (char *) calloc(CITY_NAME + 1, sizeof(char));
int dxOfFront, dyOfFront;
//read in data from user
for (int i = 0; i < numOfCities; i++) {
scanf("%d", &xOfCity[i]);
if (xOfCity[i] > MAX_GRAPH || xOfCity[i] < MIN_GRAPH)
return ERROR;
scanf("%d", &yOfCity[i]);
if (yOfCity[i] > MAX_GRAPH || yOfCity[i] < MIN_GRAPH)
return ERROR;
for (int j = 0; j < CITY_NAME; j++)
scanf("%s", cityName[i][j]);
}
To be sure that the 2D array was the problem I commented it out and ran the program only taking the integers as inputs, and the program ran fine. I tried allocating the array in a different way, but that didn't seem to work either.
Why would my program crash upon entering a string?
It's important here to keep track of your pointer dereferences.
You start with a char**, and you access it after dereferencing it twice - that is, the two indexes, i and j. When you access cityName[i][j], you're not referencing the char*, you're actually passing the value of the first character itself. That means your program is using a character as a pointer!
You'd be better simply doing:
scanf("%s",cityName[i]);
The j is not necessary.

How to fix a segmentation error (core dumped) within a function using structs

Trying to initialize a function so its data members are 0 for the numerical values and "none" for the string but a segmentation error occurs for the strcpy.
This is for a code that creates a 2d array of an island of x,y points and prior to the later functionality I need to initialize the function to default (0's and none). I have tried to mess with the pointers and not using strcpy but to my understanding for updating strings, strcpy is needed.
typedef struct Hill {
char name[20];
int loc[2];
double height;
double slope;
} Hill;
Hill* setHill (Hill* hill){
strcpy(hill->name, "none"); // error appears to be here
hill->loc[0] = 0;
hill->loc[1] = 0;
hill->height = 0;
hill->slope = 0;
return hill;
}
int main() {
Hill* hillsArray[5];
int i;
// calling setHill to populate an array of 5 hills
for(i=0; i<5; ++i) {
setHill(hillsArray[i]);
}
// updating hill "ada's apex"
strcpy((hillsArray[0]->name), "Ada's Apex");
hillsArray[0]->loc[0] = 12;
hillsArray[0]->loc[1] = 9;
hillsArray[0]->height = 20;
hillsArray[0]->slope = 0.25;
// updating hill turing's top
strcpy((hillsArray[1]->name), "Turing's top");
hillsArray[1]->loc[0] = 4;
hillsArray[1]->loc[1] = 3;
hillsArray[1]->height = 20;
hillsArray[1]->slope = 0.33;
This updating of the hill repeats 3 more times for a total of 5 hills but its the same code just updating each hill with different values.
At least one problem, you're not allocating any memory for the Hills. Hill* hillsArray[5]; is an array of Hill pointers. They point to nowhere, so when you do hill->name, you're dereferencing a bad pointer, which is undefined behavior, which in your case is manifesting itself as a seg fault. You need to allocate memory for each Hill object, either dynamically or automatically, like this:
// dynamically (following what you have now)
int main() {
Hill* hillsArray[5];
int i;
// calling setHill to populate an array of 5 hills
for(i=0; i<5; ++i) {
hillsArray[i] = malloc(sizeof(hillsArray[0])); // equivalent to malloc(sizeof(struct Hill));
if (hillsArray[i] == NULL)
{
// in the case the malloc fails, handle the error however you want
printf("Could not allocate memory for Hill %d\n", i);
return 1;
}
setHill(hillsArray[i]);
}
....
// it's considered good practice to clean up memory you dynamically allocate,
// although you will find differing opinions of that on SO, so up to you.
// When your process exits, the OS will clean up any allocated memory, so
// in this case, it's not all that important to clean it up yourself. But
// for programs that run indefinitely, it's much more of a concern.
for (i=0; i<5; i++)
{
free(hillsArray[i]);
}
}
Or if you don't want to mess with dynamically allocating memory (I don't unless I have to), you can
// setup Hills in automatic storage instead
int main() {
Hill hillsArray[5]; // each hill is in automatic storage, probably on the stack
int i;
// calling setHill to populate an array of 5 hills
for(i=0; i<5; ++i) {
setHill(&(hillsArray[i])); // now you must pass the address of each Hill to the setHill function
}
....
// since it's automatic storage, no need to clean it up yourself
}

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

Dynamically allocating a 2D array in 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).

why I am getting segmentation fault with scanf at large inputs

I have written c code to merge sort a array of input
and I tried the code for 2 3 5 10 100 1000 10,000 and 1,000,000
it worked as desired in all cases except the 10,000 and 1,000,000
after debugging I found that the error is within scanf() code
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006a7 in main () at merge.c:10
10 scanf("%i",&array[i]);
but the code is perfectly correct as far as I am concerned
int len;
scanf("%i",&len);
int array[len];
for(int i=0; i<len;i++)
{
scanf("%i",&array[i]);
}
In case you need the full code for clearification here it is
#include <stdio.h>
void mergesort(int* list , int len);
int main()
{
int len;
scanf("%i",&len);
int array[len];
for(int i=0; i<len;i++)
{
scanf("%i",&array[i]);
}
mergesort(array,len);
for(int i=0; i<len;i++) printf("%i\n",array[i]);
printf("\b");
}
void mergesort (int* list, int len)
{
if(len == 1) return;
int i = len/2, j = len-i;
int list1[i], list2[j];
for(int k=0;k<i;k++)
{
list1[k]= list[k];
list2[k]= list[i+k];
}
if(len%2!=0) list2[j-1] = list[len-1];
mergesort(list1 , i);
mergesort(list2 , j);
int k=0,l=0;
// k represent counter over elements in list1
// l represent counter over elements in list2
// k+l represent counte over total elements in list
while(k+l!=len)
{
if(k==i)
{
for(;l<j;l++) list[k+l] = list2[l];
return;
}
else if (l==j)
{
for(;k<i;k++) list[k+l] = list1[k];
}
else if(list1[k]<list2[l])
{
list[k+l]=list1[k];
k++;
}
else if(list1[k]>list2[l])
{
list[k+l] = list2[l];
l++;
}
else
{
//handles dublication
list[k+l] = list1[k];
k++;
list[k+l] = list[l];
l++;
}
}
}
EDIT:
in case you believe that the problem platform dependent I use ubuntu 14.04
and gnu c compiler 4.8.2 and I compile the code with flags -std=c99 -Wall
and it is error and warning free
Merge sort eats plenty of memory, and you're allocating additional memory in what c programmers call stack ( int list1[i], list2[j]; ). And there's actually little room in stack. Doing it over and over again for large values exceeds the limit.
You must use heap allocations instead - dynamic allocations. Heap has plenty of memory available for allocation and is used for large arrays among other purposes. You do it like this:
//C example with malloc, ALWAYS use sizeof
int *array = (int*) malloc( length * sizeof(int));
//C++ way
int *array = new int[length];
But memory remains allocated after the program ends, unless you free it. Which can be a problem in thid case. Make sure to unallocate it when you no longer need it.
//C way
free(array);
//C++ way for arrays
delete[] array;
//C++ way for single heap values
delete value;
This is the right way so you should get used to it as youll need dynamic allocation very much in future.

Resources