Удаление последовательных повторяющихся символов из строки с помощью C - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь удалить последовательные повторяющиеся символы из заданной строки.

Пример:

bssdffFdcrrrtttii *** #

вывод должен быть:

bsdfFdcrti * #

Этот код не работает и печатает только первый символ (b), я хочу узнать о моей ошибке. когда я делаю тест printf, он работает, но не для пробелов. Я думаю, что проблема может быть с новым массивом символов.

void Ex6() {
    char* string[80];
    scanf("%s", &string);
    puts(removeDup(string));
}

char* removeDup(char *string) {
    int i, c = 0;
    char* newString[80];
    for (i = 0; i < strlen(string); i++) {
        if (string[i] != string[i + 1]) {
            newString[c++] = string[i];
        }
    }
    return newString;
}

Ответы [ 3 ]

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

В вашей программе довольно много проблем. Он даже не скомпилирует, не говоря уже о запуске. Кроме того, наиболее проблемная проблема заключается в том, что вы возвращаете указатель на локальную переменную из функции, которая прекращает свою область действия после завершения. Упрощенная версия вашей программы выглядит следующим образом:

void Ex6() 
{
   char string[80];
    scanf("%s", string);
        int i, c = 0;
    char newString[80];
    for (i = 0; i < strlen(string); i++) {
        if (string[i] != string[i + 1]) {
            newString[c++] = string[i];
        }
    }
    newString[c] = '\0';
    puts(newString);
}
0 голосов
/ 10 мая 2018

Вы можете сделать это за время O (n) и пространство O (1), изменив существующую строку:

#include <stdio.h>

char* removeDup(char* input) {
        char* newTail = input, *oldTail = input;
        while (*oldTail) {
            if (*newTail == *oldTail) {
                ++oldTail;
            } else {
                *++newTail = *oldTail++;
            }
        }
    return newTail;
}

int main() {
   char string[] = "bssdffFdcrrrtttii ***#";
   char* newEnd = removeDup(string);
   char* tmp = string;
   while (tmp != newEnd) {
       printf("%c", *tmp++);
   }
   //Print the last char if string had any duplicates
   if(*tmp) {
       printf("%c", *tmp++);
   }
   return 0;
}
0 голосов
/ 10 мая 2018

Есть несколько проблем с вашей программой:

  • Объявление newString должно быть char newString[80], т. Е. Массивом символов, а не массивом указателей на символы, ианалогично для объявления в Ex6.
  • Тогда вызов scanf должен быть scanf("%s", string), поскольку string уже является адресом массива символов, но ...
  • Используйте fgets для чтения строки от пользователя, чтобы убедиться, что вы читаете пробел, если это важно, и что буфер не превышен.
  • newString выделен в стеке и поэтому не долженбыть возвращенным звонящему.Лучше сделать char *newString = strdup(string), или, чуть менее небрежно, char *newString = malloc(strlen(string)+1), который вызовет malloc для блока памяти, достаточного для хранения исходной строки, и, следовательно, версии без дубликатов - комментарии правильно указываютчто это может быть оптимизировано.В принципе, вызывающий объект, т. Е. Ex6, должен free возвращенный указатель, чтобы избежать утечки памяти, но это вряд ли имеет значение в такой короткой программе.
  • В результате необходим нулевой терминатор: newString[c] = '\0'.

В противном случае, функция removeDup, кажется, работает правильно.

Итак, собрав все это вместе:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* removeDup(const char *string)
{
    size_t i, c = 0;
    size_t string_len = strlen(string);
    char *newString = malloc(string_len + 1);

    for (i = 0; i < string_len; i++) {
        if (string[i] != string[i + 1]) {
            newString[c++] = string[i];
        }
    }
    newString[c] = '\0';

    return newString;
}

#define MAX_STRING_LEN 80

void Ex6() {
    char string[MAX_STRING_LEN];
    char* result;

    if (fgets(string, MAX_STRING_LEN, stdin) != NULL) {
        result = removeDup(string);

        printf("%s", result);
        free(result);
    }
}

Наконец, я согласен сКомментарий @ tadman.Поскольку входную строку в любом случае необходимо пройти для вычисления длины, мы также можем оптимизировать размер строки результата:

char* removeDup(const char *string)
{
    size_t i, c = 0;
    char *newString;

    for (i = 0; string[i] != '\0'; i++)
        c += (string[i] != string[i + 1]);

    newString = malloc(c + 1);

    for (i = c = 0; string[i] != '\0'; i++) {
        if (string[i] != string[i + 1]) {
            newString[c++] = string[i];
        }
    }
    newString[c] = '\0';

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