#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <ctype.h>
#define CHECKERROR(X, Y);
if (!X)
{
perror(Y);
return LOSE;
}
const int LOSE = 0; const int WIN = 1; const char* READFILENAME = "/home/alex/Desktop/Shekspir.txt"; const char* WRITESAVEFILENAME = "/home/alex/Desktop/test.txt"; const char* WRITEALPHABETFILENAME = "/home/alex/Desktop/inalpha.txt"; const char* WRITEENDALPHABETFILENAME = "/home/alex/Desktop/unalpha.txt";
struct String { char* str; int len; }; //========================================================================================= FILE* FileOpen (const char* FileName, const char* mode) { FILE* fp = fopen (FileName, mode); if (!fp) { errno = ENOENT; return NULL; } return fp; } //========================================================================================= int FileLen (FILE* file) { fseek (file, 0, SEEK_END); int len = ftell (file); rewind (file); if (!len) { errno = EPERM; return 0; } return len; } //========================================================================================= char* InputDinamic (const int Size) { if (Size <= 0) { errno = EDOM; return NULL; }
char* arr = (char*) calloc (Size, sizeof (*arr));
if (!arr)
{
errno = ENOMEM;
return NULL;
}
return arr;
}
//========================================================================================= int FindCountStr (char* buffer, int len) { if ((!buffer) || (!len)) { errno = EDOM; return 0; } int CountStr = 0; for (int i = 0; i < len; i++) { if (buffer[i] == '\n') CountStr++; } return CountStr; } //========================================================================================= String* InputDinamicString (const int Size) { if (Size <= 0) { errno = EDOM; return NULL; }
struct String* arr = (String*) calloc (Size, sizeof (*arr));
if (!arr)
{
errno = ENOMEM;
return NULL;
}
return arr;
}
//========================================================================================= bool FillStr (char* Buffer,const int len, String* Str, const int CountStr) { if ((CountStr <= 0) || (!Buffer) || (!Str) || (!len)) { errno = EDOM; return false; }
int NumberStr = 0;
for (int i = 0; i < len; i++)
{
if (i == 0)
{
(Str[NumberStr]).str = Buffer;
NumberStr++;
}
if (Buffer[i] == '\n')
{
Buffer[i] = '\0';
(Str[NumberStr]).str = Buffer + i + 1;
(Str[NumberStr - 1]).len = (Str[NumberStr]).str - (Str[NumberStr - 1]).str;
NumberStr++;
}
if (NumberStr == CountStr)
{
(Str[NumberStr - 1]).len = Buffer + len - (Str[NumberStr - 1]).str;
break;
}
}
return true;
}
//========================================================================================= char* StringArrToBuf (String* Text,const int CountStr, int Size) { for (int i = 0; i < CountStr; i++) if ((Text[i]).len > 1) Size += (Text[i]).len; char arr = (char) calloc (Size, sizeof(arr)); int Num = 0; for (int i = 0; i < CountStr; i++) if ((Text[i]).len > 1) for (int j = 0; j < Text[i].len; j++) { arr[Num] = Text[i].str[j]; Num++; } return arr; } //========================================================================================= bool FileWrite (FILE File, String Text, const int CountStr) { if ((!Text) || (!CountStr)) { errno = EDOM; return false; } int BufLength = 0; char* Buf = StringArrToBuf(Text, CountStr, &BufLength); for (int i = 0; i < BufLength - 1; i++) { if (Buf[i] == '\0') Buf[i] = '\n'; fprintf(File, "%c", Buf[i]); }
return true;
}
//========================================================================================= bool LeadTextToStd (String* Text, const int CountStr) { if ((!Text) || (!CountStr)) { errno = EDOM; return false; } for (int i = 0; i < CountStr; i++) { while (isspace ((Text[i]).str[0]) && ((Text[i]).len > 1)) { (Text[i]).str = &(Text[i]).str[1]; (Text[i]).len--; } while (((Text[i]).len > 1) && (isspace ((Text[i]).str[(Text[i]).len - 2]))) { (Text[i]).str[(Text[i]).len - 2] = '\0'; (Text[i]).len--; } } return true; } //========================================================================================= int FindStartAlpha (String Text) { int Start = -1; if (Text.len <= 1) return Start;
while (Start < Text.len - 1)
{
Start++;
if (isalpha (Text.str[Start]))
return (Start);
}
return -1;
}
//========================================================================================= int Mystrcmp (String Text1, String Text2) { int Start1 = FindStartAlpha (Text1), Start2 = FindStartAlpha (Text2); if ((Start1 < 0) && (Start2 < 0)) return 0; if (Start1 < 0) return -1; if (Start2 < 0) return 1; int i = 0; for (i = 0; tolower (Text1.str[Start1 + i]) == tolower (Text2.str[Start2 + i]); i++) if (Text1.str[Start1 + i] == '\0') return 0; return (tolower (Text1.str[Start1 + i]) - tolower (Text2.str[Start2 + i])); } //========================================================================================= int FindEndAlpha (String Text) { if (Text.len <= 1) return -1;
int End = Text.len;
while (End > 0)
{
End--;
if (isalpha (Text.str[End]))
return (End);
}
return -1;
}
//========================================================================================= int Mystrrewcmp (String Text1, String Text2) { int End1 = FindEndAlpha (Text1), End2 = FindEndAlpha (Text2); if ((End1 < 0) && (End2 < 0)) return 0; if (End1 < 0) return -1; if (End2 < 0) return 1; int i = 0; for (i = 0; tolower (Text1.str[End1 - i]) == tolower (Text2.str[End2 - i]); i++) if (Text1.str[End1 - i] == '\0') return 0; return (tolower (Text1.str[End1 - i]) - tolower (Text2.str[End2 - i])); } //========================================================================================= void Swap (String* s1, String* s2) { String Save = *s1; *s1 = *s2; s2 = Save; } //========================================================================================= bool Sort (String Text, const int CountStr, int (*compare)(String Text1, String Text2)) { if ((!Text) || (!CountStr)) { errno = EDOM; return false; } for (int i = 0; i < CountStr; i++) { for (int j = 0; j < CountStr - i - 1; j++) { if (((Text[j]).len <= 1) || ((compare)(Text[j], Text[j + 1]) > 0)) Swap (&Text[j], &Text[j + 1]); } } return true; } //========================================================================================= bool String_destruct (String This) { if (!This) { errno = EDOM; return false; } (This).str = NULL; (This).len = -1; free ((This).str); return true; } //========================================================================================= bool DeliteArrString (String Arr, const int Size) { if ((!Arr) || (!Size)) { errno = EDOM; return false; } for (int i = 0; i < Size; i++) if (!String_destruct(&Arr[i])) { errno = EDOM; return false; } free (Arr); return true; } //========================================================================================= bool DeliteBuf (char buffer) { if (!buffer) { errno = EDOM; return false; } free (buffer); buffer = NULL; return true; } //========================================================================================= bool String_OK (const String This) { return (!(This) || !((*This).str) || !(This).len > 0); } //========================================================================================= void String_Dump (const String This) { if (String_OK(This)) printf("Struct (Bad) \n" "{This structure is flawed}"); else { printf("Struct (OK) \n" "{\nstr = <"); int MaxLine = 80; if ((*This).len < MaxLine) MaxLine = (*This).len; for (int i = 0; i < MaxLine; i++) printf("%c", (*This).str[i]); printf("> \n"); if ((*This).len > MaxLine) { printf("Not all the characters are derived.\n"); if ((*This).str[MaxLine] != '\0') printf("The string is not over.\n"); } printf("len = %d", (*This).len); } } //========================================================================================= //========================================================================================= int main() { printf ("# "Sort text" v.1.0.0 by Al.Liogky \n");
FILE* fp = FileOpen (READFILENAME, "rb");
CHECKERROR (fp, "Error open file");
int len = FileLen (fp);
CHECKERROR (len, "Error file size");
char* buffer = InputDinamic (len);
CHECKERROR (buffer, "Error initialization buffer");
fread (buffer, len, sizeof (*buffer), fp);
if (ferror (fp))
{
errno = EILSEQ;
perror ("Error reading file");
return LOSE;
}
fclose (fp);
int CountStr = FindCountStr (buffer, len);
struct String* text = InputDinamicString (CountStr);
CHECKERROR (text, "Error initialization struct of pointers")
CHECKERROR (FillStr (buffer, len, text, CountStr), "Error data");
FILE* fs = FileOpen (WRITESAVEFILENAME, "wb");
CHECKERROR (fs, "Error open file");
CHECKERROR (FileWrite (fs, text, CountStr), "Error writinging file");
fclose (fs);
CHECKERROR (LeadTextToStd (text, CountStr), "Error align the text to the standard form")
FILE* fa = FileOpen (WRITEALPHABETFILENAME, "wb");
CHECKERROR (fa, "Error open file");
CHECKERROR (Sort (text, CountStr, &Mystrcmp), "Error data");
CHECKERROR (FileWrite (fa, text, CountStr), "Error writinging file");
fclose (fa);
FILE* fea = FileOpen (WRITEENDALPHABETFILENAME , "wb");
CHECKERROR (fea, "Error open file");
CHECKERROR (Sort (text, CountStr, &Mystrrewcmp), "Error data");
CHECKERROR (FileWrite (fea, text, CountStr), "Error writinging file");
fclose (fea);
if ((!DeliteArrString(text, CountStr)) || (!DeliteBuf(buffer)))
perror("Warning. Failed to clean up used memory");
return 1;
}