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: