Сортировка повторяющихся строк в C - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь написать программу на C, которая может фильтровать строки. Предполагается печатать только одну строку при наличии последовательных повторяющихся строк. Я должен использовать массивы символов для сравнения строк. Размеры массивов несущественны (для проекта установлено 79 символов). Я инициализировал массивы так:

char newArray [MAXCHARS];
char oldArray [MAXCHARS];

и заполнил массив с помощью этого цикла for, чтобы проверить наличие новых строк и конца файла:

 for(i = 0; i<MAXCHARS;i++){
         if((newChar = getc(ifp)) != EOF){
                 if(newChar != '/n'){
                           oldArray[i] = newChar;
                           oldCount++;
                  }
                  else if(newChar == '/n'){
                           oldArray[i] = newChar;
                           oldCount++;
                           break;
                  }
         }
         else{
              endOf = true;
              break;
         }
}      

Для циклического перехода по следующей строке (строкам) и поиска дубликатов я использую цикл while, который изначально установлен в значение true. Он заполняет следующий массив до новой строки и тестирует на EOF. Затем я использую два цикла for для проверки массивов. Если они одинаковы в каждой позиции в массивах, дубликат остается неизменным и ничего не печатается. Если они не совпадают, для параметра duplicate устанавливается значение false, и вызывается функция (testArrays) для печати содержимого каждого массива.

 while(duplicate){
         newCount = 0;
         /* fill second array, test for newlines and EOF*/
         for(i =0; i< MAXCHARS; i++){
                if((newChar = getc(ifp)) != EOF){
                       if(newChar != '/n'){
                           newArray[i] = newChar;
                           newCount++;
                       }
                       else if(newChar == '/n'){
                              newArray[i] = newChar;
                              newCount++;
                              break;
                       }
                }
                else{                 
                        endOf = true;
                         break;
                }
         }
/* test arrays against each other to spot duplicate lines*
  if they are duplicates, continue the while loop getting new 
  arrays of characters in newArray until these tests fail*/
        for(i =0; i< oldCount;  i++){
               if(oldArray[i] == newArray[i]){
                     continue;
               }
              else{
                    duplicate = false;
                     break;
               }
        }
        for(i =0; i <newCount; i++){
                if(oldArray[i] == newArray[i]){
                       continue;
                }
                else{
                     duplicate = false;
                     break;
                }
        }

        if(endOf && duplicate){
                testArray(oldArray);
                break;
         }
}      
if((endOf && !duplicate) || (!endOf && !duplicate)){
         testArray(oldArray);
         testArray(newArray);
}      

Я считаю, что это не работает, и в любом случае печатаются последовательные идентичные строки. Я не могу понять, как это могло случиться. Я знаю, что это большой код, который нужно пройти, но он довольно прост, и я думаю, что другой взгляд на это легко обнаружит проблему. Спасибо за помощь.

Ответы [ 4 ]

0 голосов
/ 01 мая 2018

Вам нужно использовать функцию для чтения строк - либо fgets(), либо ту, которую вы пишете (или POSIX getline(), если вы знакомы с динамическим распределением памяти).

Затем вам нужно использовать алгоритм, эквивалентный:

  1. Прочитать первую строку в old.
  2. Если нет линии (EOF), остановитесь.
  3. Распечатать первую строку.
  4. Для каждой дополнительной строки читать в new.
    • Если нет линии (EOF), остановитесь.
    • Если new совпадает с old, перейдите к шагу 4.
    • Печать new.
    • Копировать new в old.
    • Перейти к шагу 4.

Эти шаги перехода будут частью обычных элементов управления цикла, а не фактических goto операторов.

0 голосов
/ 01 мая 2018

Я бы сделал это по строкам вместо char по char. Я бы использовал get (), чтобы получить полную строку ввода и передать ее в предыдущую строку. Вы также можете использовать fgets (str, MAX_CHARS, stdin), если хотите. strcmp предполагает, что ваши строки обнуляются, и вам может потребоваться специальная обработка EOF, но что-то вроде того, что ниже, должно работать:

int main(){
  char newStr[MAX_CHARS] = {0}; //string for new input
  char oldStr[MAX_CHARS] = {0};

  // Loop over input as long as there is something to read
  while(gets(newStr) != NULL){
    if(strcmp(newStr,oldStr) != 0){
      printf("%s", newStr); 
    }
    else{
      //This is the case when you have duplicate strings.  Dont print
    }

    memset(oldStr, 0, sizeof(oldStr)); //clear out old string incase it was longer
    strcpy(oldStr, newStr); //copy new string into old string for future compare
  }
}
0 голосов
/ 01 мая 2018

В той части, где вы проверяли дубликаты, может быть, вы могли бы сначала проверить oldCount == newCount? Я считаю, что если это повторяющаяся строка, oldCount будет равен newCount. Если это правда, тогда перейдите к проверке двух массивов?

0 голосов
/ 01 мая 2018

есть ли причина, по которой вы читаете символ за раз, а не вызываете fgets () для чтения строки?

char instr[MAXCHARS];
for( iline = 0; ( fgets( instr, 256, ifp ) ); iline++ ) {

. . .<strcmp() current line to previous line here>. . .

}

EDIT: Возможно, вы захотите объявить 2 символьные строки и 3 символьных указателя - один указывает на текущую строку, а другой на предыдущую строку. Затем поменяйте местами два указателя, используя третий указатель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...