Обработка строки с помощью указателей на Си
"Ввести символьную строчку.
Программа должна удалить все слова состоящие из 5-ти букв. Обработка строки должна быть выполнена с помощью указателя.
Язык СИ Only".
Как сделать это по человечески я не знаю, поэтому сотворил "хитрый план".:rolleyes: Выглядит он так:
_____________________________________________________________
#include <string.h>
void main(void)
{
char s[100];
char *p, *f;
gets(s);
p = &s[0];
f = &s[0];
while (*f!='\0')
{
p=p+5;
if (*p==' ' || *p=='\t' || *p!='\0')
{
while (f!=p)
{
*f='\0';
f=f+1;
}
p=p+1;
*f='\0';
f=f+1;
}
else
{
while (*f!=' ' || *f!='\t' || *p!='\0')
f=f+1;
f=f+1;
p=f;
}
}
puts(s);
}
___________________________________________________________
Разумеется эта программа не работает. Да :confused:
Пожалуйста, помогите найти ошибку в коде. Или подскажите нормальный способ решение поставленной задачи.
Заранее спасибо
Названия переменных s, p, f ни о чём не говорят. Дайте им осмысленные названия.
Функция gets устарела - чревато переполнением буфера.
Какой функцией в пределах Си заменить gets?
Можно использовать дополнительную строку, в которую будет помещаться результат без этих 5-буквенных слов. Так наиболее удобно, думаю.
Можно конечно обойтись и без дополнительной строки, а, например, каждый раз при нахождении слова сдвигать массив на нужное число символов, но тут больше возни.
Да. Слова могут разделаться не только пробелами, но и знаками препинания. Но это тонкости.
Написано вместе. Уважаю.
Да, именно так.
Это здорово. Только вот как указателями отделить эти слова и перекидать остальные в другую строчку?
Я знал что пригодится ^^
В принципе, наверное можно и с одной обойтись. Тут нужно 2 указателя, как у вас, и счетчик числа букв слова. Тогда в цикле проходим первым указателем по строке, анализируя с помощью счетчика длину слов. С помощью второго указателя копируем символы с позиции первого. Если обнаружена ситуация с пятибуквенным словом, то возвращаем второй указатель на нужное количество символов назад.
Счетчик должен работать так: если указываем на букву, счетчик инкрементируется, если на пробел (точку, запятую и т.д.), то анализируется значение счётчика, после чего он сбрасывается в ноль.
[QUOTE=Phodopus;332325]Строку надо просто вывести без этих слов или преобразовать в буфере?
Да, именно так.
[/QUOTE]
Афтор, своим ответом ты просто вынес мой моцк...
2Phodopus Пожалуйста ^^
ТС, раз уж написали программку - поделитесь кодом с сообществом, мы покритикуем, авось ошибки найдём, подскажем чо.
Вот мой вариант. Результирующая строка помещается в другой буфер. Как известно, хороший программист - ленивый программист :). Поэтому целенаправленно писал как можно короче. Использовал стандартные функции strcspn и strspn. Хотя по скорости такой код неоптимален.
#define SIZE 100
void main()
{
char str[SIZE]; // буфер для ввода строки с консоли
char res[SIZE] = ""; // итоговая строка
char *ptr = str;
// здесь код для ввода строки с консоли
// ...
// Удаляем из строки все слова в пять символов (кроме пробелов и табов)
while(*ptr)
{
size_t count = strcspn(ptr, " \t"); // можно дополнить другими символами
if (5 != count)
strncat(res, ptr, count);
ptr += count;
count = strspn(ptr, " \t"); // можно дополнить другими символами
strncat(res, ptr, count);
ptr += count;
}
puts(res);
}
Теперь о вводе строки с консоли. Вместо небезопасной функции gets можно использовать fgets
fgets(str, SIZE, stdin); // в буфер вводится и символ перевода строки
end = strlen(str) - 1;
if (str[end] == '\n')
str[end] = '\0'; // убираем символ перевода строки
или scanf
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'
Строка формата весьма хитрая: чтобы буфер не переполнился, указываем максимальное количество вводимых символов (в данном случае 99 при размере буфера 100 - один знак под терминальный ноль); используется знак 'c', а не 's' - в таком случае можно будет ввести не одно слово, а именно строку (с пробелами); чтобы ввод прекращался по нажатию Enter - указываем [^\n]. При этом нужно убрать из буфера консоли оставшийся там символ клавиши Enter, иначе последующая функция ввода может сработать не правильно.
На тот случай, если память под вводимую строку выделяется динамически (malloc) и размер буфера при компиляции неизвестен, строку формата тоже формируем динамически. Например, так
sprintf(format, "%%%d[^\n]c", SIZE - 1);
scanf(format, str);
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'
Вроде работает :).
Счётчик букв и отступов назад второго указателя получился такой ЕдрЁный, что я им даже горжусь :) и даже не до конца понимаю как он у меня работает, но РАБОТАЕТ!)
#include <string.h>
void main(void)
{
char s[10000];
char d[10000];
char *p, *f;
int n, u;
n = 0;
u = 0;
gets(s);
p = &s[0];
f = &d[0];
while (*p!='\0')
{
if (*p==' ' || *p=='\t' || *p=='\0')
{
n=0;
}
else
{
n++;
}
if (n==5 && (*(p+1)==' ' || *(p+1)=='\t' || *(p+1)==','))
{
f=f-4;
u++;
p=p+2;
n=1;
}
*f=*p;
p++;
f++;
if (n==5 && *p=='\0')
{
f=f-5;
u++;
*f='\0';
}
}
if (*f!='\0')
*f='\0';
printf ("\n\nstring 1 - %s\n", s);
printf ("string 2 - %s\n\n", d);
printf (" - %d words\n\n",u);
}
Коротко и простенько
sprintf(format, "%%%d[^\n]c", SIZE - 1);
scanf(format, str);
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'
Если я правильно понимаю,\n попадёт в буфер,только если было введено столько символов,что перевод строки в буфер уже не влез.А вот если было введено меньше,всё в буфер влезет и [FONT="Courier New"]getchar();[/FONT],сдаётся мне,будет уже ждать ввода символа
Немножко не так: если будет введено количество символов меньше, чем указано, то в буфере консоли останется \n (в нашу строку он не попадёт, т. к. указано [^\n] ). И в этом случае может нарушиться работа последующего оператора ввода с консоли (если таковой есть в программе). Поэтому нужен getchar.
А вот если символов будет введено больше, чем указано, то в нашу строку попадёт указанное количество. И в буфере консоли останутся лишние символы. Тут getchar не в тему. Да, scanf даже с такой мудрёной строкой формата работает не совсем хорошо. Помнится, я изобретал этот способ, когда не знал простого способа с fgets.
Топикстартеру:
в общем, я ожидал увидеть нечто подобное: без единого комментария...
А проблема переполнения буфера решена его увеличением :rolleyes: