Gentlemen, good time of day. There is a task:

Given a sequence of characters consisting of words. Select in each word the most distant alphabetical letter. If from the beginning of the word to the position of this letter all the letters are ordered in ascending order, then delete such a word while preserving the structure of spaces. Display the edited text or the message "No" if there was no deletion of words. The definition of ordering in ascending order corresponds to the alphabetical order of the letters in the word.

I wrote two solutions, both do not work for an unknown reason:

#define _CRT_SECURE_NO_WARNINGS #include "stdio.h" #include "stdlib.h" #include "string.h" int main(void) { char str[100], word[100] = " ", word_arr[20][20]; // str - вводимая строка, word - хранилище слова, word_arr - 2D массив слов int i, j = 0, k = -1, *last, t = 0; // i, j - счётчики букв, k - счётчик кол-ва слов // last - массив положений наиболее удаленной по алф. буквы в каждом слове // t - счётчик слов, подлежащих удалению fgets(str, 100, stdin); for (i = 0; i <= strlen(str); i++) if (str[i] == ' ' || i == strlen(str)) { word[j] = '\0'; k++; strcpy(word_arr[k], word); word[j = 0] = '\0'; } else word[j++] = str[i]; last = (int*)malloc((k + 1) * sizeof(int)); for (i = 0; i <= k; i++) { for (j = 0; word_arr[i][j] != '\0'; j++) { if (word_arr[i][j - 1] < word_arr[i][j]) last[i] = j; } } for (i = 0; i <= k; i++) { for (j = 0; j <= last[i] - 2; j++) { if (word_arr[i][j] < word_arr[i][j + 1]) t++; } if (t == last[i] - 2) last[i] = -1; } t = 0; for (i = 0; i <= k; i++) if (last[i] == -1) t++; if (t = 0) { printf("No\n"); return 0; } for (i = 0; i <= k; i++) { if (last[i] != -1) { for (j = 0; word_arr[i][j] != '\0'; j++) printf("%c", word_arr[i][j]); printf(" "); } } return 0; } 

And second:

 #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" #include "stdlib.h" #include "string.h" int main(void) { char str[100], str2[100], word[100]; //str - вводимая строка, str2 - строка после преобразований, word - временное хранилище слова int i, j=0, t, k=0, words=0, max=0; // i - счётчик для перехода по знакам строки, j - счётчик букв в слове // t - счётчик для нахождения наиб. удаленной по алфавиту буквы, k - счётчик букв, удовл. условию // words - кол-во слов, подлежащих удалению, max - положение наиболее удаленной по алфавиту буквы fgets(str, 100, stdin); for (i = 0; i <= strlen(str); i++) { if (str[i] == ' ' || i == strlen(str)) { word[j++] = ' '; for (t = 0; t < j; t++) if (word[t] < word[t + 1]) max = ++t; for (t = 0; t < max-1; t++) { if (word[t] > word[t + 1]) break; k++; } if (k != max - 1) { strcat(str2, word); words++; } j=0; } else word[j++] = str[i]; } if (words == 0) printf("No"); else printf(str2); return 0; } 

In the first program, the last line of the array is moving out, the second one does not understand why. Tell me what's wrong. I would be very grateful!

  • I didn’t understand the program’s algorithm well, but ... (for now, let’s say about the second program) obvious errors: 1. You didn’t initialize the strings during the declaration. As a result, in the string str2 where you add everything - initially some kind of garbage lies. I would suggest they all do this: char str[100]={0}, str2[100]={0}, word[100]={0}; . - Vladimir
  • 2. If I understand correctly, the cycle on i (external) should divide into words, and these words are stored in word . So, after each word found (in the transition to a new one), you do not clear this word. The trash is again obtained (which remains if the new word is shorter). I propose to do something like this at each iteration of the loop after the conditional operator: memset(word,0,sizeof(word)); 3. Not so much a mistake as ... I have some doubts that it makes sense to lead a cycle to i <= strlen(str) - after all, the last character should be '\ 0'. - Vladimir

2 answers 2

I commented out the wrong place and added a couple of my commands and another printf () for debugging (you can delete it or use it for further struggle).

Your search for the maximum was incorrectly made (if I correctly understood this place). But this did not help much the work, it seems there are still errors in the program's algorithm. So far, deletes only one word at a time (I tested on the line: "qwert jbjhbjb jhbjbjhb 12345 abcdefgh"). The first one (in this example, only 12345 was deleted). But if you slip the data so that there are no deletions of the words, then "No" does not write :-(. Or, perhaps, I do not quite understand the task :-). In general, the program with mingw-w64 gcc now works without “crashes” (by the way, it didn’t crash with gcc, it just took out garbage in variables) and there is something to cut further. Maybe tomorrow with a fresh mind (if the team does not overtake) I will try to find the remaining mistakes.

 #include "stdio.h" #include "stdlib.h" #include "string.h" int main(void) { char str[100]={0}, str2[100]={0}, word[100]={0}; //str - вводимая строка, str2 - строка после преобразований, word - временное хранилище слова int i, j=0, t, k=0, words=0, max=0; // i - счётчик для перехода по знакам строки, j - счётчик букв в слове // t - счётчик для нахождения наиб. удаленной по алфавиту буквы, k - счётчик букв, удовл. условию // words - кол-во слов, подлежащих удалению, max - положение наиболее удаленной по алфавиту буквы fgets(str, 100, stdin); for (i = 0; i <= strlen(str); i++) { if ((str[i] == ' ') || (i == (strlen(str)))) { //++j; word[j++] = ' '; for (t = 0; t < j; t++) //if (word[t] < word[t + 1]) //max = ++t; if (word[t] > word[max]) max = t; printf("VAK: max = %i\n",max); for (t = 0; t < max-1; t++) { if (word[t] > word[t + 1]) break; k++; } if (k != (max - 1) ) { strcat(str2, word); words++; } j=0; k=0; memset(word,0,sizeof(word)); max = 0; } else word[j++] = str[i]; printf("vak: %s\n", word); } if (words == 0) printf("No"); else printf(str2); return 0; } 

PS: yes, of course ... even at each iteration over i it is necessary to clear the counter k. if you put k = 0; - then everything is a little better, but now there is a false response to "qwert".

  • I just changed the algorithm a bit and it worked! Thank you so much for showing how to create a clean line and clear memory, this was the main problem. Well, about the reset of meters, I forgot yesterday, hurried. - Watchman
  • Why did you use% i here printf ("VAK: max =% i \ n", max)? - Watchman
  • @Watchman, yes that the first came to hand :-). This is an analogue of% d. Why left it - I do not know, apparently, to maintain compatibility with the old versions. - Vladimir

Fully working version of the program.

 #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" #include "stdlib.h" #include "string.h" int main(void) { char str[100] = { 0 }, str2[100] = { 0 }, word[100] = { 0 }; int i, j = 0, t, k = 0, words = 0, max = 0; fgets(str, 100, stdin); for (i = 0; i <= strlen(str); i++) { if (str[i]>'A' && str[i]<'Z') str[i] += 'z' - 'Z'; // Устраняется разница кодов заглавных и строчных символов if ((str[i] == ' ') || (i == (strlen(str)))) { word[j++] = ' '; for (t = 0; t < j; t++) if (word[t] > word[max]) max = t; if (max < 2) k = -1; // Если перед самой удаленной по алфавиту буквой в слове меньше двух символов, то удалять такое слово не нужно for (t = 0; t < max - 1; t++) { if (word[t] > word[t + 1]) break; k++; } if (k == (max - 1)) words++; else strcat(str2, word); // Если все буквы идут по алфавиту, счётчик собирает все k и добавляет единицу к числу удаленных слов. В противном случае записывает слово в новую строку для вывода j = 0; k = 0; memset(word, 0, sizeof(word)); max = 0; } else word[j++] = str[i]; } if (words == 0) printf("No\n"); else printf("%s\n", str2); system("pause"); return 0; }