I'm working on image convolution for a 416 * 416 color image with a 3 * 3 * 3 * 16 kernal weights (where kernal width - 3, kernal height - 3, filter channels - 3, number of filters - 16). I'm trying to do this in C, but first I need to read the image from the text file and store it in the memory before working with the convolution function. But I think it seems that C doesn't allow me to write 416 * 416 * 3 size string values into an array. I'm actually a newbie to C, so I'm trying to figure out what would be the best approach I should obey in this ?
Below you can see the code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char line[255];
int fileSize = 416 * 416 * 3;
char image[416 * 416 * 3][255];
FILE *fpointer_1 = fopen("dog_text_image.txt", "r");
for (int i = 0; i < fileSize; i++)
{
fgets(line, 255, fpointer_1);
strcpy(image[i], line);
};
fclose(fpointer_1);
printf("1st value : %s\n", image[0]);
printf("2nd value : %s\n", image[1]);
printf("3rd value : %s\n", image[3]);
return 0;
}
You can alternatively use pointer to array (instead of pointer to pointer) to allocate the entire matrix with a single malloc, and deallocate it with a single free:
#include <stdio.h>
#include <stdlib.h>
int main()
{
/*Pointer to array of length 255*/
char (*image)[255];
/*One malloc to allocate memory*/
if(!(image = malloc(416 * 416 * 3 * sizeof *image))){
perror("Bad allocation!");
return EXIT_FAILURE;
}
/* Do stuff with the matrix*/
image[400][100] = 'a';
/*One free to deallocate memory*/
if(image){
free(image);
}
return 0;
}
It's likely you are getting a stack overflow, try allocating the memory to the heap, something like replacing
char image[416 * 416 * 3][255];
with
//...
char **image;
if(!(image = malloc((fileSize) * sizeof(*image)))){
perror("Bad allocation!");
return EXIT_FAILURE;
}
for(int i = 0; i < fileSize; i++) {
if(!(image[i] = malloc(255))){
perror("Bad allcation!");
return EXIT_FAILURE;
}
}
//...
To free the memory it's the other way around:
for (int i = 0; i < fileSize; i++){
if(image[i])
free(image[i]);
}
if(image)
free(image);
Also, in the code
//...
fgets(line, 255, fpointer_1);
strcpy(image[i], line;
//...
strcpy is really unnecessary you can read directly to image[i] in fgets.
It's possible you can solve the issue with the help of #CraigEstey's comments, try that first.
Related
Hey I'm trying to copy an array of SDL_Color created from an image in another one. But for some images, I get :
Process finished with exit code -1073741819 (0xC0000005)
It happens for an image of 20 x 20 pixels but it works well for a 50 x 50 one...
here is my code :
FILE *debugFile = fopen("C:\\Users\\Clement\\Documents\\coding\\ImageOfCLife\\debug.txt", "w+");
int imgWidth, imgHeight, channels;
unsigned char *img = stbi_load("C:\\Users\\Clement\\Documents\\coding\\ImageOfCLife\\star.jpg", &imgWidth,
&imgHeight, &channels, 0);
fprintf(debugFile, "Loaded image with a width of %dpx, a imgHeight of %dpx and %d channels\n", imgWidth, imgHeight, channels);
dRulesLen = sizeof(deathRules);
bRulesLen = sizeof(birthRules);
if (img == NULL) {
fprintf(debugFile, "Error in loading the image\n");
exit(3);
}
int ch, pix;
SDL_Color **stateMatrix1 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix1 == NULL) {
fprintf(debugFile,"Unable to allocate memory\n");
exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
stateMatrix1[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}
for (ch = 0; ch < imgHeight; ch++) {
printf("{");
for (pix = 0; pix < imgWidth; pix++) {
unsigned bytePerSDL_Color = channels;
unsigned char *SDL_ColorOffset = img + (pix + imgHeight * ch) * bytePerSDL_Color;
SDL_Color p = initSDL_Color(SDL_ColorOffset);
stateMatrix1[ch][pix] = p;
printSDL_Color(p);
printf(", ");
}
printf("}\n");
}
SDL_Color stateMatrix2[imgHeight][imgWidth];
memcpy(stateMatrix2, stateMatrix1, imgWidth*imgHeight*sizeof(SDL_Color));
the last line is the problem according to the debugger
I tried
memcpy(stateMatrix2, stateMatrix1, sizeof(stateMatrix2))
too but I get the same result.
I work on windows 10 with minGW and Clion. I hope you can help me with this issue.
I also tried to replace SDL_Color stateMatrix2[imgHeight][imgWidth]; by :
SDL_Color **stateMatrix2 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix2 == NULL) {
fprintf(debugFile,"Unable to allocate memory\n");
exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
stateMatrix2[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}
but i got the same issue.
I forgot to say it but I want ant to be able to use both stateMatrix as parameter of a function.
To fix it I used the Olaf solution explained below :
I kept :
SDL_Color **stateMatrix1 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix1 == NULL) {
fprintf(debugFile,"Unable to allocate memory\n");
exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
stateMatrix1[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}
to allocate memory to both matrix and used :
for (int i = 0; i < imgHeight; ++i) {
memcpy(stateMatrix2[i], stateMatrix1[i], imgWidth * sizeof(SDL_Color));
}
to perform the copy.
I also verified that the two matrix were'nt linked and there were no problem.
When copying
memcpy(stateMatrix2, stateMatrix1, imgWidth * imgHeight * sizeof(SDL_Color));
you will go beyond the end of stateMatrix1, which is not imgWidth * imgHeight * sizeof(SDL_Color), but imgHeight * sizeof(SDL_Color*).
Copying in a loop from stateMatrix1 to stateMatrix2 is one way to solve this
for (int i = 0; i < imgHeight; ++i) {
memcpy(stateMatrix2[i], stateMatrix1[i], imgWidth * sizeof(SDL_Color));
}
Another would be making both matrices the same type. But when allocating stateMatrix2 as
SDL_Color **stateMatrix2 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
and later use the same memcpy as above, you will still go beyond stateMatrix1 and now also beyond the end of stateMatrix2.
The correct way to copy (but still wrong for another reason) would be
memcpy(stateMatrix2, stateMatrix1, sizeof(*stateMatrix1));
This is correct in terms of size, but still wrong, because it copies the pointers of stateMatrix1 to stateMatrix2. This has two effects
When you initialized stateMatrix2 with its own pointers, there will be memory leaks.
Now both matrices point to the same memory, which means changing one, will change the other too.
Your error is explained in comments. You could fix it by allocating a contiguous block of memory for your matrix instead of many blocks as you did. This way of doing is even simpler, for allocation, deallocation and copy (since you can then use a single call to memcpy) :
#include <stdio.h>
#include <stdlib.h>
struct SDL_Color {
unsigned char rgba[4];
};
int main() {
int ch, pix;
int imgWidth = 100;
int imgHeight = 100;
struct SDL_Color (*stateMatrix1)[imgWidth][imgHeight] = malloc(sizeof(*stateMatrix1));
if (*stateMatrix1 == NULL) {
printf("Unable to allocate memory\n");
} else {
free(*stateMatrix1);
printf("Success\n");
}
return 0;
}
You just need to take care of dereferencing the pointer to the matrix each time you use it.
it's my first post so I apologize in advance if I've posted the code format wrong.
I've been trying to work out where I'm going wrong here for awhile now and haven't been able to find an answer. I keep getting a segmentation fault after two Lines of a text file have been scanned into my arrays. Text file follows the pattern of : City1 City2 distance.
I feel like it has something to do with the memory but I can't understand why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //Chosen to use this library to break text file down.
#include "list.h" //Using file created in lab 3 earlier this year.
#define DYNAMIC_RESIZE 0 ///Might not be needed...
#define Max_Lines 40
#define LINE_SIZE 150
int main()
{
FILE *Distances_File = fopen("Distances.txt", "r");
char *City1[Max_Lines];
char *City2[Max_Lines];
int *Distances[Max_Lines];
City1[Max_Lines] = malloc(sizeof(Max_Lines));
City2[Max_Lines] = malloc(sizeof(Max_Lines));
Distances[Max_Lines] = malloc(sizeof(Max_Lines));
char File_Line[LINE_SIZE];
int Line_Count = 0;
if (!Distances_File) {
printf("File could not open");
return 1;
}
if ( Distances_File != NULL )
{
///Intro to the program.
printf("This is a program that will calculate the shortest distance between selected \ncities.");
printf("\nSo wish me luck :(\n \n");
while(fgets(File_Line, sizeof(File_Line), Distances_File))
{
//printf("%s", File_Line);
sscanf(File_Line, "%s%s%s", City1[Line_Count], City2[Line_Count], Distances[Line_Count]);
///Still issue of Distances being a char.
printf("%s\n%s\n%s\n\n", City1[Line_Count], City2[Line_Count], Distances[Line_Count]);
Line_Count++;
printf("%d", Line_Count);
}
}
}
This statement
char *City1[Max_Lines];
declare an array of char pointers and the size of the array is Max_Lines.
And here you are allocating memory to an invalid index of the array:
City1[Max_Lines] = malloc(sizeof(Max_Lines));
Max_Lines value is 40, so the valid index of the array of size Max_Lines will be 0-39.
You need to allocate memory to all the pointers of array City1 and City2 before using them.
May you write a function to perform this allocation, like this:
void allocate_city_mem(char *arr[], size_t sz) {
for(size_t i = 0; i < sz; i++) {
arr[i] = malloc(LINE_SIZE);
if (NULL == arr[i])
exit(EXIT_FAILURE);
}
}
In doing so, you need to make sure to free the dynamically allocated memory once you have done with it. You can do:
void free_city_mem(char *arr[], size_t sz) {
for(size_t i = 0; i < sz; i++) {
free(arr[i]);
arr[i] = NULL;
}
}
In your program, I can see that the Max_Lines and LINE_SIZE are small values, so as an alternative you can do this:
char City1[Max_Lines][LINE_SIZE];
With this, you don't need to take care of any allocation/deallocation of memory.
Also, no need to take the array of integer pointer for storing distance. Distances could be an array of integers.
In your code, you are calling fopen() and checking the return value of it (if (!Distances_File) {....) somewhere below in the code after calling malloc. As a good programming practice, you should immediately check the return value of library function in such cases because if they fail, there is no point in proceeding further.
Also, when using scanf family functions, make sure that format specifier corresponding to the parameter passed should be correct.
Collectively all above points, the main() will be something like this:
int main() {
FILE *Distances_File = fopen("Distances.txt", "r");
if (!Distances_File) {
printf("File could not open");
return 1;
}
char City1[Max_Lines][LINE_SIZE];
char City2[Max_Lines][LINE_SIZE];
int Distances[Max_Lines];
char File_Line[LINE_SIZE];
int Line_Count = 0;
//Intro to the program.
printf("This is a program that will calculate the shortest distance between selected \ncities.");
printf("\nSo wish me luck :(\n \n");
while(fgets(File_Line, sizeof(File_Line), Distances_File)) {
printf("Line number : %d\n", Line_Count+1);
//printf("%s", File_Line);
sscanf(File_Line, "%s%s%d", City1[Line_Count], City2[Line_Count], &Distances[Line_Count]);
///Still issue of Distances being a char.
printf("%s\n%s\n%d\n\n", City1[Line_Count], City2[Line_Count], Distances[Line_Count]);
Line_Count++;
}
return 0;
}
You have undefined behavior accessing City1[Max_Lines] where the size of the array is Max_Lines. You should change it instead allocate memory and make those pointers point to it. So you will do something like this:-
#define MAXLEN 100
...
for(size_y i = 0; i < Max_Lines; i++){
City1[i] = malloc(MAXLEN);
/* check malloc return value */
}
And also here you can simply do this too,
char City1[Max_Lines][MAXLEN];
Because here if you want to get MAXLEN byte buffer then instead of dynamic allocation you can do this. The only problem is that if Max_lines and MAXLEN is larger then there is a possibilty of constrained by stack size. Then dynamic allocation will be a rescue.
Also you should check the return value fopen. There are cases when fopen fails. You need to handle those cases separately.
try below variant:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //Chosen to use this library to break text file down.
//#include "list.h" //Using file created in lab 3 earlier this year.
#define DYNAMIC_RESIZE 0 ///Might not be needed...
#define Max_Lines 40
#define LINE_SIZE 150
typedef struct {
char data[LINE_SIZE];
} LineBuffer;
int main()
{
FILE *Distances_File = fopen("Distances.txt", "r");
LineBuffer *City1;
LineBuffer *City2;
int *Distances;
char File_Line[LINE_SIZE];
int Line_Count = 0;
City1 = (LineBuffer *)malloc(sizeof(LineBuffer)*Max_Lines);
City2 = (LineBuffer *)malloc(sizeof(LineBuffer)*Max_Lines);
Distances = (int *)malloc(Max_Lines);
if (!Distances_File) {
printf("File could not open");
return 1;
}
if ( Distances_File != NULL ) {
///Intro to the program.
printf("This is a program that will calculate the shortest distance between selected \ncities.");
printf("\nSo wish me luck :(\n \n");
while(fgets(File_Line, sizeof(File_Line), Distances_File) && Line_Count < Max_Lines)
{
//printf("%s", File_Line);
sscanf(File_Line, "%s%s%d", City1[Line_Count], City2[Line_Count], Distances[Line_Count]);
///Still issue of Distances being a char.
printf("%s\n%s\n%d\n\n", City1[Line_Count], City2[Line_Count], Distances[Line_Count]);
Line_Count++;
printf("%d", Line_Count);
}
}
free(City1);
free(City2);
free(Distances);
}
edit
sizeof(int) should be 4 bytes so malloc(sizeof(Max_Lines)) will allocate 4 bytes
I encountered a problem which after expanding memory with realloc(), Segmentation fault reached when it try to reach specific memory number. 135,126th char address to be exact.
But, that mark never a problem if I allocate memory with malloc() bigger in the first place.
Here is my experiment with C that run on linux AMD64 compiled with gcc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SECT_SIZE 25
#define SECT_EXTEND_SIZE 100
#define MAX_SECT_TEST 18000
void extend_memory(char *c_memory, int *i_current_sect_size){
char *c_temp = realloc(c_memory, sizeof(char) * SECT_SIZE * (*i_current_sect_size + SECT_EXTEND_SIZE));
if(c_temp == NULL){
printf("realloc failed upon %d + %d\n", *i_current_sect_size, SECT_EXTEND_SIZE);
exit(EXIT_FAILURE);
}
else{
c_memory = c_temp;
*i_current_sect_size += SECT_EXTEND_SIZE;
printf("realloc success\n");
}
}
int main(int argc, char *argv[]){
//INITIALIZATION
int i_current_sect_size;
char *c_memory = (char *) malloc( sizeof(char) * SECT_SIZE * SECT_EXTEND_SIZE);
if(c_memory == NULL){
printf("c_memory malloc failed\n");
exit(EXIT_FAILURE);
}
else
i_current_sect_size = SECT_EXTEND_SIZE;
memcpy(c_memory, "123456789012345", SECT_SIZE); //fill up 0th sector.
//INITIALIZATION FINISHED
for(int a = 0; a < MAX_SECT_TEST; a++){ //fill dummy data foreach sectors
if(a + 1 == i_current_sect_size)
extend_memory(c_memory, &i_current_sect_size);
memcpy(&c_memory[SECT_SIZE * a], &c_memory[SECT_SIZE * (a+1)], SECT_SIZE);
printf("success %d\n", a);
}
return EXIT_SUCCESS;
}
In simple words, this program would repeatedly copy previous SECT value into next SECT as counter a increase. Upon reaching maximum allocated address, it would expand memory allocation using realloc() by SECT_EXTEND_SIZE and continue doing its job. This process done when MAX_SECT_TEST reached.
I ran the program with SECT_SIZE equal to 9, 16, 25; All variations seems to fall into Segmentation Fault as it try to copy into SECT 15015, 8446, 5405 respectively.
9 x 15015 = 135,135
16 x 8446 = 135,136
25 x 5405 = 135,125
Why (135,125-135,136)th char become a limit?
I have a 8GB memory by the way. I'm pretty sure the actual limit should way bigger than that.
void extend_memory(char *c_memory, int *i_current_sect_size){
...
c_memory = c_temp;
is effectively a noop and caller will not see the changed c_memory.
You will need to use an argument like char **c_memory and work with *c_memory within the function.
If you want a function to update a pointer value, you must pass a pointer to the pointer:
extend_memory(&c_memory, &i_current_sect_size);
and update your function as
void extend_memory(char **c_memory, int *i_current_sect_size){
...
char *c_temp = realloc(*c_memory, sizeof(char) * SECT_SIZE * (*i_current_sect_size + SECT_EXTEND_SIZE));
...
*c_memory = c_temp;
I am trying to realloc an array of structs when it runs out of space as I'm putting elements into it but I keep receiving a realloc stderr. The array of struct will eventually have 235,000 elements in it. When I set the initial start size to 100,000 I receive the stderr when trying to realloc. If I se the initial start size to 300,000 it does not give the error because it never reaches the realloc statement.
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#define BUFFERLEN 200
#define START_SIZE 100000
#define GROW 1000
#define TRUE 1
#define FALSE 0
typedef struct{
char *forw;
char *back;
} word;
typedef struct{
char *entry;
} single_words;
FILE *words;
/*-------------Function Prototypes------------*/
void reverse(char* string, char* revstr, int len);
int search_struct(char* find, word* words, int length);
int compare(const void* eventa, const void* eventb);
int length(char* string);
int main(void)
{
char *buffer;
int letter_index[26];
char alpha[] = "abcdefghijklmnopqrstuvwxyz";
int i=0, found = FALSE, strlen=0, letter=0;
word *word_storage;
single_words *output_storage;
int num_words = 0, size = 0;
int num_output = 0, output_size = 0;
/*buffer for the input strings of the words in the input file*/
buffer = (char*) malloc (sizeof(char)*BUFFERLEN);
if(!buffer){
fprintf(stderr, "Error in buffer string mem alloc\n");
exit(1);
}
/*Initializing the array of structs to store the forward and reverse of each word*/
word_storage = (word*) malloc (sizeof(word)*START_SIZE);
if(!word_storage){
fprintf(stderr, "Error in word_storage string mem alloc\n");
exit(1);
}
size = START_SIZE;
/*Initializing the array of structs for the output*/
output_storage = (single_words*) malloc (sizeof(single_words)*START_SIZE);
if(!output_storage){
fprintf(stderr, "Error in output_storage mem alloc\n");
exit(1);
}
output_size = START_SIZE;
/*Set the letter index 0(which is a) to the first character*/
letter_index[0] = 0;
words = fopen("words", "r");
/*Read the words(forward and reverse) in from stdin into the word_storage*/
while(fgets(buffer, BUFFERLEN, words) != NULL){
buffer = strtok(buffer, "\n");
strlen = length(buffer);
if (num_words < size){
/*Allocate memory for the forward and reverse strings*/
word_storage[num_words].forw = (char *) malloc (sizeof(char) * strlen);
if(!word_storage[num_words].forw){
free(word_storage[num_words].forw);
fprintf(stderr, "word_storage forward string malloc was unsuccessful");
exit(1);
}
word_storage[num_words].back = (char *) malloc (sizeof(char) * strlen);
if(!word_storage[num_words].back){
free(word_storage[num_words].back);
fprintf(stderr, "word_storage forward string malloc was unsuccessful");
exit(1);;
}
/*Store the forward and reverse in the strings*/
strncpy(word_storage[num_words].forw, buffer, strlen);
reverse(word_storage[num_words].forw, word_storage[num_words].back, strlen);
printf("%d: %s %s\n", num_words, word_storage[num_words].forw, word_storage[num_words].back);
/*Increment the letter if it changes*/
if(word_storage[num_words].forw[0] != alpha[letter]){
letter++;
letter_index[letter] = num_words + 1;
}
num_words++;
}
else{
/*Increase the size of word_storage*/
word_storage = (word*) realloc (word_storage, sizeof(word) * size * GROW);
if(!word_storage){
free(word_storage);
fprintf(stderr, "Error in word_storage realloc string mem realloc\n");
exit(1);
}
size = size * GROW;
}
}
return 0;
}
The realloc error occurs here:
word_storage = (word*) realloc (word_storage, sizeof(word) * size * GROW);
if(!word_storage){
free(word_storage);
fprintf(stderr, "Error in word_storage realloc string mem realloc\n");
exit(1);
}
size = size * GROW;
So, you initially set size to START_SIZE, which is 100,000. Then when you use that up, you try to allocate sizeof(word) * size * GROW bytes. sizeof(word) is presumably 16 bytes; we know that size is 100000, and GROW is 1000. So that works out to enough space for 100,000,000 entries, of which you say you will use 235,000. That seems like the allocation is a bit on the generous side.
The total space for 100,000,000 entries is 1,600,000,000 bytes. That seems like a lot, although these days many desktop machines could handle that. But it doesn't seem too surprising that realloc fails.
Perhaps you should make GROW something more reasonable, like 2.
By the way, once you've established that word_storage is NULL, there is no point in calling free(word_storage). It does no harm, since free(NULL) is a no-op, but it also does no good for the same reason.
You are multiplying the size by 1000 which is too much (highly exponential growth 1 -> 1000 -> 1000 000 -> 1000 000 000 ...), and you are not displaying the errno. I suggest instead
size_t newsize = 3*size/2 + 1000;
word_storage = realloc(word_storage, sizeof(word)*newsize);
if (!word_storage) {
fprintf(stderr, "Cannot grow storage to %ld size, %s\n",
(long) newsize, strerror(errno));
exit (EXIT_FAILURE);
}
else size = newsize;
then if starting with an initial size of 1000, you are getting the much more reasonable progression 1000 -> 2500 -> 4750 -> 8125 -> 13187 -> 20780 ... and more importantly you are spending at most 50% of useless memory, not a factor of nearly 1000!
I am having trouble with a struct array. I need to read in a text file line by line, and compare the values side by side. For example "Mama" would return 2 ma , 1 am because you have ma- am- ma. I have a struct:
typedef struct{
char first, second;
int count;
} pair;
I need to create an array of structs for the entire string, and then compare those structs. We also were introduced to memory allocation so we have to do it for any size file. That is where my trouble is really coming in. How do I reallocate the memory properly for an array of structs? This is my main as of now (doesn't compile, has errors obviously having trouble with this).
int main(int argc, char *argv[]){
//allocate memory for struct
pair *p = (pair*) malloc(sizeof(pair));
//if memory allocated
if(p != NULL){
//Attempt to open io files
for(int i = 1; i<= argc; i++){
FILE * fileIn = fopen(argv[i],"r");
if(fileIn != NULL){
//Read in file to string
char lineString[137];
while(fgets(lineString,137,fileIn) != NULL){
//Need to reallocate here, sizeof returning error on following line
//having trouble seeing how much memory I need
pair *realloc(pair *p, sizeof(pair)+strlen(linestring));
int structPos = 0;
for(i = 0; i<strlen(lineString)-1; i++){
for(int j = 1; j<strlen(lineSTring);j++){
p[structPos]->first = lineString[i];
p[structPos]->last = lineString[j];
structPos++;
}
}
}
}
}
}
else{
printf("pair pointer length is null\n");
}
}
I am happy to change things around obviously if there is a better method for this. I HAVE to use the above struct, have to have an array of structs, and have to work with memory allocation. Those are the only restrictions.
Allocating memory for an array of struct is as simple as allocating for one struct:
pair *array = malloc(sizeof(pair) * count);
Then you can access each item by subscribing "array":
array[0] => first item
array[1] => second item
etc
Regarding the realloc part, instead of:
pair *realloc(pair *p, sizeof(pair)+strlen(linestring));
(which is not syntactically valid, looks like a mix of realloc function prototype and its invocation at the same time), you should use:
p=realloc(p,[new size]);
In fact, you should use a different variable to store the result of realloc, since in case of memory allocation failure, it would return NULL while still leaving the already allocated memory (and then you would have lost its position in memory). But on most Unix systems, when doing casual processing (not some heavy duty task), reaching the point where malloc/realloc returns NULL is somehow a rare case (you must have exhausted all virtual free memory). Still it's better to write:
pair*newp=realloc(p,[new size]);
if(newp != NULL) p=newp;
else { ... last resort error handling, screaming for help ... }
So if I get this right you're counting how many times pairs of characters occur? Why all the mucking about with nested loops and using that pair struct when you can just keep a frequency table in a 64KB array, which is much simpler and orders of magnitude faster.
Here's roughly what I would do (SPOILER ALERT: especially if this is homework, please don't just copy/paste):
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
void count_frequencies(size_t* freq_tbl, FILE* pFile)
{
int first, second;
first = fgetc(pFile);
while( (second = fgetc(pFile)) != EOF)
{
/* Only consider printable characters */
if(isprint(first) && isprint(second))
++freq_tbl[(first << 8) | second];
/* Proceed to next character */
first = second;
}
}
int main(int argc, char*argv[])
{
size_t* freq_tbl = calloc(1 << 16, sizeof(size_t));;
FILE* pFile;
size_t i;
/* Handle some I/O errors */
if(argc < 2)
{
perror ("No file given");
return EXIT_FAILURE;
}
if(! (pFile = fopen(argv[1],"r")))
{
perror ("Error opening file");
return EXIT_FAILURE;
}
if(feof(pFile))
{
perror ("Empty file");
return EXIT_FAILURE;
}
count_frequencies(freq_tbl, pFile);
/* Print frequencies */
for(i = 0; i <= 0xffff; ++i)
if(freq_tbl[i] > 0)
printf("%c%c : %d\n", (char) (i >> 8), (char) (i & 0xff), freq_tbl[i]);
free(freq_tbl);
return EXIT_SUCCESS;
}
Sorry for the bit operations and hex notation. I just happen to like them in such a context of char tables, but they can be replaced with multiplications and additions, etc for clarity.