C: если внутри строки существует подстрока, измените строчные буквы на строчные - PullRequest
0 голосов
/ 14 января 2019

Я пишу программу для заглавных букв подстрок в строке на C.

Вот примеры, иллюстрирующие мой ожидаемый результат:

String:    "hello world"
Substring: "wo"
Output:    "hello WOrld"
String:    "I don't know how to do this"
Substring: "do" 
Output:    "I DOn't know how to DO this"
String:    "mouse is useful thing"
Substring: "use" 
Output:    "moUSE is USEful thing"
String:    "replace occurrences of 'r'"
Substring: "r" 
Output:    "Replace occuRRences of 'R'"

По сути, везде, где есть подстрока в строке, прописные буквы в исходной строке.

Вот мой код:

void replaceSubstring(char *str, char *substr) {
    char *p = str;
    char *k = substr;
    int substringLength = strlen(k);

    while (*p)
    {
        if (strncmp(p, k, substringLength) == 0)
        {
            for (p; p < p + substringLength; p++)
            {
                *p = *p - 32;
            }
        }
        p++;
    }
    puts(p);
    printf("\n"); 
}

Однако мой код не работает. Мой подход заключается в том, чтобы выполнить цикл, пока символ не является '\0', и проверить, находится ли подстрока где-то в строке (используя функцию strncmp), и если это так, я бы хотел изменить значение *p на заглавная буква путем уменьшения значения ASCII на 32.

Почему это не работает? Где ошибка?

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Для одной строки и одного шаблона вы можете использовать kmp.

https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/

Для набора строк и одного шаблона может потребоваться алгоритм на основе fsm.

https://www.geeksforgeeks.org/finite-automata-algorithm-for-pattern-searching/

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

0 голосов
/ 14 января 2019

Основная проблема с вашим внутренним циклом заключается в том, что p нельзя использовать одновременно как цель завершения (p + substringLength) и в качестве счетчика. Это как сказать for (int i = 0; i < i + 10; i++). i когда-нибудь достигнет i + 10?

Вы можете попробовать установить p + substringLength в переменную len, а затем использовать эту фиксированную стойку ворот в качестве условия завершения цикла.

Во-вторых, используйте toupper() для преобразования символов. В противном случае пробелы и неалфавитные символы также будут изменены, что приведет к неожиданному поведению. Например, пробелы будут превращены в нулевые завершающие символы, лишающие сироты конца строки.

Если сложить все вместе, получится:

for (char *len = p + substringLength; p < len; p++)
{
    *p = toupper(*p);
}

Наконец, puts(p); не работает так, как вы ожидаете. К концу функции p использовался для перебора строки и теперь указывает на конец строки, а не на начало. Используйте puts(str); или просто печатайте из области вызова, чтобы избежать побочных эффектов .

Вот полный пример:

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

void replaceSubstring(char *str, char *substr) {
    char *p = str;
    int substringLength = strlen(substr);

    while (*p)
    {
        if (strncmp(p, substr, substringLength) == 0)
        {
            for (char *len = p + substringLength; p < len; p++)
            {
                *p = toupper(*p);
            }
        }

        p++;
    }
}

int main(void) {
    char s[12] = "hello world";
    replaceSubstring(s, "llo wor");  
    printf("%s\n", s);
    replaceSubstring(s, "ll");  
    printf("%s\n", s);
    replaceSubstring(s, "h");  
    printf("%s\n", s);
    replaceSubstring(s, "hello worldz");  
    printf("%s\n", s);

    char t[28] = "i don't know how to do this";
    replaceSubstring(t, "do");  
    printf("%s\n", t);
    replaceSubstring(t, "'t know");  
    printf("%s\n", t);
    return 0;
}

Выход:

heLLO WORld
heLLO WORld
HeLLO WORld
HeLLO WORld
i DOn't know how to DO this
i DOn'T KNOW how to DO this

Попробуйте!

...