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

У меня есть две строки в стиле C:

char st[100] = "to be  or not to be ";
char sub_s[100] = "be";

Мне нужно найти начало "быть" с strstr(st, sub_s) и измените его на заглавные буквы. Новая строка должна быть "" быть или не быть ";

Мне удается сделать это без функции так:

void main()
{
    char st[100] = "to be  or not to be ";
    char sub_s[100] = "be";
    char* p;
    int i;

    while (p = strstr(st, sub_s))
    { 
        for (i = 0; i < strlen(sub_s); i++)
        {
            p[i] -= 32;
        }
    }

    printf("%s\n", st);
}

Но когда я помещаю этот код в его собственную функцию, он больше не работает:

void main()
{
    char st[100] = "to be  or not to be ";
    char sub_s[100] = "be";
    replaceSubstring(st, sub_s);
}

void replaceSubstring(char* str, char* substr)
{
    int* p;
    int i;

    while (p = strstr(str, substr))
    { 
        for (i = 0; i < strlen(substr); i++)
        {
            p[i] -= 32;
        }
    }

    printf("%s\n", st);
}

Что тут происходит?

1 ответ

В функции, которую вы написали, вы установили тип p быть int*не char *, Это значит когда пишешь

p[i] -= 32;

компилятор примет каждый элемент, на который указывает p является int и, следовательно, сделать шаг размера sizeof(int) в памяти, а не шаг размером 1 в памяти. Другими словами, код интерпретируется как

Start at the location pointed at by p.
Jump forward i * sizeof(int) bytes.
Read an integer value from that location.
Subtract 32 from it.
Write it back

скорее, чем

Start at the location pointed at by p.
Find the character i steps down from there.
Subtract 32 from that character.

Чтобы это исправить, измените тип p быть char*не int*,

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

Некоторые другие случайные заметки:

  1. Тип возврата main должно быть intне void,
  2. Вместо того, чтобы вычитать 32 из каждого символа, который работает, но не самая ясная вещь в слове, рассмотрите использование tolower функция от <ctype.h> заголовок.
  3. Если искомая подстрока состоит исключительно из буквенных символов (скажем, ":-)"), то этот код может вызвать бесконечный цикл. Вы понимаете почему? Подумайте, как вы можете это исправить.
Другие вопросы по тегам