#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ctype.h>
#include <wctype.h>
// Structure to represent an object with string, frequency, occurrence, and coordinates
typedef struct {
char String[30];
float frequency;
int occurrence;
int x;
int y;
} object;
// Structure for a matrix containing a list of objects and its dimensions
typedef struct {
object** list;
int* x;
int y;
} matrix;
// Structure to represent an alphabet node
struct Alphabet {
struct Alphabet* subAlphabet[31];
object* word;
};
// Define Dictionary as a pointer to Alphabet struct
typedef struct Alphabet Dictionary;
// Declaration of the recursive deallocation function
Dictionary* deallocation(Dictionary* dict);
// Function to get the ASCII index of a character
int asciiIndex(char character) {
// Maps characters A-Z, a-z, !, ?, ., and ' to ASCII values
if ((character >= 'A' && character <= 'Z')) {
return (int)(character - 'A');
} else if ((character >= 'a' && character <= 'z')) {
return (int)(character - 'a');
} else if (character == '!') {
return 27;
} else if (character == '?') {
return 28;
} else if (character == '.') {
return 29;
} else if (character == ''') {
return 30;
}
return '';
}
// Function to compare two strings
bool compareStrings(char* string1, char* string2) {
// Checks if the two strings are equal, considering case insensitivity
if ((int)*string1 == (int)*string2 || ((int)*string1 + 32) == (int)*string2 || ((int)*string1 - 32) == (int)*string2) {
// Strings are equal or differ only by case
} else {
// Strings are different
return false;
}
// If both strings have reached the end, they are equal
if ((*string1 || *string2) == '') {
return true;
} else {
// Otherwise, compare the next characters recursively
compareStrings((string1 + 1), (string2 + 1));
}
}
// Function for operational search of a string in the matrix
int operationalSearch(char string[], int index, Dictionary* dict, int y, matrix* m) {
// Initialize the current dictionary
Dictionary* currentDict = dict;
int ASCII;
// If the end of the string is reached, compare strings or add the new word
if (string[index] == '') {
printf("%s = %sn", currentDict->word->String, string);
if (compareStrings(currentDict->word->String, string) == 1) {
return currentDict->word->y;
} else {
// Add the new word to the dictionary
strcpy(currentDict->word->String, string);
currentDict->word->y = y;
printf("stored: %sn", currentDict->word->String);
return -1;
}
}
// The word is not present in the matrix, so add it to the dictionary
ASCII = asciiIndex(string[index]);
if (currentDict->subAlphabet[ASCII] == NULL) {
currentDict->subAlphabet[ASCII] = (Dictionary*)calloc(1, sizeof(Dictionary));
if (currentDict->subAlphabet[ASCII] == NULL) {
exit(1);
}
currentDict->subAlphabet[ASCII]->word = (object*)malloc(sizeof(object));
if (currentDict->subAlphabet[ASCII]->word == NULL) {
exit(1);
}
// Initialize the allocated memory to zero
memset(currentDict->subAlphabet[ASCII]->word, 0, sizeof(object));
}
currentDict = currentDict->subAlphabet[ASCII];
return operationalSearch(string, index + 1, currentDict, y, m);
}
// Function to print the string and recursively call itself
void printString(char String[30], matrix m, Dictionary* dict, int y, int generatedWords, int generatedWordCount, FILE* outputFile, int pipe2[], char selectedWord[30]) {
if (generatedWordCount == generatedWords) { // base case
fprintf(outputFile, "n");
return;
}
printf("%sn", String);
fprintf(outputFile, "%s", String);
if (m.list[y][1].frequency == 1.0) {
y = operationalSearch(m.list[y][1].String, 0, dict, y, &m);
} else {
int numElementsRow = m.x[y];
// Iterate through words and select one based on probability
srand(clock()); // use clock ticks as seed for random generator
float randomNum = (float)rand() / RAND_MAX;
for (int i = 1; i < numElementsRow; ++i) {
if (randomNum < m.list[y][i].frequency) {
printf("%s repeatedn", m.list[y][i].String);
y = operationalSearch(m.list[y][i].String, 0, dict, y, &m);
break;
} else {
// Subtract the probability of the current word
randomNum -= m.list[y][i].frequency;
}
}
}
printf("middle: %sn", m.list[y][0].String);
fprintf(outputFile, " ");
return printString(m.list[y][0].String, m, dict, y, generatedWords, generatedWordCount + 1, outputFile, pipe2, selectedWord);
}
// Function to read CSV file and write words to the pipe
void readCSV(FILE* file, int pipe1[]) {
char buffer[31]; // Buffer to read words
char character;
int bytesRead;
while (1) {
bytesRead = fscanf(file, "%30[^,n]", buffer);
if (bytesRead == 1) {
write(pipe1[1], buffer, sizeof(buffer));
} else {
break;
}
printf("%s|", buffer);
character = fgetc(file); // Read the next character
if (character == 'n') {
strcpy(buffer, "n"); // Add a newline to the buffer
printf("%s", buffer);
write(pipe1[1], buffer, sizeof(buffer));
} else if (character == EOF) {
break;
}
}
close(pipe1[1]);
}
// Function to create the matrix and populate it from the pipe data
void createMatrix(matrix* m, int pipe1[], int pipe2[], Dictionary* dict) {
char string1[31];
int* capitalIndexes = NULL;
int capitals = 0;
int columnIndex = 0;
int rowIndex = 0;
capitalIndexes = malloc(sizeof(int));
if (capitalIndexes == NULL) {
perror("Memory allocation error");
exit(EXIT_FAILURE);
}
while (read(pipe1[0], string1, sizeof(string1)) > 0) {
printf("%c", string1[0]);
if (isalpha(string1[0]) || iswalpha(string1[0])) {
if (m->x[m->y - 1] - 1 != 0) { // if the previous string stored in the matrix is the key
m->x[m->y - 1]++;
m->list[m->y - 1] = realloc(m->list[m->y - 1], m->x[m->y - 1] * sizeof(object));
}
strcpy(m->list[m->y - 1][m->x[m->y - 1] - 1].String, string1);
} else if (isdigit(string1[0])) {
m->list[m->y - 1] = realloc(m->list[m->y - 1], m->x[m->y - 1] * sizeof(object));
} else if (string1[0] == 'n') {
m->y++;
m->list = realloc(m->list, m->y * sizeof(object*));
m->x = realloc(m->x, m->y * sizeof(int));
m->list[m->y - 1] = NULL;
m->x[m->y - 1] = 0;
}
}
printf("cnnn");
// Print the matrix
for (int i = 0; i < m->y - 1; i++) {
for (int j = 0; j < m->x[i]; j++) {
if (j == 0) {
printf("%s ", m->list[i][j].String);
} else {
printf(",%s,%.4f ", m->list[i][j].String, m->list[i][j].frequency); // Print the frequency value of the element
}
}
printf("n");
}
close(pipe1[0]);
close(pipe2[1]);
}
// Main function
int main() {
Dictionary* dict = (Dictionary*)calloc(1, sizeof(Dictionary));
dict->word = (object*)malloc(sizeof(object));
FILE *file = fopen("controprova.csv", "r");
if (file == NULL) {
fprintf(stderr, "Error opening file.n");
return 1;
}
FILE *outputFile = fopen("prova1.txt", "w");
char selectedWord[30] = "";
int generatedWords = 30;
int pipe1[2], pipe2[2];
if (pipe(pipe1) == -1 || pipe(pipe2) == -1) {
exit(EXIT_FAILURE);
}
// Initialize the matrix structure
matrix* m = (matrix*)malloc(sizeof(matrix));
m->list = NULL;
m->x = NULL;
m->y = 0;
pid_t pid1, pid2, pid3;
pid1 = fork();
if (pid1 == -1) {
perror("Fork error");
return 1;
} else if (pid1 == 0) {
printf("Process 1: %dnn", getpid());
close(pipe1[0]);
readCSV(file, pipe1);
exit(0);
}
pid2 = fork();
if (pid2 == -1) {
printf("Fork error");
return 1;
} else if (pid2 == 0) {
printf("nnProcess 2: %dnn", getpid());
close(pipe1[1]); // Close pipe1[1] in the child process
close(pipe2[0]);
createMatrix(m, pipe1, pipe2, dict);
exit(0);
}
pid3 = fork();
if (pid3 == -1) {
perror("Fork error");
return 1;
} else if (pid3 == 0) {
printf("nnProcess 3: %dn", getpid());
close(pipe2[1]);
// ... (code for process 3) ...
exit(0);
}
free(m->list);
free(m->x);
free(m);
// Deallocate the dictionary (words and structure)
for (int i = 0; i < 30; i++) {
dict->subAlphabet[i] = deallocation(dict->subAlphabet[i]);
}
free(dict->word);
free(dict);
return 0;
}
// Recursive deallocation function
Dictionary* deallocation(Dictionary* dict) {
if (dict == NULL) {
return NULL;
}
for (int i = 0; i < 30; i++) {
dict->subAlphabet[i] = deallocation(dict->subAlphabet[i]);
}
free(dict->word);
free(dict);
return NULL;
}
I am a beginner in C programming and I am working on a project that involves reading a CSV file, processing its content, and then generating some output. The project involves three processes:
-
The first process reads the CSV file and writes the words to a pipe.
-
The second process reads from the pipe, constructs a matrix structure, and stores the words along with their frequencies.
-
The third process (yet to be implemented) will use the matrix to generate output based on the processed data.
I am facing issues with the synchronization of these processes, particularly with ensuring that the pipes are not closed prematurely, which leads to communication problems between the processes. I need help understanding how to properly manage pipe read/write operations and process synchronization to avoid these issues. Additionally, I need to ensure that the matrix structure is correctly populated and that memory allocation is handled properly.
I have tried implementing three processes to handle reading, processing, and outputting data from a CSV file. Here is what I did:
-
Reading CSV (Process 1): This process reads the CSV file, splits the words, and writes them to a pipe.
-
Constructing the Matrix (Process 2): This process reads the words from the pipe, constructs a matrix structure, and stores the words along with their frequencies.
-
Generating Output (Process 3): This process is yet to be implemented. It is supposed to use the matrix to generate and print the output based on the processed data.
Expected Outcome: I expected the second process to read from the pipe correctly and construct the matrix. Specifically, I expected the matrix to be printed on the screen, showing each word and its corresponding frequency using nested for
loops.
Actual Outcome: The matrix is not being constructed correctly. The processes are facing synchronization issues, likely due to premature closing of the pipes or incorrect handling of read/write operations. This results in incomplete or incorrect data being read and processed, leading to an incorrect or empty matrix being printed.
I need help ensuring proper synchronization between the processes and correct handling of pipe operations to achieve the expected outcome.
input CSV:
.,What,1.0000
What,do,1.0000
do,the,1.0000
the,forecasts,1.0000
forecasts,of,0.6667,weather,0.3333
of,time,1.0000
time,?,0.3333,of,0.3333,uncertain,0.3333
?,Forecasts,1.0000
of,today,0.5000,tomorrow,0.5000
today,time,1.0000
uncertain,!,1.0000
!,Forecasts,1.0000
tomorrow,?,1.0000