String pointer issue in C code - c

This C program reads a line of text from keyboard and then writes the longest word in the line. The issue with my code below is that it only prints the last word apart from its length, although everything seems fine. Can anyone see a problem with my code?
#include<stdio.h>
#include<string.h>
#define MAX 132
#define MAXW 30
int Len_w[MAXW];
int Max_V(int vf[], int len);
main()
{
char s[MAX+1], w[MAXW], *Ind_w[MAXW],*p,out[MAXW];
int k=0, i=0, Maximum, g=0;
printf("\nInsert the line....\n");
p=fgets(s, MAX, stdin);
while(sscanf(p, "%s%n", w, &k)==1){
Len_w[i] = strlen(w);
Ind_w[i] = w; //the issue is here!!
p+=k+1;
i++;
}
Maximum = Max_V(Len_w,i);
for(g=0;g<i;g++){
if(Len_w[g] == Maximum){
//sscanf(Ind_w[g],"%s",out);
printf("\n%s", Ind_w[g]);
}
}
return 0;
}
/*----------------------------------------------------------------------------*/
int Max_V(int vf[], int len)
{
int j; int Max;
Max=*vf;
for(j=1; j < len; j++)
{
if(*(vf+j) > Max)
{
Max=*(vf + j);
}
}
return Max;
}
/*----------------------------------------------------------------------------*/

Ind_w[i] = w;//the issue is here!!
You let all pointers in Ind_w point to the same buffer, which is overwritten for each entered word. So only the last entered word remains "visible".
If you have it,
Ind_w[i] = strdup(w);
is a simple solution. Otherwise
Ind_w[i] = malloc(strlen(w)+1);
strcpy(Ind_w[i], w);
Both ways require the pointed-to memory to be freed when it is no longer used.

Ind_w[i] = strdup(w);//the issue is here!!
You have to duplicate the w buffer each time you read the buffer and not use the same buffer for all reading. with the way you did you will have all the array elements pointing to the same buffer and this buffer is containing the same string which is the last one read with sscanf
Note: you have to free all the duplicated buffers when they come useless. You can do it by go over the array of pointers and free each element (pointer)

Related

C string pointer initializes itself then de-initializes itself?

This is an excerpt from a Conway's Game of Life-program that I'm writing. In this part I'm trying to get the program to read a file that specifies what cells are to be populated at the start of the game (i.e. the seed).
I get a weird bug. In the read_line function, the program crashes online[i++] = ch statement. When I debug the program, I see that the line-pointer is NULL when it crashes. Fair enough, I think, I should initialize line. But here is the (for me) strange part:
The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file. And when I look at the execution in the debugger, I see that line is indeed holding a value in those first two executions of read_line. How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAX_COORDINATE_SIZE 50
#define MAX_FILENAME_SIZE 20
#define MAX_GENERATIONS 10
#define MAX_REPETITION_PERIOD 4
struct coord{ //Holds coordinates to a cell
int x;
int y;
};
struct cell{
int pop; //Populated
int age;
};
struct coord *read_init(FILE *fp, int *i);
static int read_line(FILE *fp, char *line, int max_length);
struct coord read_coords(char *line);
struct cell **create_board(int x, int y);
struct cell **start_game(FILE *fp, int nrows, int ncols);
struct cell new_cell(int x, int y, int pop, int age);
void print_board(struct cell **board, int nrows, int ncols);
void populate_board(struct coord *coords, struct cell ***board, int *n);
int main(int argc, const char * argv[]) {
int gens;
char gens_string[MAX_GENERATIONS];
if(argc != 3){
fprintf(stderr, "Usage: %s <seed-file> <generations>\n<seed-file> can me up to %d characters long\n", argv[0], MAX_FILENAME_SIZE);
exit(1);
}
FILE *fp = fopen(argv[1], "r");
strncat(gens_string, argv[2], MAX_GENERATIONS);
gens = atoi(gens_string);
int nrows = 10;
int ncols = 10;
struct cell **board= start_game(fp, nrows, ncols);
print_board(board, nrows, ncols);
return 0;
}
struct coord *read_init(FILE *fp, int *n){ //Takes in filename and returns list of coordinates to be populated
char raw_n[100];
struct coord *coords;
char *line;
read_line(fp, raw_n, 100); // get the first line of the file (number of popuated cells)
*n = atoi(raw_n);//make an int out of raw_n
coords = malloc(sizeof(struct coord)*(*n)); //Allocate memory for each coord
for(int i = 0; i<(*n); i++){ // for each line in the file (each populated cell)
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0';
}
return coords; // return coordinates
}
static int read_line ( FILE *fp, char *line, int max_length)
{
int i;
char ch;
/* initialize index to string character */
i = 0;
/* read to end of line, filling in characters in string up to its
maximum length, and ignoring the rest, if any */
for(;;)
{
/* read next character */
ch = fgetc(fp);
/* check for end of file error */
if ( ch == EOF )
return -1;
/* check for end of line */
if ( ch == '\n' )
{
/* terminate string and return */
line[i] = '\0';
return 0;
}
/* fill character in string if it is not already full*/
if ( i < max_length )
line[i++] = ch;
}
/* the program should never reach here */
return -1;
}
struct coord read_coords(char *line){ // Returns coordinates read from char *line
struct coord c;
char *x;
char *y;
x = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
y = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
int i = 0;
do{
x[i] = line[i]; //Get the x coordinate
i++;
}while(line[i] != ' ');
i++;
do{
y[i-2] = line[i];
i++;
}while(line[i] != '\0');
c.x = atoi(x)-1;
c.y = atoi(y)-1;
return c;
}
void init_board(int nrows, int ncols, struct cell ***board){
*board = malloc(nrows * sizeof(*board) + nrows * ncols * sizeof(**board));
//Now set the address of each row or whatever stackoverflow says
struct cell * const firstrow = *board + nrows;
for(int i = 0; i < nrows; i++)
{
(*board)[i] = firstrow + i * ncols;
}
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = new_cell(i, j, 0, 0);
}
}
}
void print_board(struct cell **board, int nrows, int ncols){
printf("--------------------\n");
for(int i = 0; i<nrows; i++){
for(int j = 0; j<ncols; j++){
if(board[i][j].pop == 1){
printf("%d ", board[i][j].age);
}else if(board[i][j].pop == 0){
printf(" ");
}else{
printf("\n\nERROR!");
exit(0);
}
}
printf("\n");
}
printf("--------------------");
printf("\n");
}
struct cell **start_game(FILE *fp, int nrows, int ncols){ //x,y are no of rows/columns, fn is filename
int n; // n is the number of populated cells specified in the seed
struct coord *coords = read_init(fp, &n); // get the list of coords to populate board with
struct cell **board;
init_board(nrows, ncols, &board); // Set up the board
populate_board(coords, &board, &n); //populate the cells specified in the seed
return board;
}
void populate_board(struct coord *coords, struct cell ***board, int *n){
for(int i = 0; i < *n; i++){
(*board)[coords[i].x][coords[i].y].pop = 1; //populate the cell
}
}
struct cell new_cell(int x, int y, int pop, int age){ //Return new populated or non-populated cell with specified coordinates
struct cell c;
c.pop = pop;
c.age = age;
return c;
}
The seed file:
4
3 6
4 6
5 6
5 7
EDIT:
The error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
In read_init() :
struct coord *read_init(FILE *fp, int *n){
//...
char *line;
//...
for(int i = 0; i<(*n); i++) {
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0'; // <<--- you set line to NULL here.
*line = 0; // this is what you wanted to do, is not necessary...
}
// ....
}
I get a weird bug.
I suggest asking some questions about the compiler output. We should never blindly ignore warnings, after all. Speaking of reading things, I think you're spending too long reading StackOverflow and not long enough reading K&R2e and doing the exercises. We'll come back to that.
In the read_line function, the program crashes on line[i++] = ch statement ... But here is the (for me) strange part: ... The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file
The C and C++ standards rationalise the concept of "undefined behaviour" for this class of errors that are computationally difficult to diagnose. In other words, because you made an error, the behaviour of your program is undefined. It isn't required that your malfunctioning code crash every time, as that would be defining the undefined; instead they leave this "undefined" and the first two times your erroneously code works (whatever that means), purely by coincidence that the uninitialised variable points somewhere accessible. Later on you assign line = '\0';, which changes line to be a null pointer, and then you try to assign into whatever that null pointer points at. That's more undefined behaviour.
How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
line isn't initialised; you're using it uninitialised, which happens to coincidentally work (but needs fixing), then you assign it to be a null pointer and dereference a null pointer (more UB that needs fixing). Such is the nature of undefined behaviour. Such is the nature of learning C by guessing. You need a book!
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
You need to fix all of the errors, not just the one. For assistance you could see the warnings/errors your compiler emits. I see more uninitialised access here:
char gens_string[MAX_GENERATIONS]; // <--- where's the initialisation??
// Snip
strncat(gens_string, argv[2], MAX_GENERATIONS); // Boom
There's some really sus code around this comment: //Now set the address of each row or whatever stackoverflow says ... and on that note I want to point out that there are some subtly toxic know-it-alls who answer questions despite having as many misunderstandings as you, a humble person, and so you shouldn't hope to get the same quality of education from StackOverflow as you would from K&R2e... but apparently I'd be toxic for pointing out the egomaniacs and suggesting decent resources to learn from, so that's none of my business 🙄🤷‍♂️ let's just let the sociopaths sabotage the education of everyone huh?
(*board)[i] = firstrow + i * ncols;
Look, there is no guarantee that this even compiles let alone that the address on the right has a suitable alignment to store the type of value on the left. Misaligned access causes more undefined behaviour, which may also work coincidentally rather than logically. Just as you've never seen alignment violations before, so too has the person who suggested you use this code. Assuming the alignment requirements for your implementation are satisfied by this code, we then have the same questions to raise here:
(*board)[i][j] = new_cell(i, j, 0, 0);
Your whole program needs remodelling around the declaration of board changing from struct cell **board to struct cell (*board)[ncols];, for example. It'll become much simpler, and a whole class of bugs related to alignment requirements will disappear. To see the extent of the simplification, here's what your init_board ought to look like:
void init_board(int nrows, int ncols, struct cell (**board)[ncols]){
*board = malloc(nrows * sizeof(*board));
// NOTE: I snipped the erroneous StackOverflow logic around the comment mentioned above; you don't need that crud because of the more suitable choice of type
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = (struct cell){ 0, 0 };
}
}
}

Need to be "pointed" in the right direction beginning C programming

and thanks for your time. I apologize in advance I am new to C programming and posting on stack overflow. Any information I may have left out and questions you have please ask.
I have this lab I am working on for my class and I'm having trouble understanding how the dreaded pointers operate. First I will explain the lab instructions.
First, I am to create an array of 200 words with a max length of 30+1 for null.
Next, call functions I need to create which include:
A read function which reads words from a file into the array. I must use fopen and fscanf functions.
A function to convert a string to lowercase using the ASCII codes of each character. (Must use pointers)
A function to return the length of a string.(Can't use strlen function and must use pointers)
A function with three parameters(array of words, # of words in array, and an int length). Function returns the number words in the array that match the int length.
A print function to print all the words in the array.
The IDE I am using is Dev C++ its been wonky so I have also been using netbeans.
I have only attempted to create the read, print, and converting to lowercase functions. I first tried to read the file and print the array in main. The file I'm reading is created by me it contains a short sentence which follows exactly:
There ARE so MANY words in HERE
EDIT- Updated main code to current with working lowercase loop inside main.
#define rows 200 //How many words allowed in array.
#define cols 31 //How many characters allowed for each word.
void lowercase(char* words, int count);
int read(char (*words)[cols]);
void print(char (*words)[31], int count);
int main(int argc, char *argv[]){
char words[rows][cols];
int i, j;
int count = read(words);
print(words, count);
/*
//make words lowercase
for(i = 0;i<count;i++){
for(j = 0;j<cols;j++){
if(words[i][j]!=0){
if(words[i][j]<91 && words[i][0]>64)
words[i][j] = words[i][j]+32;
}
}
}*/
for(i = 0;i < count;i++){
lowercase(*words+i, count);
}
print(words, count);
return 0;
}
The code is poorly written and managed properly I'm just trying to get everything to work first then it will be more appropriate. The first printf output comes out how it should:
Array [0]: There
Array [1]: ARE
Array [2]: so
Array [3]: MANY
Array [4]: words
Array [5]: in
Array [6]: HERE
Then the print function I have prints out the words correctly in the array but it includes all 30 spaces for each word instead of just the word. This is how it is written I need to change it.
void print(void *array, int SIZE){
int i,
j;
char *charArray = (char *) array;
for( j = 0; j < SIZE; j++ ){
for( i = 0; i < SIZE; i ++){
printf( "%c ", charArray[j*SIZE + i] );
}
printf( "\n" );
}
}
The tolower function I created was partially working converting the first letter of each word to lowercase. Now it is broke and do not remember what I have changed.
EDIT- updated lowercase function. The lowercase in main works exactly but with this function it doesn't convert all the words to lowercase it stops at the third word the rest are the same.
void lowercase(char *words, int count){
int j;
for(j = 0;j<cols;j++){
if(words[j]!=0){
if(words[j]<91 && words[j]>64)
words[j] = words[j]+32;
}
}
}
I tried to move the read code in main to its own function also trying to mimic the print code with the pointers but when I run the program it stalls and the exe file stopped working window pops up with command prompt.
No errors or warnings in IDE.
int read(void *array){
FILE *file;
int i,
j;
char *words = (char *) array;
file = fopen("words.txt", "r");
//STORE IN ARRAY
for(i=0;i<7;i++)
fscanf(file,"%s", words[i]);
}
If you have not figured out I have no idea when or how to use pointers or addresses. I have been taught basically all of C in literally 12 hours which is in my opinion not enough time to learn the language at all especially understand it efficiently. Any help will be greatly appreciated. Thank You.
By casting a 2-dimensional array down to a char*, you have lost some information. If you read the words in correctly, then in memory, your array might look like this:
0 10 20 30
|.........|.........|.........|.
There
ARE
so
MANY
words
in
HERE
To access words[1] the compiler is automatically offsetting 31 bytes from the beginning of the array.
Your problem is that after you cast words to char*, then the compiler no longer knows about the 2D structure, and words[1] will now only offset 1 byte from the beginning of the array.
A simple solution is to redefine your read function:
int read(char words[][31])
{
FILE *file;
int i, j, count = 0;
file = fopen("words.txt", "r");
for (i=0; i<7; i++)
{
count += (1 == fscanf(file, "%s", words[i]));
}
return count;
}
Now the compiler knows that the memory stride size for words[i] is 31 char values.
Similar thing with print:
void print(char words[][31], int count)
{
int i;
for( i = 0; i < count; i ++)
{
printf( "%s\n", words[i] );
}
}
fix like this:
#include <stdio.h>
#include <stdlib.h>
//Stringification
#define S_(n) #n
#define S(n) S_(n)
//Information to be shared across the whole area
#define MAX_ROWS 200
#define MAX_WORD_LENGTH 30
#define COLS (MAX_WORD_LENGTH + 1)
#define DATA_FILE "words.txt"
int read(void *array);
void print(void *array, int rows);
int main(void){
char words[MAX_ROWS][COLS];
int rows;
rows = read(words);
print(words, rows);
return 0;
}
int read(void *array){
FILE *file = fopen(DATA_FILE, "r");
if(file == NULL){
perror("fopen:");
exit(EXIT_FAILURE);
}
char *words = array;
int rows;
for(rows = 0; rows < MAX_ROWS; ++rows, words += COLS){
if(fscanf(file, "%" S(MAX_WORD_LENGTH) "s", words) == EOF)
break;
}
fclose(file);
return rows;
}
void print(void *array, int rows){
char *words = array;
for(int r = 0; r < rows; ++r, words += COLS){
printf("Array [%d]: %s\n\n", r, words);
}
}

Requiring help to understand arrays

I'm learning about arrays in C and I can't figure out why the following is not correct?
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
string plaintext = get_string();
int x = 5;
long long N = strlen(plaintext);
string a = plaintext;
long long c = 0;
int z = x;
for(int i = 0; i < N + (N/x) ; i++)
{
if( i == x)
{
a[c] = 32;
c++;
z = (z + x);
//printf("%c\n", a[c]);
}
a[c] = plaintext[i];
//printf("%c\n", a[c]);
c++;
}
printf("%s\n", a);
}
It's meant to insert spaces into a string of text after every x chars... I know it's not efficient (I reckon I need something called pointers) but why isn't it working? I went through it using a debugger and it seems like my original string is changing as I go... but why?
Assuming string is char * then text and a point to the same string. That explains why your original string changes. What you can do is:
string a= malloc(N+1 + N/x +1);
This allocates space for a new string, into which you copy the original with a space after every x characters. Add 1 for the terminating null character and 1 "to be safe" when x or N are odd.
#include <bits/stdc++.h>
using namespace std;
#define freinput "input.txt","r",stdin
#define freoutput "output.txt","w",stdout
#define mp make_pair
#define fi first
#define sc second
#define ellapse printf("Time : %0.3lf\n",clock()*1.0/CLOCKS_PER_SEC);
typedef long long ll;
typedef unsigned long int uld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int,int> pii;
string s;
string stringInsertion(int x,string neww){
for(int i = 0;i<s.size();i++){
if(i!=0 && i%x==0){
neww=neww+' '+s[i];
}
else neww+=s[i];
}
return neww;
}
int main(){
cin>>s;
int x = 2;
string neww="";
cout<<stringInsertion(x,neww);
}
just set the x number.hope this help
Okay, let's do something similar first: Print out the string with spaces. Use i to loop through the string. Every time i is evenly divisibly by x, we print a space before we print the character, but not at the beginning:
void print_spaced(const char *s, int x)
{
int i;
for (i = 0; s[i]; i++) {
if (i && i % x == 0) putchar(' ');
putchar(s[i]);
}
putchar('\n');
}
You don't need to determine the length beforehand, because you can stop when you hit the terminating null character. That is, keep going as long as s[i] is not null. (Recall that s[i] is the same as s[i] != '\0' and similarly, i is the same as i != 0.)
Now let's fill a char array with the spaced out string instead of printing it:
int space_out_unsafe(char *res, const char *s, int x)
{
int i, k = 0;
for (i = 0; s[i]; i++) {
if (i && i % x == 0) res[k++] = ' ';
res[k++] = s[i];
}
res[k] = '\0';
return k;
}
This function takes an additional parameter: A char buffer to fill. It has a second index, k, which is the current length of the result buffer. Whenever we printed in the first version, we now append a character to the string:
res[k++] = '#';
Tis overwrites the current end and moves k on one position. We don't write a newline at the end, but we must null-terminate the result.
There is one problem, though: The buffer may overflow; note how I have labelled the function above unsafe. Arrays in C have a fixed size and won't grow automatically when something is appended. It is there fore a good idea to pass the maximum buffer size max to the function and check for overflow before appending:
int space_out(char *res, int max, const char *s, int x)
{
int i, k = 0;
for (i = 0; s[i]; i++) {
if (i && i % x == 0 && k < max - 1) res[k++] = ' ';
if (k < max - 1) res[k++] = s[i];
}
res[k] = '\0';
return k;
}
You can now use this function like this:
char res[20];
space_out(res, sizeof(res), "Doremifasola", 2);
puts(res);
There are other ways to accomplish this. You could allocate the memory dynamically, as Paul suggested. That way, you can cater for the additional space you need, but you also make the caller of the function take care of cleaning up the allocated memory with free. Dynamically allocating memory is something to look into after your first week. :)
Another possibility is to space out the string in place, that modify the contents of the original buffer. You still have to take care to provide the extra space, though. (Usually, in-place midofication is used when the result string is shorter, e.g. when filtering out characters.) You should also process your string from the and as not to overwrite data you need later with spaces. If you feel confident, that's an exercise for next week, too.

how to make two array strings into one array string in C

How do you make 2 array strings into 1 array string, where I can print out all the 52 playing cards?
my code:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
int main() {
char deck[52];
char suits[] = {"Hearts","Diamonds","Clubs","Spades"};
char values[]= {"Ace","Two","Three","Four","Five","Six",\
"Seven","Eight","Nine","Ten","Jack",\
"Queen","King"};
int V, S, d = 0;
char string;
for ( S= 0; S <4; S++) {
for (V =0; V< 13; V++) {
string = strcat( values[V], suits[S]);
deck[d] = string;
printf("%s\n", string);//prints out all the 52 playing cards
d++;
}
}
return 0;
}
When I executed the program, the problem comes up which asks me to debug the program or close the program, where I closed the program in the end, which returns nothing. Can you please give me the answer which works?
Check the below code which fixes the issues in your code:
The problem with your code is you try to modify the actual string before printing and because of this there is a modified string in the next iteration. So just copy the values and suits to array and print it out as shown below.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
int main()
{
int i=0;
char deck[30] = "";
char suits[][30] = {"Hearts","Diamonds","Clubs","Spades"};
char values[][30]= {"Ace","Two","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten","Jack",
"Queen","King"};
int V, S;
for ( S= 0; S <13; S++)
{
for (V =0; V< 4; V++){
memset(deck,0,sizeof(deck));/* Clear the buffer before writing new value*/
strcpy( deck, values[S]);
strcat(deck,suits[V]);
printf("%s\n", deck);//prints out all the 52 playing cards
i++;
}
}
printf("Number of playing cards: %d\n",i);
return 0;
}
strcat() returns a char *, a pointer to a char, not a char.
You are not even required to even consider the return value of strcat() since the destination pointer (first argument) will now contain the concatenated string, assuming enough memory is already allocated.
So here in your code, you are trying to put the concatenated string to values[V] which could fail when memory already allocated to it becomes insufficient.
The best method would be to allocate some memory (as you did with deck[]) and set it all to zeroes. Then keep strcat()ing there.
strcat(deck, values[V]);
strcat(deck, suits[S]);
An alternative to using strcpy and strcat is to use sprintf.
#include<stdio.h>
#include<string.h>
#define NUM_SUITS 4
#define CARDS_PER_SUIT 13
#define TOTAL_CARDS (NUM_SUITS * CARDS_PER_SUIT)
int main()
{
char deck[TOTAL_CARDS][24];
char* suits[NUM_SUITS] = {"Hearts","Diamonds","Clubs","Spades"};
char* values[CARDS_PER_SUIT]= {"Ace","Two","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten","Jack",
"Queen","King"};
int s, c, i;
for(s = 0; s < NUM_SUITS; s++)
{
for(c = 0; c < CARDS_PER_SUIT; c++)
{
sprintf(deck[(s * CARDS_PER_SUIT) + c], "%s of %s", values[c], suits[s]);
}
}
for(i = 0; i < TOTAL_CARDS; i++)
{
printf("%s\n", deck[i]);
}
return 0;
}

Image erosion technic in c

I have some weird issue with c program. I am learning c programming on-line and I practise some exercise. On of them is about a imagery technic called erosion. Imagine there is an image with two types of pixels symbolized by either '.' or '#'. When a pixel is surrounded by 4 '#' character, it is preserved, and in the other case it is replaced by a '.' character. The input is N the number of times the erosion is applied, H and L the height and width of the image, and a rectangle of characters composed by '.' and '#' character.
For instance input :
1 //N
4 //H
4 //L
....
.###
####
####
and the output is
....
....
.##.
....
The problem is that the on-line compiler (that tests a random serie of inputs) rejects my code telling that the memory is overflowed
Here is the code
#include <stdlib.h>
#include <stdio.h>
//test wether a pixel is surrounded by 4 '#' characters
char test(int i, int j,int H, int L, char c[H][L]){
int k=0;
int l=0;
char result='-';
if((i==0)||(i==H-1)||(j==0)||(j==L-1)){
result='+';
}
else{
for(k=0;k<2;k++){
for(l=0;l<2;l++){
if(c[i+(1-2*k)*l][j+(1-2*k)*(1-l)] =='.'){
result='+';
break;
}
else{
}
}
if(result=='+'){break;}
else{}
}
}
return result;
}
//The erode function that replaces the image by one in which '#' characters are replaced by '.' characters when it is not surrounded by 4 '#' characters
char **erode(int H, int L, char c[H][L]){
int i;
int j;
char ch='-';
char **d = malloc (H * sizeof (int *));
for (i = 0; i < H; i++) {
d[i] = malloc (L * sizeof (int));
}
i=0;
for (i=0;i<H;i++)
{
for (j=0;j<L;j++)
{
ch=test(i,j,H,L,c);
if(ch=='+'){
d[i][j]='.';
}
else{
d[i][j]=c[i][j];
}
ch='-';
}
}
for (i= 0; i < H; i++) {
free(d[i]);
}
free(d);
return d;
}
//here are computed the inputs and outputs
int main()
{
int i=0;
int j=0;
int N;
int H;
int L;
char o;
scanf("%d",&N);
scanf("%d",&H);
scanf("%d",&L);
scanf("%c",&o);
char c[H][L];
char d[H];
char ero[H][L];
while (i<H)
{
while (j<L)
{
scanf("%c",&c[i][j]);
j++;
}
j=0;
scanf("%c",&d[i]);
i++;
}
int l;
int m;
int n;
for(l=0;l<N;l++){
for (i=0;i<H;i++)
{
for (j=0;j<L;j++)
{
ero[i][j]=erode(H,L,c)[i][j];
}
}
for (m=0;m<H;m++)
{
for (n=0;n<L;n++){
c[m][n]=ero[m][n];
}
}
}
for (i=0;i<H;i++)
{
for (j=0;j<L;j++){
printf("%c",c[i][j]);
}
printf("\n");
}
}
(The code is far from being optimal because I tried to debugg it and to make something really decomposed)
Does anyone has an idea why I have this message error?
This is probably because within your erode function you are using malloc a number of times but never calling free. You actually call erode inside a triple loop from main. This suggests it could be getting called many times but as the allocated memory never gets released it is entirely possible that your memory is getting exhausted which explains the error message. Take more care to release the memory using free when you no longer need it.

Resources