#c #string
Вопрос:
Ситуация следующая: В первой строке введите строку, затем следующие строки — «команда». 2 типа команд » p » и «s», » p «означает печать строки,» s » означает подстановку. например, Введите строку aaabbbcccqwerdd, затем введите sbqwerbkkk (s означает подстановку, b действует как разделитель, поэтому это означает замену qwer в строке на kkk) Ожидаемый результат должен быть aaabbbccckkkdd, но вместо этого я получил aaabbbccckkkrdd Какая-нибудь помощь?
#include lt;stdio.hgt; #include lt;stdlib.hgt; #include lt;string.hgt; #define MAXLEN 1023 int main() { char str[MAXLEN]; scanf("%s", str); char command[MAXLEN]; while (scanf("%s", command) != EOF) { if (command[0] == 'p') { printf("%sn", str); } else if (command[0] == 's') { char delimiter[] = {"0"}; strncpy(delimiter, command 1, 1); char *a = command; a = strtok(command, delimiter); a = strtok(NULL, delimiter); char *b = command; b = strtok(NULL, delimiter); int alength = strlen(a); int blength = strlen(b); char *bereplaced = strstr(str, a); if (bereplaced == NULL) { continue; } int aindex = bereplaced - str; strncpy(str aindex, b, blength); } } return 0; }
Комментарии:
1. Ручка и бумага-ваши друзья здесь! Нарисуйте строки на бумаге, используя квадраты для отдельных символов. Используйте это, чтобы определить индексы или указатели, из которых вам нужно скопировать каждую часть каждой строки, и как получить длину. Сделайте это для нескольких разных строк и не забудьте включить как меньшие, равные, так и большие замены. Как только это начнет работать, определите функции, необходимые для получения индексов или указателей и длин, и начните реализацию. И не волнуйтесь, код никогда не будет выглядеть очень красиво. И выделите его в отдельную функцию, чтобы сделать его более простым и удобным в обслуживании.
2. С точки зрения реализации я бы на самом деле рекомендовал две функции «замены»: одну для замены с использованием индексов; И одну с использованием разделителей. Функция-разделитель находит индексы и использует первую функцию на основе индексов.
3. Неправильно выполнять strtok один раз для одного разделителя, а другой раз для другого разделителя, так как первый вызов изменяет начальный ввод.
Ответ №1:
Здесь многое может пойти не так, но главная проблема заключается в копировании из исходной строки в саму себя, может возникнуть перекрытие памяти. Вместо этого объявите новый буфер для результата операции поиска/замены.
Вы можете определить отдельную find_replace
функцию следующим образом:
char* find_replace(const char* src, const char* find, const char* replace) { if (!src) return NULL; char* find_ptr = strstr(src, find); if (!find_ptr) return NULL; int find_start = find_ptr - src; int find_length = strlen(find); char* result = malloc(strlen(src) strlen(replace) 1); strncpy(result, src, find_start); strcpy(result find_start, replace); strcat(result, find_ptr find_length); return result; } int main() { char source[] = "aaabbbcccqwerdd"; char command[] = "sbqwerbkkk"; if (command[0] != 's') return 0; char delimiter[] = { "0" }; delimiter[0] = command[1]; char* find = strtok(command, delimiter); if (!find) return 0; find = strtok(NULL, delimiter); if (!find) return 0; char* replace = strtok(NULL, delimiter); if (!replace) return 0; char* result = find_replace(source, find, replace); if (!result) return 0; printf("%sn", result); free(result); return 0; }
Ответ №2:
Вот еще одно решение. Он выполняет подстановку непосредственно во входную строку с помощью:
- Используется
memmove
для перемещения конечной части исходной строки в ее конечное местоположение - Используется
strncpy
для копирования подстроки-замены в ее конечное расположение
Нравится:
#include lt;stdio.hgt; #include lt;string.hgt; #define MAXLEN 1023 int main(void) { char str[MAXLEN] = "aaabbbcccqwerdd"; char command[MAXLEN] = "sbqwerbkkk"; printf("COMMAND : %sn", command); printf("TEXT BEFORE : %sn", str); char* pfind = command 2; // skip initial sb char* psub = strchr(pfind, 'b'); // find delimiter *psub = ''; // terminate replace string psub; // point to substitute substring size_t flen = strlen(pfind); // calculate length size_t slen = strlen(psub); // calculate length char* p = strstr(str, pfind); // find location of replace string size_t sc = strlen(p); // calculate length memmove(p slen, p flen, sc - flen 1); // Move trailing part strncpy(p, psub, slen); // Put in substitute substring printf("TEXT AFTER : %sn", str); return 0; }
Выход:
COMMAND : sbqwerbkkk TEXT BEFORE : aaabbbcccqwerdd TEXT AFTER : aaabbbccckkkdd
Раскрыватель
Чтобы сократить пример кода, приведенный выше код слепо верит в то, что команда и исходная строка образуют законную замену и что для результата достаточно памяти.
В реальном коде вам нужно это проверить. Например, проверьте это strchr
и strstr
не возвращает значение NULL.