Re: Memory Allocation Problem, please help
- From: Barry Schwarz <schwarzb@xxxxxxxxx>
- Date: Sat, 12 May 2007 16:51:12 -0700
On 12 May 2007 10:09:25 -0700, "weidongtom@xxxxxxxxx"
<weidongtom@xxxxxxxxx> wrote:
snip 150 obsolete lines
Thanks for the advice, which has been the most helpful, and I've
finally got my modified code running. (see code that follows) I am
If you are going to post a completely new program, there is no need to
quote 150 lines of obsolete and irrelevant code.
snip questions about old code
/* Entropy, a program to calculate the entropy of a file with the
formula:
----
H(S) = \ (P )*log ( 1/(P ))
/ i 2 i
----
i
Even in a monospaced font, this didn't come out right.
i.e. H(S) = sum of P[i]*log(base=2, 1/P[i]) for i in 0 to
sizeof(S)
build with -lm
*/
#define INC_SIZE 3 /* number of elements the arrays should
increase.*/
#define MAX_CHAR_LINE 400 /* Maximum number of char in one line */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* this can be made to a structure.*/
typedef struct word_tag{
char *word;
int count;
}word;
/* This time, I use a struct, instead of separate arrays. */
struct{
word *words;
int used;
int total;
It doesn't hurt to place these variables inside this struct but it
doesn't buy you anything either. In this program, the only effect is
to increase the typing load.
}array;
Using words which have a common and intuitive meaning in a completely
different way only leads to confusion. array is not an array. It is
a single instance of an anonymous (having no tag) struct.
static int total_word_count;
static double log_base_2(double i);
static double entropy(double probability, int total_occurance);
static void init_arrays();
If the function takes no arguments, then specify it as such:
static void init_arrays(void);
static void increase_arrays();
static int word_index(const char *word);
static void add_word(const char *word);
/* calculate the logarithm of i to the base of 2.
* log2() maybe used in C99 implementation, but this conforms to C89
standard.*/
static double log_base_2(double i){
return log(i)/log(2);
}
/* calculate the entropy of the one word. */
static double entropy(double probability, int total_occurance){
return total_occurance * probability * log_base_2(1/probability);
}
/* Initialise the arrays words, word_counts, and the variables
array_size
* and total_words.
*/
static void init_arrays(){
int i;
array.words = malloc(sizeof(array)*INC_SIZE);
This is the wrong size. You don't want sizeof(array); you may have
confused yourself into thinking array was the array. You want
sizeof(word). When you are allocating memory and assigning the
address to a pointer, the allocated memory should always have the same
type as what the pointer points to. array.words points to a word.
Therefore, however many objects you are allocating space for will each
have type word and will each occupy sizeof(word) bytes.
Make life easy on yourself. Use the following form for malloc
pointer_name = malloc(object_count * sizeof *pointer_name);
if(!array.words){
fprintf(stderr, "Fatal Error: failed to allocate memory.\n");
exit(1);
This is not portable. Use EXIT_FAILURE instead of 1 to maximize the
number of people here who can help diagnose your code.
}
for(i = 0; i < INC_SIZE; i++){
array.words[i].word = NULL;
array.words[i].count = 0;
}
array.total = INC_SIZE;
array.used = 0;
total_word_count = 0;
}
/* Increases the storage for the arrays words, word_counts
* and adjust related variables
*/
static void increase_arrays(){
int i;
int new_size = array.total + INC_SIZE;
/* an array of pointer to char* with size new_size*/
You don't have, and don't want, and array of pointer to char*. You
have a single pointer to word which points to the first element of a
dynamically allocated array of struct. Did using the variable name
"array" confuse you again?
word *tmp_words = realloc(array.words, sizeof(word)*new_size);
You have it correct here?
if(!tmp_words){
fprintf(stderr, "Fatal Error: failed to allocate memory.\n");
Use a different error message than the one you used for malloc. You
might also include the value of new_size so you get a clue about the
limits of your system.
exit(1);
}
array.words = tmp_words;
You have now successfully expanded your array of struct.
for(i = array.total; i < new_size; i++)
This will loop through each of the new elements of the array.
array.words[i].word = NULL;
Neither one matters but in init_array you went to the trouble to
initialize both members of each struct in the array and here you only
initialize one.
array.total = new_size;
}
/* return the index of word in the array words on success,
* -1 if word does not exist in the array.
*/
static int word_index(const char *word){
int index;
for(index = 0; index < array.used; index++){
if(!strcmp(array.words[index].word, word)) /* matches*/
return index;
}
/* word does not exist */
return -1;
}
/* add word to the array words if it does not exist,
* else words is not modified.
* adjust related the word_counts, and other related
* variables.
*/
static void add_word(const char *word){
int index;
int length;
index = word_index(word);
if(index == -1){
/* word does not exist*/
if(array.used >= array.total)
increase_arrays();
length = strlen(word);
(array.words[array.used]).word=malloc(length+1);
if(array.words[array.used].word){
strcpy(array.words[array.used].word, word);
array.words[array.used].count = 1;
array.used +=1;
}
else{
fprintf(stderr, "Fatal Error:failed to allocate memory.\n");
exit(1);
}
}
else{
/* word exists */
array.words[index].count++;
}
total_word_count++;
}
int main(int argc, char *argv[]){
FILE *infile;
int i = 1;
int trace = 1;
double total_entropy = 0.0f;
if(argc < 2){
argv[1] = "../entropy.c";
If argc is less than 2, argv[1] may not exist. In any event, you
never use the new values of argv[1] or argc (below) so why bother?
argc = 2;
/*
printf("Usage:\n\t%s filename\n", argv[0]);
exit(1);
*/
}
infile = fopen(argv[1], "r");
if(!infile){
fprintf(stderr, "Failed to open file: %s. %s\n", argv[0],
argv[0] is not the name of the file. argv[1] is.
strerror(errno));
fopen() is not required to set errno.
exit(1);
}
init_arrays();
while(!feof(infile)){
This does not do what you want. It will cause you to attempt to
process the last line of the file twice. I'm pretty sure it is an
unintended side effect but the memset below insures that the second
attempt to process the last line recognizes end of string immediately.
char buffer[MAX_CHAR_LINE];
char *c;
char *token;
memset(buffer, 0, MAX_CHAR_LINE);
Why? You immediately fill buffer with data from the file and fgets is
guaranteed to properly terminate the string.
fgets(buffer, MAX_CHAR_LINE, infile);
You should always check the result of file I/O. This is where you
would find out that you are at end of file and there is no more data.
/* replace \n \t with space to work with strtok()*/
while((c = strchr(buffer, '\n')))
*c = ' ';
while((c = strchr(buffer, '\t')))
*c = ' ';
token = strtok(buffer, " ");
while(token){
add_word(token);
token = strtok(NULL, " ");
You could eliminate the two while loops above by using " \n\t" as your
token string instead of " ".
}
}
fclose(infile);
for(i = 0; i < array.used; i++){
double itsEntropy, probability;
probability = (double)array.words[i].count / total_word_count;
itsEntropy = entropy(probability, array.words[i].count);
if(trace)
printf("%50s %10f\n", array.words[i].word, itsEntropy);
Since your variables are doubles, you might as well use %lf and take
advantage of the extra precision.
total_entropy += itsEntropy;
}
printf("total entropy: %f\n", total_entropy);
return 0;
}
Remove del for email
.
- References:
- Memory Allocation Problem, please help
- From: weidongtom@xxxxxxxxx
- Re: Memory Allocation Problem, please help
- From: Ben Bacarisse
- Re: Memory Allocation Problem, please help
- From: weidongtom@xxxxxxxxx
- Memory Allocation Problem, please help
- Prev by Date: Re: Where to find the exact requirement of the operand for C operators?
- Next by Date: Problem Reading Bmp's ..
- Previous by thread: Re: Memory Allocation Problem, please help
- Next by thread: Re: Memory Allocation Problem, please help
- Index(es):
Relevant Pages
|