001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004:
005: // data structure to manage an array of text rows (i.e. strings)
006: struct text
007: {
008: char **righe;
009: int nrighe;
010: };
011:
012: // function prototypes
013: void I(struct text*);
014: void V(struct text*);
015: void E(struct text*);
016: void S(struct text*);
017: void C(struct text*);
018: void wipe(struct text*);
019:
020: int main(int argc, char **argv){
021:
022: // define and init struct
023: struct text mytext;
024: mytext.righe = NULL;
025: mytext.nrighe = 0;
026:
027: // variables to manage requested command
028: char command;
029:
030: // loop to read commands
031: printf("Command: ");
032: while(scanf(" %c", &command) == 1)
033: {
034: switch(command)
035: {
036: case 'V':
037: V(&mytext);
038: break;
039: case 'I':
040: I(&mytext);
041: break;
042: case 'E':
043: E(&mytext);
044: break;
045: case 'S':
046: S(&mytext);
047: break;
048: case 'C':
049: C(&mytext);
050: break;
051: case 'F':
052: exit(EXIT_SUCCESS);
053: break;
054: default:
055: fprintf(stderr, "Unknown command!\n");
056: }
057: printf("Command: ");
058: }
059:
060: return 0;
061: }
062:
063: void V(struct text *t)
064: {
065: for(int i = 0; i < t->nrighe; ++i)
066: {
067: printf("#%3d: %s\n", i+1, t->righe[i]);
068: }
069: }
070:
071: void I(struct text *t)
072: {
073: int n;
074: scanf("%d", &n); // read "n"
075: // given that we have to add a line just after the n-th line this means that n is already
076: // the right array index where to add the line
077:
078: char tmp[1000];
079: printf("Insert the row to be added: ");
080: scanf(" %[^\n]", tmp);
081:
082: // we need to add a line to our array of rows
083: t->nrighe++;
084: t->righe = realloc(t->righe, t->nrighe*sizeof(char *));
085:
086: if(n >= t->nrighe) // true if we have less than n rows, in this case we have to add the line as last line
087: {
088: // insert the new line as the last one
089: t->righe[t->nrighe - 1] = malloc(sizeof(char)*(strlen(tmp) + 1));
090: strcpy(t->righe[t->nrighe - 1], tmp);
091: }
092: else
093: {
094: // before inserting the new line we have to make space moving other rows
095: for(int i=t->nrighe - 1; i >= n + 1; --i)
096: {
097: t->righe[i] = t->righe[i - 1];
098: }
099: // allocate new line space
100: t->righe[n] = malloc(sizeof(char)*(strlen(tmp) + 1));
101: strcpy(t->righe[n], tmp);
102: }
103: }
104:
105: void E(struct text *t)
106: {
107: int n;
108: scanf("%d", &n); // read "n"
109: // we have to remove the n-th rows, a little adjustment is necerssary
110: // given that the array index starts from 0
111: --n;
112:
113: if(n < t->nrighe) // we can not remove a line that does not exist...
114: {
115: // remove the line, namely free memory
116: free(t->righe[n]);
117: for(int i = n; i < (t->nrighe - 1); ++i)
118: t->righe[i] = t->righe[i+1];
119: }
120: t->nrighe--;
121: t->righe = realloc(t->righe, t->nrighe*sizeof(char *)); // we also need to schrink the array
122: }
123:
124: void S(struct text *t)
125: {
126: char nomefile[1000];
127: printf("Enter file name: ");
128: scanf(" %s", nomefile);
129:
130: FILE *fp = fopen(nomefile, "w");
131: if(!fp)
132: {
133: printf("ERROR: I can not open file [%s] for writing\n", nomefile);
134: return;
135: }
136:
137: for(int i = 0; i < t->nrighe; ++i)
138: {
139: fprintf(fp, "%s\n", t->righe[i]);
140: }
141: fclose(fp);
142: }
143:
144: void C(struct text *t)
145: {
146: char nomefile[1000];
147: printf("Enter file name: ");
148: scanf(" %s", nomefile);
149:
150: FILE *fp = fopen(nomefile, "r");
151: if(!fp)
152: {
153: printf("ERROR: I can not open file [%s] for reading\n", nomefile);
154: return;
155: }
156:
157: // remove current content
158: wipe(t);
159:
160: // read the file line by line
161: char tmp[1000];
162: while(fscanf(fp, " %[^\n]", tmp) == 1)
163: {
164: t->nrighe++;
165: t->righe = realloc(t->righe, sizeof(char*)*t->nrighe);
166: t->righe[t->nrighe - 1] = malloc(sizeof(char)*(strlen(tmp) + 1));
167: strcpy(t->righe[t->nrighe - 1], tmp);
168: }
169:
170: }
171:
172: // additional function to completely free/wipe content of a text
173: void wipe(struct text *t)
174: {
175: // if already empy return
176: if(!t->nrighe)
177: return;
178:
179: // free each row
180: for(int i = 0; i < t->nrighe; ++i)
181: free(t->righe[i]);
182:
183: // free main pointer
184: free(t->righe);
185:
186: // reinit data
187: t->righe = NULL;
188: t->nrighe = 0;
189: }
190: