Разделение строки на c без изменения оригинала

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

void stringSplit(const char *original, char result[50][256], int* size, char delim){
    size_t begin = 0;
    if (!original){
        return;
    }
    for(size_t i=0; i<strlen(original);i++ ){
        if (original[i] == delim){
            int str_begin = 0;
            for( ; begin < i; begin++ ){
                result[*size][str_begin] = original[begin];
                str_begin++;
            }
            (*size)++;
            begin ++ ;
        }
    }
}

Прохладный. У вас есть вопросы по этому поводу?

that other guy 21.03.2018 23:07
for(size_t i=0; i<strlen(original);i++ ) -> for (size_t i = 0; original[i] != '\0'; i++ ), потому что strlen()считает символы и это неэффективно.
Iharob Al Asimi 21.03.2018 23:11
we have an school asignment - Не вовлекайте меня в свои задания.
Ed Heal 21.03.2018 23:12

@EdHeal - справедливо участвовать в заданиях, если спрашивающий приложил усилия, чтобы выполнить работу, но застрял. Я возражаю против того, чтобы текст задания просто вставлялся как вопрос.

pm100 21.03.2018 23:14

«мы» подразумевает владение. "пожалуйста, помогите мне с ..." было бы лучше

Ed Heal 21.03.2018 23:16

@IharobAlAsimi Поскольку original не изменяется в цикле, я ожидаю, что оптимизатор предварительно вычислит длину строки и заменит условие цикла for этим значением, вместо того, чтобы каждый раз вызывать strlen, нет? Вероятно, все еще не так эффективно, как то, что вы предлагали, но я бы не ожидал значительного снижения производительности от использования strlen. Просто интересно outloud, ни одной сборки не смотрел.

yano 21.03.2018 23:22

Строки должны заканчиваться '\0'. Перед (*size)++; делайте: result[*size][str_begin] = 0;

Pablo 21.03.2018 23:24

С какой реальной проблемой вы столкнулись / что не работает? А что вам говорит ваш отладчик?

Stephan Lechner 21.03.2018 23:25

Сделайте копию original, а затем используйте strtok() и strcpy().

Barmar 21.03.2018 23:25

... или используйте strchr, memcpy и завершите строки назначения.

Stephan Lechner 21.03.2018 23:27

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

pm100 21.03.2018 23:29

@yano правильно. Как я правильно помню, strlen просто использует приведение к unsigned для проверки 4-х символов на итерацию вместо 1. Вы не увидите большой измеримой разницы, пока не будете работать со строками из многих сотен (или тысяч) символов. (Я проводил тесты, потому что запоминающийся ум просто должен знать ....)

David C. Rankin 21.03.2018 23:31

@yano, Предположим, что это правда. Оптимизатор обнаружил, что перемешивание не изменилось, и заменил вызов на фиксированную длину. Он по-прежнему выглядит как PHP и заслуживает того, чтобы его изменили. К тому же original[i] != '\0' более идиоматичен.

Iharob Al Asimi 21.03.2018 23:42

@ pm100 пытался, чтобы даже мой учитель не мог сказать, что не работает, я полагаю, это было что-то с указателем, я еще не очень хорошо их понимаю

Adrian Grupaty Chlpik 22.03.2018 00:57
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
14
322
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Идея нормальная, но у вас есть пара ошибок:

Ваши строковые копии не завершаются '\0'. Также вы не принимаете учетная запись, когда несколько разделителей следуют подряд.

Если вам не разрешено использовать такие функции, как strchr и strncpy, тогда вы можете сделать это:

size_t str_begin = 0;
*size = 0; // the user may have passed an uninitialized int variable

for(size_t i = 0; original[i] && *size < 50; ++i)
{
    if (original[i] == delim)
    {
        size_t sublen = i - str_begin;
        if (sublen == 0)
        {
            // skip delimiter, last character was also a
            // delimiter and/or the first character in
            // original is a delimiter
            str_begin++;
            continue;

            // or if you want to have empty words instead of skipping
            // results[*size] = 0;
            // (*size)++;
        }

        if (sublen > 256)
            sublen = 256;

        for(size_t j = 0; j < sublen; ++j)
            result[*size][j] = original + str_begin + j;

        result[*size][j] = 0; // \0-terminating string

        (*size)++;
        str_begin = i + 1; // updating str_begin to next char
    }
}

Самый простой способ сделать это - как предложил Бармар - сделать копию исходной строки, а затем работать с strtok() и strcpy.

В качестве альтернативы вы можете использовать strchr в цикле для поиска разделителей и memcpy для копирования памяти между предыдущим разделителем и следующим. См. Следующий код, который также учитывает границы результирующего массива:

void stringSplit(const char *original, char result[50][256], int *size, char
                 delim)
{
    if (!original){
        return ;
    }

    *size = 0;
    const char* nextDelim;
    const char* prevDelim = original;
    do  {
        nextDelim = strchr(prevDelim,delim);
        size_t len = nextDelim ? (nextDelim - prevDelim) : strlen(prevDelim);
        if (len >= 256) {
            len = 256-1;
        }
        memcpy(result[*size],prevDelim,len);
        result[*size][len] = '\0';
        (*size)++;
        prevDelim = nextDelim ? nextDelim+1 : NULL;
    }
    while(nextDelim && *size < 50);
}

int main() {

    char result[50][256];
    int  size;
    stringSplit("Hello, this, is", result, &size, ',');

    return 0;

}

Надеюсь, поможет.

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