Программа палиндром C работает на локальном ПК, но не на INGInious

У меня есть программа c, которая обнаруживает палиндром. Он также обнаруживает палиндромы с пробелами. Он возвращает -1, если строка пустая, 1, если это палиндром, и 0 в противном случае. Вот код:

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

int pal(char *str){

    if (str[0] == '\0'){
        return -1;
    }else{
        size_t i = 0;
        size_t j = strlen(str) - 1;
        while(*(str + i) != '\0'){
            if (*(str + i) == ' '){
                i++;
                continue;
            }else if (*(str + j) == ' '){
                j--;
                continue;
            }else{
                if (*(str + i) != *(str + j)){
                    return 0;
                }
            }
            i++;
            j--;
        }

        return 1;

    }

}


int main(){

    char *str = "a man a plan a canal panama";
    printf("%d", pal(str));
    printf("\n");
    return 0;
}

Когда я скомпилировал и запустил эту программу на своем локальном компьютере, она работала нормально. Но когда я загрузил его в вопрос INGInious моего курса CS (INGInious — это платформа, на которой люди могут загружать свои ответы по определенной теме, и система просматривает их), это вызывает ошибку сегментации. Есть ли какой-либо сценарий, который может привести к SegFault, о котором я не знаю?

Этот код трудно читать, но я бы поставил на доступ где-то за пределами границ.

Eugene Sh. 27.02.2019 21:21
*(str + i) то же самое, что и str[i], что намного легче читать.
Kon 27.02.2019 21:22
Он также обнаруживает палиндромы с пробелами. — Чем палиндром, содержащий пробелы, отличается от других палиндромов?
Swordfish 27.02.2019 21:23

@ Феликс, это не изменено.

Weather Vane 27.02.2019 21:25

Ваш j неконтролируемо уменьшается. Если он становится равным 0, вы теряете размер size_t (и он становится огромным).

SergeyA 27.02.2019 21:26

Если тестовая строка начинается с пробела, то у элемента управления j проблемы. Но он компилируется и работает на MSVC без каких-либо проблем, и я не вижу никакой другой проблемы (кроме его эффективности - он должен остановиться на середине).

Weather Vane 27.02.2019 21:27

Это хороший момент, знает ли OP тестовую строку, вызвавшую сбой?

Weather Vane 27.02.2019 21:39

код имеет неопределенное поведение, если платформа, на которую вы загружаете свой код, тестирует str, будучи NULL...

Stephan Lechner 27.02.2019 21:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
75
3

Ответы 3

В цикле ниже:

while(*(str + i) != '\0'){
    if (*(str + i) == ' '){
        i++;
        continue;
    }else if (*(str + j) == ' '){
        j--;
        continue;
    }else{
        if (*(str + i) != *(str + j)){
            return 0;
        }
    }
    i++;
    j--;
}

Когда *(str + i) == '\0', это должно быть i == strlen(str) и j == -1 (если в строке нет пробела. В противном случае я не уверен), и это может быть проблемой. Но опять же, я действительно не вижу, чтобы вы не получили доступ str за пределы досягаемости. Вместо этого я бы предложил сделать это, чтобы вашему циклу было легче увидеть условие завершения:

while(i < j){
    // ...
}

Как я уже сказал в своих комментариях, вы не контролируете значение j, и из-за этого ваш код может потенциально демонстрировать неопределенное поведение — когда j становится 0, но вы продолжаете его уменьшать, оно зацикливается и становится максимальным значением типа size_t (довольно впечатляющее число на современной платформе).

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

Например, ваш код будет подвергаться неопределенному поведению в следующей строке: "a bcd"

Ваш код слишком сложен.

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

bool is_palindrome(char const *str)
{
    size_t length = strlen(str);

    for (char const *front = str, *back = str + length - 1; front != back; ++front, --back) {
        while (isspace((char unsigned) *front) && front != str + length - 1)
            ++front;

        while (isspace((char unsigned) *back) && back != str)
            --back;

        if (front == back)
            break;

        if (*front != *back)
            return false;
    }
    return true;
}

int main(void)
{
    char const *foo = "a man a plan a canal panama";
    printf("%d\n", is_palindrome(foo));

    char const *bar = "hello";
    printf("%d\n", is_palindrome(bar));
}

Вывод:

1
0

Другие вопросы по теме