Не могу создать функцию, которая вырезает часть массива символов (C99) - PullRequest
1 голос
/ 10 апреля 2020

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

Я получаю ошибка SIGSEGV (ошибка сегментации) во время работы с отладчиком при "Str [Pos] = 0". Я не понимаю, почему, потому что я просто пытаюсь сделать указатель на символ в этой указанной c позиции равным 0 или '\ 0', чтобы он действовал так, как будто это конец массива.

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

#include <string.h>

int main(int argc, char **argv)
{
    char * String = malloc(512);
    String = "Blobfish is the best creature ever made by nature";

    CutString(String, 3, 4);

    print("%s", String);
}

bool CutString(char * Str, int Pos, int Size)
{
    int StrLen = strlen(Str);
    printf("After4\n");

    if (Size < 1 || Size + Pos > StrLen) return true;
    printf("After4.1\n");

    char * StrPos = Str + Pos + Size;
    printf("After4.2\n");
    printf("%s", StrPos);

    Str[Pos] = 0;

    printf("After4.3\n");

    strcat(Str, StrPos);
    printf("After4.4\n");

    return false;
}

Заранее благодарю за помощь и заботу в эти времена, Жюль.

Ответы [ 3 ]

1 голос
/ 10 апреля 2020

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

char * String = malloc(512);
String = "Blobfish is the best creature ever made by nature";
CutString(String, 3, 4);
//...

Кроме того, происходит утечка памяти, поскольку сначала выделяется память, а указатель на память назначается указателю String. И тогда указатель String был переназначен с адресом строкового литерала. Таким образом, адрес выделенной памяти теряется.

Что касается функции, то ее можно определить следующим образом, как показано в демонстрационной программе ниже.

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

char * CutString( char * s, size_t pos, size_t n )
{
    size_t length = strlen( s );

    if ( pos < length )
    {
        n = length - pos < n ? length - pos : n;

        memmove( s + pos, s + pos + n, length - pos - n + 1 );
    }

    return s;
}

int main(void) 
{
    char s[]  = "Blobfish is the best creature ever made by nature";

    puts( s );
    puts( CutString( s, 3, 4 ) );

    return 0;
}

Вывод программы is

Blobfish is the best creature ever made by nature
Bloh is the best creature ever made by nature

Обратите внимание на то, что нет особого смысла, когда функция имеет тип возврата bool. Гораздо лучше, когда такая функция возвращает указатель на саму строку после ее модификации. Все стандартные строковые функции C следуют этому соглашению.

1 голос
/ 10 апреля 2020

Код пытается изменить строковый литерал , что означает неопределенное поведение .

Вместо этого измените выделенную память.

char * String = malloc(512);

// The below only copies the pointer to the string literal, not the string contents.
// String = "Blobfish is the best creature ever made by nature";

strcpy(String, "Blobfish is the best creature ever made by nature");
0 голосов
/ 10 апреля 2020

Я не могу точно сказать, что вы пытаетесь сделать с этой функцией. Но я выделил пару проблем:

Это вызовет у вас проблемы. Поскольку Size + Pos всегда должен быть больше, чем StrLen. Так как Стрлен должен быть равным размеру.

if (Size < 1 || Size + Pos > StrLen) return true;

Перепишите его как:

if (Size < 1 ||  Pos > StrLen)
{
    return true;  
}

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

char * StrPos = Str + Pos + Size;

Исправьте это следующим образом:

char * StrPos = &Str[Pos];

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

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

bool CutString(char * Str, int Pos, int Size)
{
    int StrLen = strlen(Str);

    if (Size < 1 ||  Pos > StrLen)
    {
        return true;  
    }

    char * StrPos = &Str[Pos];

    printf("%s\n", StrPos);

    strcat(Str, StrPos);
    printf("%s", Str);

    return false;
}

int main()
{
    char input[26] = "WhatDoesThisDo?";
    CutString(input,5,14);

    return 0;
}
...