Можете ли вы помочь мне найти проблему с этим базовым кодом C

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

В вопросе предлагается написать функцию с именем censor, которая изменяет строку, заменяя каждое вхождение foo на xxx.

Мой код:

int main()
{
    char msg[] = "I love food, you fool.";

    censor(msg);

    puts(msg);

    return 0;
}

void censor(char *str) {
    char *c = str;
    while (c+2 != '\0') {
        if (*c == 'f' && *(c+1) == 'o' && *(c+2) == 'o')
            *c = *(c+1) = *(c+2) = 'x';
        c++;
    }
}

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


person Manish    schedule 21.10.2020    source источник
comment
*(c+i) встречается чаще, чем c[i], даже *c обычно пишется как c[0]   -  person pmg    schedule 21.10.2020


Ответы (2)


Вы проверяете значение указателя, а не то, на что он указывает. Итак, вместо этого:

while (c+2 != '\0') {

Вы хотите это:

while (*(c+2) != '\0') {
person dbush    schedule 21.10.2020
comment
т.е. читайте предупреждения компилятора, как обычно. Даже после исправления этого с помощью предложенного ответа подумайте, как он все равно будет сломан, если когда-либо будет передана односимвольная строка или даже пустая строка. Можно также усомниться в самом существовании c, поскольку вместо этого вы можете легко пройтись по строке с помощью str. - person WhozCraig; 21.10.2020

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

Для начала такая строковая функция должна возвращать указатель на измененную строку. То есть возвращаемый тип функции должен быть char * вместо void.

Условие в цикле while

while (c+2 != '\0') {

эквивалентно

while (c+2 != NULL) {

потому что выражение c + 2 имеет тип указателя char *. Так что условие неверное.

Более того, вообще, если вы даже измените условие, например

while ( *( c+2 ) != '\0') {

цикл может иметь неопределенное поведение, если пользователь передаст строку, содержащую менее двух символов.

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

#include <stdio.h>

char * censor( char *s ) 
{
    const char *s1 = "foo";
    const char *s2 = "xxx";
    
    for ( char *p = s; *p; )
    {
        const char *t1 = s1;
        
        while ( *t1 && *t1 == *p )
        {
            ++t1; ++p;
        }
        
        p -= t1 - s1;
        
        if ( *t1 == '\0' )
        {
            for ( const char *t2 =s2; *t2; ++t2 )
            {
                *p++ = *t2;
            }
        }
        else
        {
            ++p;
        }
    }
    
    return s;
}

int main( void ) 
{
    char msg[] = "I love food, you fool.";
    
    puts( msg );
    puts( censor( msg ) );
    
    return 0;
}

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

I love food, you fool.
I love xxxd, you xxxl

Код показанной функции не зависит от строк "foo" и "xxx". Указатели s1 и s2 можно инициализировать любыми другими строками равной длины.

person Vlad from Moscow    schedule 21.10.2020