2016-03-03 2 views
0

У меня есть следующая функция, и я хочу проверить, являются ли две строки анаграммами. Один из способов, который я думал об этом, - суммировать значения каждого из символов в строках, а затем сравнить их значения.C - Передача значения int из строки char

Однако, когда я пытаюсь запустить свою программу, я получаю ошибку сегментации в обоих циклах. Я не понимаю этого правильно, есть ли что-то, что я делаю неправильно в своем коде?

int anagram(char *a, char *b) 
{ 
    int sum1 = 0; 
    int sum2 = 0; 
    char *p, *q; 

    for (p=a; p != '\0'; p++) { 
     sum1 += *p - 'a'; 
    } 

    for (q=b; q != '\0'; q++) { 
     sum2 += *q - 'a'; 
    } 

    if (sum1 == sum2) 
     return 1; 
    else 
     return 0; 
} 
+1

Должно быть '* p! = '\ 0'' и' * q! =' \ 0''. Поскольку 'p' и' q' не являются указателями NULL, ваши петли представляют собой бесконечные циклы. – user3386109

+0

@Barmar Я имею в виду, что если я напишу привет для строки a и loleh для строки b, я бы вернул 1 – lodam

+0

И как добавление символов говорит вам, являются ли они анаграммами? Вы получите те же суммы для '' abc "и' "bc" '. – Barmar

ответ

3

В ваших for петли вы должны проверить

*p != '\0'

*q != '\0'

Это причина SEG-вины.


Кроме того, даже фиксировано, что код даст вам ложных срабатываний:

«БК» анаграмма «объявления»

Я предлагаю вам другой подход:

сделать два массива от int s размер 256, ноль инициализирован.

Пусть каждый элемент каждого массива содержит счетчик каждой буквы (символа) каждой строки.

Наконец, сравните, если оба массива одинаковы.

Я оставляю задачу написания кода для вас.

+1

@chqrlie Вся его идея использовать суммы для тестирования анаграмм неверна, но об этом не спрашивается. – Barmar

+0

oh ok спасибо, плохо ищите новый подход, спасибо! – lodam

+1

Его вопрос довольно запутанный ... Но я предпочитаю ответы, чтобы адресовать большинство, если не все проблемы. – chqrlie

1

«p! = 0» должно быть «* p! = 0», так как теперь вы ожидаете, что указатель станет нулевым.

1

Вот полное решение для вашей проблемы:

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

int cmp(const void *str1, const void *str2) { 
    return (*((char*)str1) - *((char*)str2));  
} 

bool areAnagram(char *str1, char *str2) { 
    int n1 = strlen(str1); 
    int n2 = strlen(str2); 

    if (n1 != n2) 
     return false; 

    qsort(str1, n1, 1, &cmp); 
    qsort(str2, n2, 1, &cmp); 

    for (int i = 0; i < n1; i++) 
     if (str1[i] != str2[i]) 
     return false; 

    return true; 
} 

int main() 
{ 
    char str1[] = "test"; 
    char str2[] = "tset"; 
    if (areAnagram(str1, str2)) 
     printf("The two strings are anagram of each other"); 
    else 
     printf("The two strings are not anagram of each other"); 

    return 0; 
} 
+0

@chux: Thanx, я не запускал его. Просто написал это из памяти. Поменяйте линию своим предложением. – cwschmidt

1

Поскольку мы уже даем ответы на вопросы о лучших подходах, вот мой:

Получить список (желательно маленьких) простых чисел. Вам нужен один для каждого возможного символа ваших входных строк, поэтому, когда вы хотите проверить строки, содержащие только цифры от 0 до 9, вам нужно 10 простых чисел. Давайте возьмем эти:

static unsigned const primes[10] = { 
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 

Теперь, так как каждое число имеет ровно один премьер факторизации, и из-за умножением является коммутативным, вы можете просто создать произведение простых чисел для каждого символа вашей строки. Если они идентичны, то для каждого символа выполняется то же количество раз в обеих строках. Таким образом, обе строки являются анаграммами друг друга.

unsigned long prime_product(char const * str) { 
    assert(str != NULL); 
    unsigned long product = 1; 
    for (; *str != '\0'; ++str) { 
    assert(*str >= '0'); 
    assert(*str <= '9'); 
    product *= primes[*str - '0']; 
    } 
    return product; 
} 

char is_anagram(char const * one, char const * two) { 
    return prime_product(one) == prime_product(two); 
} 

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

Как видно, эта версия имеет O(n) сложность времени и постоянного пространства.

+0

Неплохо, но вам понадобится 'uint128_t' для обработки 26 разных символов. – chux

Смежные вопросы