I have written a program that replaces a given c-string with another c-string. My code works well with small files but takes too much time while working with large files (50 Megabytes and larger).
Also, there's a fast_strncat()
function which is much much faster than strcat()
function.
Please don't get offended for replacing benzene with phenol, it's just a test case.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fast_strncat(char *dest, const char *src, size_t *size)
{
if (dest && src && size)
while ((dest[*size] = *src++))
*size += 1;
}
void strreplace(char **str, const char *old, const char *new_)
{
size_t i, count_old = 0, len_o = strlen(old), len_n = strlen(new_);
const char *temp = (const char *)(*str);
for (i = 0; temp[i] != '\0'; ++i)
{
if (strstr((const char *)&temp[i], old) == &temp[i])
{
count_old++;
i += len_o - 1;
}
}
char *buff = calloc((i + count_old * (len_n - len_o) + 1), sizeof(char));
if (!buff)
{
perror("bad allocation\n");
exit(EXIT_FAILURE);
}
i = 0;
while (*temp)
{
if (strstr(temp, old) == temp)
{
size_t x = 0;
fast_strncat(&buff[i], new_, &x);
i += len_n;
temp += len_o;
}
else
buff[i++] = *temp++;
}
free(*str);
*str = calloc(i + 1, sizeof(char));
if (!(*str))
{
perror("bad allocation\n");
exit(EXIT_FAILURE);
}
i = 0;
fast_strncat(*str, (const char *)buff, &i);
free(buff);
}
int main(void)
{
FILE *fptr = fopen("./benzene.txt", "rb");
if (fptr)
{
fseek(fptr, 0, SEEK_END);
size_t len = ftell(fptr);
fseek(fptr, 0, SEEK_SET);
char *data = calloc(len + 1, sizeof(char));
if (!data)
{
perror("bad allocation\n");
return EXIT_FAILURE;
}
fread(data, sizeof(char), len, fptr);
fclose(fptr);
strreplace(&data, "Benzene", "phenol");
fptr = fopen("./phenol.txt", "wb");
if (!fptr)
{
perror("file not saved.\n");
free(data);
return EXIT_FAILURE;
}
fwrite(data, sizeof(char), strlen((const char *)data), fptr);
fclose(fptr);
free(data);
return EXIT_SUCCESS;
}
perror("file not opened.\n");
return EXIT_FAILURE;
}
I compiled the above program using the command:
gcc -Wall -Wextra main.c -o main
I ran the program for a 50 Megabytes file on zsh on Intel i5-7200U:
./main 29.09s user 0.14s system 97% cpu 30.033 total