# Thread: Function Problem

1. ## Function Problem

I have a program in which I have a function already created. The function works how it was suppose to for the previous program, but now we are to improve it. So i need to re-implement this function and change it around to work a little differently, also i need to implement a safe malloc and safe realloc function, I have a safe malloc function, I don't know how to make a safe_realloc function though. Heres the code and what to do:

char *readLine(char *s, int n, FILE * fp, bool * overflow);
Although correct, this implementation has some shortcomings,
including the following:The user of this function must be able to
estimate a maximum line length.Characters are truncated if the maximum
line length is too small.The number of parameters to this function
makes it dicult to understand.(As a generalrule,
as the number of parameters increases,
it is often more dicult.
Imagine a function with twenty
parameters !)

1. Re - read the sections in our book which describe malloc()
and realloc().Implement \ safe "
versions of each of these. The idea is that if either memory allocation or reallocation fails wewant the program to stop. (See the solution
pmsort.c to see how to do this.)2. Re-implement readLine, using the following prototype:

Here's the result we want from the revised
readLine(). If the given le pointer is at theend of le, then readLine() should return NULL. Otherwise, it should allocate just the rightamount of memory|no more and no less|to store the next line of input. All characters up toand including the newline should be read and consumed; everything except the terminatingnewline should be stored in the allocated memory. As in the previous implementation, thestring of characters should be terminated with the null character.If there is not enough space available to store such a string, readline() should abort theprogram.For eciency, use the doubling method of allocation discussed in class. Also, for debuggingpurposes, your function should display the number of bytes allocated or reallocated for thecharacter string. This should be output immediately before the function is to return.
Demonstrate your function by using a modi ed version of readfile4.c.

Code:
```#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define FILE_NAME "words"       /* name of the input file */
#define MAX_WORD_LENGTH 8       /* adjust as needed */

char *readLine(char *s, int n, FILE * fp, bool * overflow);

int main(void)
{
FILE *fp;                     /* file pointer for an input stream */
int lineCount;                /* number of lines processed */
bool lineOverflow;            /* not enough room in char array? */
int nrErrors;                 /* how many lines overflow char array? */

char line[MAX_WORD_LENGTH + 1]; /* string to hold one line of input */

/* Try to open the input stream for reading */
fp = fopen(FILE_NAME, "r");
if (fp == NULL) {
fprintf(stderr, "Error: can't open %s for reading.\n", FILE_NAME);
exit(EXIT_FAILURE);
}

/* Process the file, line by line */
nrErrors = 0;
lineCount = 0;
while (readLine(line, sizeof(line), fp, &lineOverflow) != NULL) {
printf("Current line = \"%s\"", line);
lineCount++;
if (lineOverflow) {
nrErrors++;
printf(" (overflow in line: characters discarded.)\n");
} else
printf("\n");
}
printf("Lines processed = %d\n", lineCount);
printf("Number of lines which didn't fit = %d\n", nrErrors);

/* Close the stream */
fclose(fp);

return 0;
}

/* Read and store one line of input

return NULL if stream is at eof or there was a read error
otherwise returns the pointer s to the char array

reads and stores up to n characters in the char array, stopping at newline
if there isn't space to hold the entire line, overflow is set to true
and any trailing characters on that line are discarded
*/
char *readLine(char *s, int n, FILE * fp, bool * overflow)
{
int i;                        /* number of characters stored in the string */
int ch;                       /* most recent character read from the file */
int count;                    /* number of characters read */

i = 0;
count = 0;
/* Read characters on the current line, storing as many as will fit */
while (((ch = getc(fp)) != '\n') && (ch != EOF)) {
count++;
/* Safely deposit this character */
if (i < n - 1)              /* hold one slot back for '\0' */
s[i++] = ch;
}
if ((count == 0) && (ch == EOF))  /* no characters read: at eof */
return NULL;

/* Stream was not at eof, so a line has been read */
s[i] = '\0';                  /* properly terminate the string */

/* Too many characters on this line? */
if (count > i)
*overflow = true;
else
*overflow = false;

return s;
}```
Also here is the safe_malloc function:
Code:
```/* safely allocate a block of storage, aborting program if not possible */
void *safe_malloc(size_t size)
{
void *p;
p = malloc(size);
if (p == NULL) {
fprintf(stderr, "pmsort: error - out of space!");
exit(EXIT_FAILURE);
} else
return p;
}```

2. Your quote from the assignment runs wickedly off the width of the space provided by the forum, because you posted it as code.

Shorten the line length of whatever you post between code tags, or use [quote] tags, instead. Your error message might be better if you used "error - memory allocation failed!", imo.

What have you tried to do to create a "safer" realloc()? What you've coded already is water over the dam, since it's already working and done.

You have a good code style - congrats!

3. Thank you, and its working, but I have to re-implement it for the given instructions. I dont know how to change the function in the way my professor is looking for.

4. By a safer_realloc, its just the same function as the realloc, but we are to add a part to it that ends the program if it cant realloc anymore memory. My main problem is changing the readLine function. He gave us a hint that we should be able to just use 1 parameter, FILE *fp, but the function now has to deal with memory (start with 10) and realloc memory if there are still characters in the string(double the memory each time we have to realloc). Any help?

5. No help yet. You were in the class, you did the previous functions, and you (hopefully) reviewed the part in your book the prof asked you to.

So start it out - there's no way we can know all these particulars as well as you do, and there's no way we want to spend the time to start your assignment for you. We don't do that. What we do is try to help you get over the rough spots, and fix problems with your code. As a practical matter, there's no way we can avoid the forum being turned into a free homeworking coding service, if we start assignments for the many students who read the forum.

The start is entirely up to you. Give it a shot. You may not know right now how to complete the assignment, but I'll bet you will be able to get it started, and at the same time, show that you're serious about working on it.

This is all in the FAQ of the forum, btw.

6. Okay, i've been working pretty hard trying to understand this. I have my safe_malloc and safe_realloc functions, and I have changed my readLine funciton around. My program is compiling, but with warnings of which I dont know what they mean. Could anyone help me now? I appreciate it!

Heres My Code (its in the program that we are suppose to use it in, given by our professor):

Code:
```/*
Purpose: Similar to readfile3.c, with a re-implementation of readLine
Author:  Bill Slough

Bugs:
1. We continue to assume no read error will occur.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define FILE_NAME "words"    /* name of the input file */
#define MAX_WORD_LENGTH 8    /* adjust as needed */

void *safe_malloc(size_t size);
void *safe_realloc(void *ptr, size_t size);

int main(void) {
FILE *fp;           /* file pointer for an input stream */
int lineCount;      /* number of lines processed */

char line;  /* string to hold one line of input */

/* Try to open the input stream for reading */
fp = fopen(FILE_NAME, "r");
if (fp == NULL) {
fprintf(stderr, "Error: can't open %s for reading.\n", FILE_NAME);
exit(EXIT_FAILURE);
}

/* Process the file, line by line */
lineCount = 0;
while (readLine(fp) != NULL) {
printf("Current line = \"%s\"", line);
lineCount++;
printf("\n");
}
printf("Lines processed = %d\n", lineCount);

/* Close the stream */
fclose(fp);

return 0;
}

/* Read and store one line of input

return NULL if stream is at eof or there was a read error
otherwise returns the pointer s to the char array

reads and stores up to n characters in the char array, stopping at newline
if there isn't space to hold the entire line, overflow is set to true
and any trailing characters on that line are discarded
*/
char *readLine(FILE *fp) {
int i = 0;
int capacity = 10;       /* number of characters stored in the string */
int ch;      /* most recent character read from the file */
int count;   /* number of characters read */

char *p = safe_malloc(capacity);

while(((ch = getc(fp)) != '\n') && (ch != EOF)) {
count++;
/*Check if i is at the capacity */
if (i == capacity - 1) {
/*If it is, realloc more memory */
p = safe_realloc(p, (capacity * 2));

/*Safely deposit the character */
if(i < capacity - 1) {
p[i++] = ch;
}
} else
p[i++] = ch;
}

if ((count == 0) && (ch == EOF))  /*no characters read: at EOF */
return NULL;
/*Stream not at EOF, a line has been read */
p[i] = '\0';

capacity = safe_realloc(p, count);

printf(capacity);
return p;
}

void *safe_malloc(size_t size) {
void *p;
p = malloc(size);
if (p == NULL) {
fprintf(stderr, "readfile4, error  - out of space!");
exit(EXIT_FAILURE);
} else
return p;
}

void *safe_realloc(void *ptr, size_t size) {
void *p;
p = realloc(ptr, size);
if(p == NULL) {
fprintf(stderr, "readfile4, error - out of space!");
exit(EXIT_FAILURE);
} else
return p;
}```
Warnings from compiler:
-*- mode: compilation; default-directory: "/home/connor/hw09/" -*-
Compilation started at Tue Mar 5 15:00:20

readfile4.c: In function ‘main’:
readfile4.c:38:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
readfile4.c:87:14: warning: assignment makes integer from pointer without a cast [enabled by default]
readfile4.c:89:5: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [enabled by default]
/usr/include/stdio.h:363:12: note: expected ‘const char * __restrict__’ but argument is of type ‘int’
readfile4.c:89:5: warning: format not a string literal and no format arguments [-Wformat-security]
readfile4.c: In function ‘main’:
readfile4.c:38:15: warning: ‘line’ may be used uninitialized in this function [-Wuninitialized]

Compilation finished at Tue Mar 5 15:00:21

7. Code:
`char line;  /* string to hold one line of input */`
Well, "line" is definitely not a string (Reason for the warning on line 38).

Code:
`while (readLine(fp) != NULL) {`
What about the return value of readLine()?

Code:
`count++;`
"count" is used uninitialised.

Code:
`p = safe_realloc(p, (capacity * 2));`
You never update "capacity" in your code.

Code:
```capacity = safe_realloc(p, count);
printf(capacity);```
What's the type of "capacity"?

You are also missing some free()-calls, thus leaking memory.

Bye, Andreas

8. capacity is an int, a part of this function has to handle memory allocation, the designeted memory(starting capacity) would be 10, i need to reallocate memory (doubling capacity each time), but at the end I need to only have enough memory to fit everything that was read on that line, and then i need to print out the ending memory amount that was allocated. How would i do that?

9. First post:

"For eciency[sic], use the doubling method of allocation discussed in class."
Most recent post:

...i need to reallocate memory (doubling capacity each time), but at the end I need to only have enough memory to fit everything that was read on that line
I think it's safe to say that most of us were not in your class at the time this was discussed. Can you elaborate a little on this method you learned during lecture? (Hint: refer to your notes.)

It almost sounds like you need two memory allocation mechanisms - one that grows by a increasing, fixed amount, and another that gives exactly enough memory - no more, no less.

You need to understand the requirements before you can code for it. If I'm guessing, I'd say:

Code:
```while read not complete
grow memory by a fixed amount

get size of read
allocate new space for read (let's call the quantity of that space "readAmount")
copy read from first allocation to second allocation
free first allocation

10. -+The function has to deal with malloc and realloc functions, but we had to make our own "safe" versions in which if it returns null, it exits our program. So, the function we need to allocate a starting capacity, 10. read characters in, if we run out of space we double the capacity, and keep reading characters until theres none left to read or we need to allocate more space, in which we double the current capacit again. When were done reading were suppose to realloc the memory back to just the amount that is needed. Any help based on what i have

11. Heres my current code if anyone can take a look for me:

Code:
```/*
Purpose: Similar to readfile3.c, with a re-implementation of readLine
Author:  Bill Slough

Bugs:
1. We continue to assume no read error will occur.

Edits Made By: Connor Moore
changed the readLine function to take less parameters and opperate
a little differently. It now should handle reallocating memory for
strings that wont fit the initial size.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define FILE_NAME "words"    /* name of the input file */
#define MAX_WORD_LENGTH 8    /* adjust as needed */

void *safe_malloc(size_t size);
void *safe_realloc(void *ptr, size_t size);

int main(void) {
FILE *fp;           /* file pointer for an input stream */
int lineCount;      /* number of lines processed */

char *line;  /* string to hold one line of input */

/* Try to open the input stream for reading */
fp = fopen(FILE_NAME, "r");
if (fp == NULL) {
fprintf(stderr, "Error: can't open %s for reading.\n", FILE_NAME);
exit(EXIT_FAILURE);
}

/* Process the file, line by line */
lineCount = 0;
while (readLine(fp) != NULL) {
printf("Current line = \"%s\"", line);
lineCount++;
printf("\n");
}
printf("Lines processed = %d\n", lineCount);

/* Close the stream */
fclose(fp);

return 0;
}

/* Read and store one line of input

return NULL if stream is at eof or there was a read error
otherwise returns the pointer s to the char array

reads and stores up to n characters in the char array, stopping at newline
if there isn't space to hold the entire line, overflow is set to true
and any trailing characters on that line are discarded
*/
char *readLine(FILE *fp) {
int i = 0;
int capacity = 10;       /* number of characters stored in the string */
int ch;      /* most recent character read from the file */
int count = 0;   /* number of characters read */

char *p = safe_malloc(capacity);

while(((ch = getc(fp)) != '\n') && (ch != EOF)) {
count++;
/*Check if i is at the capacity */
if (i == capacity - 1) {
capacity = capacity * 2;
/*If it is, realloc more memory */
p = safe_realloc(p, (capacity));

/*Safely deposit the character */
if(i < capacity - 1) {
p[i++] = ch;
}
} else
p[i++] = ch;
}

if ((count == 0) && (ch == EOF))  /*no characters read: at EOF */
return NULL;
/*Stream not at EOF, a line has been read */
p[i] = '\0';

capacity = safe_realloc(p, count);

printf(capacity);
return p;
}

void *safe_malloc(size_t size) {
void *p;
p = malloc(size);
if (p == NULL) {
fprintf(stderr, "readfile4, error  - out of space!");
exit(EXIT_FAILURE);
} else
return p;
}

void *safe_realloc(void *ptr, size_t size) {
void *p;
p = realloc(ptr, size);
if(p == NULL) {
fprintf(stderr, "readfile4, error - out of space!");
exit(EXIT_FAILURE);
} else
return p;
}```

12. Code:
```while (readLine(fp) != NULL) {
printf("Current line = \"%s\"", line);```
You are still throwing away the return value of readLine().

Code:
```capacity = safe_realloc(p, count);
printf(capacity);```
Ok, I try it a last time: What does safe_realloc() return and is "capacity" the right type for it (and for the first argument of printf())?

Bye, Andreas

Popular pages Recent additions