2017-01-25 2 views
0

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

Это мой main.c файл:

#include <stdio.h> 
#include <string.h> 
#include "functions.h" 

int main() { 

    char string[256]; 
    int length; 

    printf("Enter char array size of string(counting with backslash 0): \n"); 
/* 
    Example: The word aabc will get a size of 5. 
    a = 0 
    a = 1 
    b = 2 
    c = 3 
    /0 = 4 
    Total 5 slots to allocate */ 

    scanf("%d", &length); 

    printf("Enter string you wish to remove duplicates from: \n"); 
    for (int i = 0; i < length; i++) 
    { 
     scanf("%c", &string[i]); 
    } 

    deleteDuplicates(string, length); 

    //String output after removing duplicates. Prints out trash values! 
    for (int i = 0; i < length; i++) { 
     printf("%c", string[i]); 
    } 
    //Length of new string. The length is also wrong! 
    printf("\tLength: %d\n", length); 
    printf("\n\n"); 

    getchar(); 
    return 0; 
} 

Выход из printf("%c", string[i]); распечатывает значений мусора в конце строки, которая не является правильным.

Функция deleteDuplicates выглядит в файле functions.c:

void deleteDuplicates(char string[], int length) 
{ 
    for (int i = 0; i < length; i++) 
    { 
     for (int j = i + 1; j < length;) 
     { 
      if (string[j] == string[i]) 
      { 
       for (int k = j; k < length; k++) 
       { 
        string[k] = string[k + 1]; 
       } 
       length--; 
      } 
      else 
      { 
       j++; 
      } 
     } 
    } 
} 
+1

'строку [к + 1]; 'будет получать доступ за пределы (вызывая неопределенное поведение) в вашей функции' deleteDuplicates' – UnholySheep

+0

Этот подход чрезвычайно неэффективен ficient. Не лучше ли сортировать или хешировать персонажей? Также почему бы не использовать что-то 'fgets' для чтения символов? – RoadRunner

ответ

0

Функции в C являются передача по значению по умолчанию, не пройти по ссылке. Таким образом, ваша функция deleteDuplicates не изменяет длину в вашей основной функции. Если вы измените свою функцию для передачи по ссылке, ваша длина будет изменена.

Вот пример использования вашего кода.

Вызов функции будет:

deleteDuplicates(string, &length); 

функция будет:

void deleteDuplicates(char string[], int *length) 
{ 
    for (int i = 0; i < *length; i++) 
    { 
     for (int j = i + 1; j < *length;) 
     { 
      if (string[j] == string[i]) 
      { 
       for (int k = j; k < *length; k++) 
       { 
        string[k] = string[k + 1]; 
       } 
       *length--; 
      } 
      else 
      { 
       j++; 
      } 
     } 
    } 
} 
+0

Почему вы не наводите указатель на «длину»? Теперь вы сравниваете 'i

+0

@YuriyIvaskevych хороший улов. Я добавил быстрый пример и не думал о фактическом коде внутри функции. Отредактированный ответ. – quickblueblur

+0

'string [k + 1]' все еще выходит за рамки –

1

Существует более ЭФФЕКТИВНАЯ и безопасный способ сделать упражнение:

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

void deleteDuplicates(char string[], int *length) 
{ 
    int p = 1; //current 
    int f = 0; //flag found 
    for (int i = 1; i < *length; i++) 
    { 
     f = 0; 
     for (int j = 0; j < i; j++) 
     { 
      if (string[j] == string[i]) 
      { 
       f = 1; 
       break; 
      } 
     } 
     if (!f) 
      string[p++] = string[i]; 

    } 
    string[p] = '\0'; 
    *length = p; 
} 

int main() { 
    char aux[100] = "asdñkzzcvjhasdkljjh"; 
    int l = strlen(aux); 

    deleteDuplicates(aux, &l); 
    printf("result: %s -> %d", aux, l); 
} 

Вы можно увидеть результаты здесь: http://codepad.org/wECjIonL

Или даже более утонченный способ можно найти здесь: http://codepad.org/BXksElIG

0

Вы можете достичь O(n) решения путем хеширования символов в массиве.

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

Вы можете создать хэш-массив так:

int hashing[256] = {0}; 

который устанавливает все значения, чтобы быть в массиве 0. Затем вы можете проверить, имеет ли слот 0, что означает, что персонаж не был посещен. Каждый раз, когда 0 найден, добавьте символ в строку и отметьте этот слот как 1. Это гарантирует, что дублирующиеся символы не могут быть добавлены, поскольку они добавляются только в том случае, если найдено 0.

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

Также лучше использовать fgets для чтения ввода от пользователя, а не scanf().

Вот некоторые модифицированный код, который я написал некоторое время назад, который показывает эту идею хеширования:

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

#define NUMCHAR 256 

char *remove_dups(char *string); 

int main(void) { 
    char string[NUMCHAR], temp; 
    char *result; 
    size_t len, i; 
    int ch; 

    printf("Enter char array size of string(counting with backslash 0): \n"); 
    if (scanf("%zu", &len) != 1) { 
     printf("invalid length entered\n"); 
     exit(EXIT_FAILURE); 
    } 

    ch = getchar(); 
    while (ch != '\n' && ch != EOF); 

    if (len >= NUMCHAR) { 
     printf("Length specified is longer than buffer size of %d\n", NUMCHAR); 
     exit(EXIT_FAILURE); 
    } 

    printf("Enter string you wish to remove duplicates from: \n"); 
    for (i = 0; i < len; i++) { 
     if (scanf("%c", &temp) != 1) { 
      printf("invalid character entered\n"); 
      exit(EXIT_FAILURE); 
     } 
     if (isspace(temp)) { 
      break; 
     } 
     string[i] = temp; 
    } 
    string[i] = '\0'; 

    printf("Original string: %s Length: %zu\n", string, strlen(string)); 

    result = remove_dups(string); 

    printf("Duplicates removed: %s Length: %zu\n", result, strlen(result)); 

    return 0; 
} 

char *remove_dups(char *str) { 
    int hash[NUMCHAR] = {0}; 
    size_t count = 0, i; 
    char temp; 

    for (i = 0; str[i]; i++) { 
     temp = str[i]; 
     if (hash[(unsigned char)temp] == 0) { 
      hash[(unsigned char)temp] = 1; 
      str[count++] = str[i]; 
     } 
    } 

    str[count] = '\0'; 

    return str; 
} 

Пример ввода:

Enter char array size of string(counting with backslash 0): 
20 
Enter string you wish to remove duplicates from: 
hellotherefriend 

Выход:

Original string: hellotherefriend Length: 16 
Duplicates removed: helotrfind Length: 10 
Смежные вопросы