Witam. Mam do napisania następującą funkcje:
Wczytywanie słownika
struct word_t** read_words(const char* filename, enum error_t* errcode);
Funkcja wczytuje słownik z pliku filename do pamięci oraz informuje kod wywołujący o sukcesie bądź porażce całej operacji, ustawiając kod błędu typu error_t w polu, danym wskaźnikiem errcode. Podanie obu wskaźników jest wymagane. W przypadku porażki funkcja zwraca NULL.
Słownik, dany plikiem o nazwie filename, ma mieć strukturę tekstową, gdzie w każdym poprawnym wierszu ma znajdować się para słów: słowo polskie oraz jego angielski odpowiednik, rozdzielone spacją. Przykład:
zdanie sentence⏎
wielki great⏎
myslec think⏎
w_lewo left⏎
⏎
Słowo w tym zadaniu jest zdefiniowane jako nierozłączny ciąg znaków niebiałych (ang. non-white space). Proszę zwrócić uwagę, iż polskie słowa zapisane są całkowicie w formie łacińskiej, bez znaków narodowych typu ąęćńź, itp. Słowa mogą zawierać podkreślnik, np. w_lewo. Plik nie będzie zawierał uszkodzonych danych. Może jednak zawierać pustą linię na końcu.
Wartość zwracana
Funkcja zwraca:
- NULL w przypadku porażki (plus kod błędu w *errcode) lub
- wskaźnik do tablicy wskaźników do struktur word_t, reprezentujących pary słów PL-EN (plus kod błędu ERROR_OK w *errcode).
- Wskaźnik errcode jest wymagany; jego brak ma natychmiast kończyć funkcję z wartością NULL.
Struktura word_t ma mieć następującą postać:
struct word_t {
char* text_pl;
char* text_en;
};
Tablica wskaźników do struktur word_t ma być zakończona dodatkowym elementem - terminatorem w postaci wartości NULL.
Kody błędów
Funkcja określa status przeprowadzonej operacji wczytywania za pomocą stałych typu wyliczeniowego error_t. Typ należy sformułować następująco:
enum error_t{
ERROR_OK,
ERROR_INCORRECT_PARAMETERS,
ERROR_FILE_IO,
ERROR_MEMORY
};
- W przypadku sukcesu funkcja zwraca odpowiedni wskaźnik oraz ustawia kod błędu ERROR_OK.
- W przypadku przekazania niepoprawnych parametrów funkcja ustawia kod błędu ERROR_INCORRECT_PARAMETERS. Zwróć uwagę, że nie jest to możliwe w przypadku problemów z argumentem errcode.
- W przpadku wszelkich problemów z operacjami wejścia/wyjścia, formatem słownika itp., funkcja ustawia kod błędu ERROR_FILE_IO.
- W przypadku braku pamięci funkcja ustawia ERROR_MEMORY.
Wymagania pamięciowe
Funkcja nie może zaalokować więcej pamięci niż jest to niezbędne do posiadania w pamięci słownika, wczytanego z pliku.
Przykład wywołania
Słownik:
zdanie sentence⏎
wielki great⏎
myslec think⏎
Mój kod wygląda następująco:
#include "translator.h"
#include <stdlib.h>
#include <stdio.h>
void delete_words(struct word_t** tab){
if(tab==NULL||*tab==NULL) return;
struct word_t *translator = *tab;
int count=0;
while((translator+count)->text_pl!=NULL){
free((translator+count)->text_pl);
free((translator+count)->text_en);
count++;
}
free(translator);
free(tab);
tab=NULL;
}
struct word_t **read_words(const char *filename, enum error_t *errcode) {
if (filename == NULL || errcode == NULL) {
if (errcode != NULL)
*errcode = ERROR_INCORRECT_PARAMETERS;
return NULL;
}
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
*errcode = ERROR_FILE_IO;
return NULL;
}
char c;
int count = 0;
while (feof(fp) == 0) {
if (fscanf(fp, "%c", &c) != 1&&feof(fp) == 0) {
*errcode = ERROR_FILE_IO;
fclose(fp);
return NULL;
}
if (c == '\n')
count++;
}
fseek(fp, -3, SEEK_END);
fscanf(fp, "%c", &c);
if (c == '\n')
count--;
fseek(fp, SEEK_SET, 0);
struct word_t **translator=NULL;
translator=(struct word_t **) calloc(1, sizeof(struct word_t*));
if (translator == NULL) {
fclose(fp);
*errcode = ERROR_MEMORY;
return NULL;
}
*translator = (struct word_t *) calloc(count, sizeof(struct word_t));
if (*translator == NULL) {
fclose(fp);
free(translator);
*errcode = ERROR_MEMORY;
return NULL;
}
int count_2 = 0, w_pl, w_ang, place=0;
while (count_2 < count-1) {
c = 'a';
w_pl = 0;
w_ang = 0;
//polskie
while (c != ' ') {
if (fscanf(fp, "%c", &c) != 1) {
*errcode = ERROR_FILE_IO;
fclose(fp);
delete_words(translator);
return NULL;
}
w_pl++;
}
//angielskie
while (c != '\n') {
if (fscanf(fp, "%c", &c) != 1) {
*errcode = ERROR_FILE_IO;
fclose(fp);
delete_words(translator);
return NULL;
}
w_ang++;//zawsze o jeden wiecej liczy niz jest liter w słowie
}
(*translator+count_2)->text_pl = (char *) calloc(w_pl - 1, sizeof(char));
if ((*translator+count_2)->text_pl == NULL) {
fclose(fp);
delete_words(translator);
*errcode = ERROR_MEMORY;
return NULL;
}
(*translator+count_2)->text_en = (char *) calloc(w_ang - 1, sizeof(char));
if ((*translator+count_2)->text_en == NULL) {
fclose(fp);
delete_words(translator);
*errcode = ERROR_MEMORY;
return NULL;
}
place=w_ang+w_pl;
fseek(fp,-place-1, SEEK_CUR);
for(int i=0; i<w_pl-1; i++)
fscanf(fp, "%c", (*translator+count_2)->text_pl+i);
fscanf(fp, "%c", &c);
for(int i=0; i<w_ang-1; i++)
fscanf(fp, "%c", (*translator+count_2)->text_en+i);
fscanf(fp, "%c", &c);
count_2++;
}
*errcode = ERROR_OK;
return translator;
}
char** translate_words( struct word_t** tab, int n, ...){
return NULL;
}
Napotykam problem ze zwracana wartością przez fscanf w tym miejscu:
while (c != ' ') {
if (fscanf(fp, "%c", &c) != 1) {
*errcode = ERROR_FILE_IO;
fclose(fp);
delete_words(translator);
return NULL;
}
w_pl++;
}
Napisana przeze mnie funkcja jest sprawdzana przez testy automatyczne. Fscanf zwraca wartość różną od 1 dla poprawnego pliku tekstowego podanego w testach, natomiast gdy przekopiuje jego zawartość do pliku tekstowego o innej nazwie to funkcja działa już prawidłowo. Nie wiem czym może być to spowodowane, że mimo tej samej zawartości pliku (a tylko innej nazwie) funkcja fscanf zwraca różne wartości.
Byłabym wdzięczna za wszelkie wskazówki. Z góry dziękuję.