I am making a program for the school that must generate 1 million strings all different from each other and whose length varies from 3 to 20 characters, I immediately want to say that I have already finished the program and I have already generated the strings, but I wanted to, as a pastime, optimize it.
I initially conceived it by making a 2d array (array containing char arrays) and it worked but I wanted to make the string checking faster by saving each string in the column equal to its length, for example the string "Ci_3sa" which contains 6 characters is stored in arr[6][0][nOfChars]
and instead a 4 characters long word in arr[4][0][nOfChars]
, I think I explained what I wanted to do .
I do not think I have made reference errors of the type of variables, because when I compile the code I do not get errors or warnings (I have active warnings), but when I execute the code it gives me an error in the dump core, I also tried to run the code in a debugger for C but however I don't understand what the problem is because it seems to work some times and in others it doesn't (but it never finished executing the program).
I would really like to understand what kind of mistake I made.
I assume the error is in the "checkStrings()" function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define N_STRINGS 1000000
#define MIN_CHARS 3
#define MAX_CHARS 20
#define ASCII_START 32 // 32 è lo spazio
#define ASCII_END 126
#define randnum(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))
char *generateRandomString(int size)
{
int i;
// char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
// printf("Dimensione del charset: %ld\n", strlen(charset));
char *res = malloc(size + 1);
for (i = 0; i < size; i++)
{
/*
int key = randnum(0, 69);
res[i] = charset[key];
*/
int key = (rand() % (ASCII_END - ASCII_START)) + ASCII_START;
res[i] = (char)key;
if (key == 92 || key == 32 || key == 34)
i--;
}
res[i] = '\0';
return res;
}
int checkStrings(char *strs[18][N_STRINGS], char *str, int size)
{
for (int i = 0; i < size; i++)
{
/*
printf("Lunghezza stringa\n: %ld", strlen(str));
printf("Vediamo : %s\n", str);
printf("Parola Array in posizione %d: %s\n", i, strs[i]);
printf("Parola Generata: %s\n", str);
*/
if (strcmp(strs[strlen(str) - 3][i], str) == 0)
return 1;
}
return 0;
}
void wirteOutput(char *outputFile, char *strs[18][N_STRINGS], int *ss, int isJson)
{
FILE *output;
if ((output = fopen(outputFile, "w+")) == NULL)
{
printf("errore nell'apertura del file output");
exit(2);
}
if (isJson == 1)
fprintf(output, "[\n"); // inizio array in json
for (int j = 0; j < 18; j++)
{
for (int i = 0; i < ss[j]; i++)
{
if (isJson == 1)
if (i < ss[j] - 1)
fprintf(output, "\"%s\",\n", strs[j][i]);
else
fprintf(output, "\"%s\"\n", strs[j][i]);
else
fprintf(output, "%s\n", strs[j][i]);
// printf("i: %d\n", i);
}
}
if (isJson == 1)
fprintf(output, "]\n"); // fine array in json
fclose(output);
}
int main()
{
// printf("Questo è il char 32: '%c'\n\n", 32);
srand(time(NULL));
// printf("%d\n", randnum(1, 70));
int percentage = 0;
int sizes[18] = {0};
char *strings[18][N_STRINGS];
printf("Starting to generate random strings\n\n");
for (int i = 0; i < N_STRINGS; i++)
{
int n = randnum(MIN_CHARS, MAX_CHARS);
// printf("Numero di lettere estratto: %d\n", n);
char *str = generateRandomString(n);
// printf("Parola generata: %s\n", str);
// sleep(1);
if (checkStrings(strings, str, sizes[strlen(str) - 3]) != 0)
{
// printf("find same word\n");
i--;
}
else
{
strings[strlen(str) - 3][i] = str;
sizes[strlen(str) - 3]++;
}
// if (i >= 10000 && N_STRINGS % i == 0 && ((100 * i) / N_STRINGS) % 10 == 0)
if (i >= (N_STRINGS / 100) && percentage != (100 * i) / N_STRINGS)
{
percentage = (100 * i) / N_STRINGS;
fputs("\033[A\033[2K", stdout);
rewind(stdout);
printf("%d%%\n", percentage); // 1000 : 100 = i : x
}
// printf("Parola assegnata: %s\n", strings[i]);
}
wirteOutput("output2.json", strings, sizes, 1);
wirteOutput("output2.txt", strings, sizes, 0);
printf("End\n");
return 0;
}
EDIT:
This is my test code and @AndreaWenzel i tried your solution but after some attempts it works, but I don't understand how this 3d array should work because according to the logic of this code it should only write the strings that have been generated and instead it writes me in the file 1 or 2 strings and in the other cases (null) even if the code reaches the end by writing "End".
This is the file
(null)
Ji+]
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
//#define N_STRINGS 1000000
#define N_STRINGS 100
#define MIN_CHARS 3
#define MAX_CHARS 20
#define ASCII_START 32 // 32 è lo spazio
#define ASCII_END 126
#define randnum(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))
char *generateRandomString(int size)
{
int i;
// char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
// printf("Dimensione del charset: %ld\n", strlen(charset));
char *res = malloc(size + 1);
for (i = 0; i < size; i++)
{
/*
int key = randnum(0, 69);
res[i] = charset[key];
*/
int key = (rand() % (ASCII_END - ASCII_START)) + ASCII_START;
res[i] = (char)key;
if (key == 92 || key == 32 || key == 34)
i--;
}
res[i] = '\0';
return res;
}
int checkStrings(char *strs[18][N_STRINGS], char *str, int size)
{
for (int i = 0; i < size; i++)
{
printf("Lunghezza stringa: %ld\n", strlen(str));
// sleep(1);
printf("Parola Array in posizione %d: %s\n", i, strs[strlen(str) - 3][i]);
printf("Parola Generata: %s\n", str);
if (strs[strlen(str) - 3][i] != NULL)
if (strcmp(strs[strlen(str) - 3][i], str) == 0)
return 1;
}
return 0;
}
void wirteOutput(char *outputFile, char *strs[18][N_STRINGS], int *ss, int isJson)
{
FILE *output;
if ((output = fopen(outputFile, "w+")) == NULL)
{
printf("errore nell'apertura del file output");
exit(2);
}
if (isJson == 1)
fprintf(output, "[\n"); // inizio array in json
for (int j = 0; j < 18; j++)
{
for (int i = 0; i < ss[j]; i++)
{
if (isJson == 1)
if (i < ss[j] - 1)
fprintf(output, "\"%s\",\n", strs[j][i]);
else
fprintf(output, "\"%s\"\n", strs[j][i]);
else
fprintf(output, "%s\n", strs[j][i]);
// printf("i: %d\n", i);
}
}
if (isJson == 1)
fprintf(output, "]\n"); // fine array in json
fclose(output);
}
int main()
{
// printf("Questo è il char 32: '%c'\n\n", 32);
srand(time(NULL));
// printf("%d\n", randnum(1, 70));
int percentage = 0;
int sizes[18] = {0};
// char *strings[18][N_STRINGS];
char *(*strings)[N_STRINGS];
strings = malloc(18 * sizeof *strings);
if (strings == NULL)
{
fprintf(stderr, "Memory allocation error!\n");
exit(EXIT_FAILURE);
}
printf("Starting to generate random strings\n\n");
for (int i = 0; i < N_STRINGS; i++)
{
int n = randnum(MIN_CHARS, MAX_CHARS);
// printf("Numero di lettere estratto: %d\n", n);
char *str = generateRandomString(n);
// printf("Parola generata: %s\n", str);
// sleep(1);
if (checkStrings(strings, str, sizes[strlen(str) - 3]) != 0)
{
// printf("find same word\n");
i--;
}
else
{
strings[strlen(str) - 3][i] = str;
sizes[strlen(str) - 3]++;
}
// if (i >= 10000 && N_STRINGS % i == 0 && ((100 * i) / N_STRINGS) % 10 == 0)
if (i >= (N_STRINGS / 100) && percentage != (100 * i) / N_STRINGS)
{
percentage = (100 * i) / N_STRINGS;
fputs("\033[A\033[2K", stdout);
rewind(stdout);
printf("%d%%\n", percentage); // 1000 : 100 = i : x
}
// printf("Parola assegnata: %s\n", strings[i]);
}
printf("Ecco quante parole sono state scritte\n");
for (int i = 0; i < 18; i++)
printf("%d\n", sizes[i]);
// wirteOutput("output2.json", strings, sizes, 1);
wirteOutput("output2.txt", strings, sizes, 0);
printf("End\n");
free(strings);
return 0;
}
I fixed the core dump problem, apparently, but the thing that turns my nose up in any case is that, in the test code, cmq when the words are generated and there are no similar ones, it does not assign them because so many times it has happened that was going to check for more than one null value within the same word length section.
This is another test after the changes: (N_STRINGS = 50)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
1/E1-&E/3@K
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
@wLo!>p%QR|+bNUgs
(null)
(null)
(null)
(null)
(null)
(null)
(null)
x>KEeQ&tG[jgT9roWdt
(null)
(null)
(null)
(null)