Проверка строки палиндрома в c

Я принимаю строку в качестве аргумента командной строки. Я хочу проверить, является ли введенная строка палиндромом или нет, и распечатать результат. Я написал следующий код. Но он отображает результат «не палиндром» для всех входов.

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

int main(int argc, char argv[20]) {
    int i;
    int l = strlen(argv);    
    char str[20];
    bzero(str, 20);

    for(i=0; i<l; i++)
    {
        str[i] = argv[i+2];
    } 
    int flag;
    int len = strlen(str);
    for(i=0; i< len/2; i++)
    {
        if(str[i] == str[len - (i+2)])
        {
            flag = 0;
        }
        else
        {
            flag = 1;
            break;
        }
    }

    if(flag == 0)
        printf("Palindrome\n");
    else
        printf("Not a palindrome\n");
}

person Khushboo    schedule 12.08.2010    source источник
comment
Я не могу отформатировать код здесь. Может ли кто-нибудь помочь мне с этим, а также с проблемой программирования? Как напечатать каждую строку кода в отдельной строке?   -  person Khushboo    schedule 12.08.2010
comment
Чтобы отформатировать код, сделайте отступ в четыре пробела или нажмите кнопку 101010. Это не читается так, как сейчас.   -  person Thomas    schedule 12.08.2010
comment
@user417316 user417316, вставьте свой код в текстовое поле из любого редактора, который вы используете, выберите его все, а затем нажмите кнопку форматирования кода (она выглядит как маленькие 1 и 0).   -  person Carl Norum    schedule 12.08.2010
comment
Не ответ на ваш вопрос, но нет необходимости сбрасывать flag при каждой успешной итерации. Просто инициализируйте его и изменяйте только в случае сбоя. Также у вас неправильный тип для argv, который должен быть char**; это может вызвать почти любой хаос.   -  person dmckee --- ex-moderator kitten    schedule 12.08.2010
comment
@Томас: Спасибо!! Это помогло. @Carl Norum: Спасибо за помощь!! @dmckee: Спасибо!   -  person Khushboo    schedule 12.08.2010
comment
@user417316 user417316, если это домашнее задание, отметьте правильно...   -  person Bruno Brant    schedule 12.08.2010


Ответы (6)


Вы можете сделать это в стиле K&R, используя два итератора смещения в цикле for:

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

int main(int argc, char *argv[]) {
    assert(argc != 1);

    char *text = argv[1];

    int len = strlen(text);
    int is_palindrome = 1;
    int i, j;

    for(i = 0, j = len - 1; i < len / 2; i++, j--) {
        if(text[i] != text[j]) {
            is_palindrome = 0;
            break;
        }
    }

    printf("%s a palindrome.\n", is_palindrome ? "is" : "isn't");

    return(0);
}

Отличия от оригинала:

  • Изменен сдвиг (длина >> 1) на деление (длина / 2), как предложил tenfour.
person gamen    schedule 12.08.2010
comment
на самом деле мне не совсем удобно программировать с использованием указателей. Мне нужно получить больше информации и понимания указателей. Может быть, тогда я попробую программировать с использованием указателей. Есть ли другой способ решить проблему с палиндромом? - person Khushboo; 14.08.2010
comment
оптимизация: int len = strlen(text) / 2; - person tenfour; 14.08.2010
comment
Я хотел бы порекомендовать забавные видеоролики Бинки: cslibrary.stanford.edu/104. - person gamen; 25.08.2010

Обновлено на основе комментариев:

int is_palindrome(const char *s)
{
   const char *t = s + strlen(s);
   while (s<t && *s==*--t) s++;
   return s>=t;
}

И поскольку OP хочет версию, которая не так тяжела для указателей:

int is_palindrome(const char *s)
{
   size_t i=0, j = strlen(s);
   while (i<j && s[i]==s[--j]) i++;
   return i>=j;
}

Для справки, вот оригинальная версия с ошибками:

int is_palindrome(const char *s)
{
   const char *t = s + strlen(s) - 1;
   while (s<t && *s++==*t--);
   return s>=t;
}
person R.. GitHub STOP HELPING ICE    schedule 13.08.2010
comment
Я не называю это загадочным. Я называю это не делать еду из вещей. Когда вам нужно выполнить тривиальное задание, не делайте его сложным, написав так много... если только вы не пытаетесь расслабиться и убедить своего босса, что написали кучу строк кода. - person R.. GitHub STOP HELPING ICE; 13.08.2010
comment
К сожалению, это не работает для многих не-палиндромов, таких как ab. Попробуйте while (*s == *t && s++ < t--) ;. И есть проблема с проверкой пустой строки. - person schot; 13.08.2010
comment
Я ждал, пока кто-нибудь уловит технические особенности уменьшения t до начала строки, когда строка пуста. :-) И вы правы по поводу другой ошибки - это то, что я получаю за кодирование в текстовом поле на SO. я бы поменял на for (t=s+strlen(s)-1; s<t && *s==*t; s++, t--); - person R.. GitHub STOP HELPING ICE; 13.08.2010
comment
на самом деле мне не совсем удобно программировать с использованием указателей. Мне нужно получить больше информации и понимания указателей. Может быть, тогда я попробую программировать с использованием указателей. Есть ли другой способ решить проблему с палиндромом? - person Khushboo; 14.08.2010
comment
Хорошо, я добавлю версию с индексами массива. - person R.. GitHub STOP HELPING ICE; 14.08.2010

Во-первых, ваша подпись для main отключена. Должно быть int main(int argc, char** argv) или int main(int argc, char * argv[]). Вы обрабатываете указатель на строку, как если бы это была строка.

Когда вы это изменили, нужная вам строка должна быть в argv[1] (поскольку argv[0] является некоторым представлением имени программы).

person David Thornley    schedule 12.08.2010
comment
На самом деле я пробовал с int main(int argc, char** argv). Но это дает мне некоторую ошибку литья. Я тоже пытаюсь это выяснить. - person Khushboo; 12.08.2010
comment
@user: Тогда вам нужно выяснить эту ошибку, потому что подпись main обязательна по стандарту. - person dmckee --- ex-moderator kitten; 12.08.2010
comment
Я делал только с argv[1]. Но все же показывает несколько ошибок и предупреждений. - person Khushboo; 12.08.2010
comment
@Khushboo: В этом случае отредактируйте вопрос, чтобы показать исправленный код, а также ошибки и предупреждения. - person David Thornley; 12.08.2010

Для этого есть хороший случай использовать указатели, а не индексы:

int is_palindrome(const char *s) {
    const char *end = s + strlen(s);
    while (end > s) {
        --end;
        if (*end != *s) return 0;
        ++s;
    }
    return 1;
}

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

int is_palindrome(const char *s) {
    const char *end = s + strlen(s);
    while (end > s) if (*(--end) != *(s++)) return 0;
    return 1;
}

argv - это не строка, это массив строк, одна для имени программы, а затем одна для каждого аргумента (обычно разделенного пробелом в командной строке). Итак, чтобы проверить, является ли первый аргумент палиндромом, вам понадобится argv[1].

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("usage: %s <string>\n", argv[0]); // or something
        return 1;
    }
    if (is_palindrome(argv[1])) {
        printf("Palindrome\n");
    } else {
        printf("Not a Palindrome\n");
    }
}
person Steve Jessop    schedule 13.08.2010

Первый цикл не имеет смысла. Копировать строку в другую не имеет смысла.

Просто сделайте это и настройте индекс:

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

int main(int argc, char **argv) {
int i;
char * str = argv[1];
int flag;

int len = strlen(str);

for(i=0; i< (len+1)/2; i++)
{

    printf("DEBUG: Comparing %c %c\n",str[i], str[len - (i+1)]);


    if(str[i] == str[len - (i+1)])
    {
        flag = 0;
    }
    else
    {
        flag = 1;
        break;
    }
}

    if(flag == 0)
    printf("Palindrome\n");
else
    printf("Not a palindrome\n");
}
person LatinSuD    schedule 12.08.2010

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

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

int main( int argc, char *argv[] )
{
    char    *s2;

    if ( argc != 2 )
        return ( 1 );   //  not properly invoked

    if ( (s2 = strdup( argv[1] )) == NULL )
        return ( 2 );   //  failed (not likely)

    printf( "\"%s\" %s a palindrome.\n", argv[1], strcmp( argv[1], strrev( s2 ) ) ? "is not" : "is" );

    free( s2 );

    return ( 0 );
}
person BillP3rd    schedule 14.08.2010