Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Обработка строки с помощью указателей на Си

62K
20 сентября 2010 года
RXBlackon
8 / / 20.09.2010
Доброе время суток. Обращаюсь я к вам по причину поступившего задания

"Ввести символьную строчку.
Программа должна удалить все слова состоящие из 5-ти букв. Обработка строки должна быть выполнена с помощью указателя.
Язык СИ Only".

Как сделать это по человечески я не знаю, поэтому сотворил "хитрый план".:rolleyes: Выглядит он так:
_____________________________________________________________
Код:
#include <stdio.h>
#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:

Пожалуйста, помогите найти ошибку в коде. Или подскажите нормальный способ решение поставленной задачи.
Заранее спасибо
297
20 сентября 2010 года
koodeer
1.2K / / 02.05.2009
Используйте тэги [noparse]
 
Код:
 
[/noparse] для вставки своего кода в сообщение. Без них код нечитаем.

Названия переменных s, p, f ни о чём не говорят. Дайте им осмысленные названия.

Функция gets устарела - чревато переполнением буфера.
62K
20 сентября 2010 года
RXBlackon
8 / / 20.09.2010
Код добавил. Теперь читаемее.
Какой функцией в пределах Си заменить gets?
14
21 сентября 2010 года
Phodopus
3.3K / / 19.06.2008
Строку надо просто вывести без этих слов или преобразовать в буфере?
87
21 сентября 2010 года
Kogrom
2.7K / / 02.02.2008
Цитата: RXBlackon
Или подскажите нормальный способ решение поставленной задачи.


Можно использовать дополнительную строку, в которую будет помещаться результат без этих 5-буквенных слов. Так наиболее удобно, думаю.

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

Да. Слова могут разделаться не только пробелами, но и знаками препинания. Но это тонкости.

Цитата: RXBlackon
Заранее



Написано вместе. Уважаю.

62K
23 сентября 2010 года
RXBlackon
8 / / 20.09.2010
Цитата: Phodopus
Строку надо просто вывести без этих слов или преобразовать в буфере?


Да, именно так.

Цитата: Kogrom
Можно использовать дополнительную строку, в которую будет помещаться результат без этих 5-буквенных слов. Так наиболее удобно, думаю.


Это здорово. Только вот как указателями отделить эти слова и перекидать остальные в другую строчку?

Цитата: Kogrom
Уважаю.


Я знал что пригодится ^^

87
23 сентября 2010 года
Kogrom
2.7K / / 02.02.2008
Цитата: RXBlackon
Только вот как указателями отделить эти слова и перекидать остальные в другую строчку?



В принципе, наверное можно и с одной обойтись. Тут нужно 2 указателя, как у вас, и счетчик числа букв слова. Тогда в цикле проходим первым указателем по строке, анализируя с помощью счетчика длину слов. С помощью второго указателя копируем символы с позиции первого. Если обнаружена ситуация с пятибуквенным словом, то возвращаем второй указатель на нужное количество символов назад.

Счетчик должен работать так: если указываем на букву, счетчик инкрементируется, если на пробел (точку, запятую и т.д.), то анализируется значение счётчика, после чего он сбрасывается в ноль.

14
24 сентября 2010 года
Phodopus
3.3K / / 19.06.2008
Цитата: RXBlackon

[QUOTE=Phodopus;332325]Строку надо просто вывести без этих слов или преобразовать в буфере?


Да, именно так.
[/QUOTE]
Афтор, своим ответом ты просто вынес мой моцк...

62K
24 сентября 2010 года
RXBlackon
8 / / 20.09.2010
2Kogrom Спасибо! большое. теперь она работает. Я рад
2Phodopus Пожалуйста ^^
297
25 сентября 2010 года
koodeer
1.2K / / 02.05.2009
Эх, напишу!
ТС, раз уж написали программку - поделитесь кодом с сообществом, мы покритикуем, авось ошибки найдём, подскажем чо.

Вот мой вариант. Результирующая строка помещается в другой буфер. Как известно, хороший программист - ленивый программист :). Поэтому целенаправленно писал как можно короче. Использовал стандартные функции strcspn и strspn. Хотя по скорости такой код неоптимален.
Код:
#include<string.h>
#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
 
Код:
size_t end;
fgets(str, SIZE, stdin); // в буфер вводится и символ перевода строки

end = strlen(str) - 1;
if (str[end] == '\n')
    str[end] = '\0'; // убираем символ перевода строки

или scanf
 
Код:
scanf("%99[^\n]c", str);
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'

Строка формата весьма хитрая: чтобы буфер не переполнился, указываем максимальное количество вводимых символов (в данном случае 99 при размере буфера 100 - один знак под терминальный ноль); используется знак 'c', а не 's' - в таком случае можно будет ввести не одно слово, а именно строку (с пробелами); чтобы ввод прекращался по нажатию Enter - указываем [^\n]. При этом нужно убрать из буфера консоли оставшийся там символ клавиши Enter, иначе последующая функция ввода может сработать не правильно.

На тот случай, если память под вводимую строку выделяется динамически (malloc) и размер буфера при компиляции неизвестен, строку формата тоже формируем динамически. Например, так
 
Код:
char format[10];
sprintf(format, "%%%d[^\n]c", SIZE - 1);

scanf(format, str);
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'

Вроде работает :).
62K
25 сентября 2010 года
RXBlackon
8 / / 20.09.2010
Окей, я поделюсь с общественностью кодом что у меня получился.
Счётчик букв и отступов назад второго указателя получился такой ЕдрЁный, что я им даже горжусь :) и даже не до конца понимаю как он у меня работает, но РАБОТАЕТ!)

Код:
#include <stdio.h>
#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);
}


Коротко и простенько
7
25 сентября 2010 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: koodeer
 
Код:
char format[10];
sprintf(format, "%%%d[^\n]c", SIZE - 1);

scanf(format, str);
getchar(); // нужно для извлечения из буфера консоли оставшегося там символа '\n'

Если я правильно понимаю,\n попадёт в буфер,только если было введено столько символов,что перевод строки в буфер уже не влез.А вот если было введено меньше,всё в буфер влезет и [FONT="Courier New"]getchar();[/FONT],сдаётся мне,будет уже ждать ввода символа

297
28 сентября 2010 года
koodeer
1.2K / / 02.05.2009
Цитата: @pixo $oft
Если я правильно понимаю,\n попадёт в буфер,только если было введено столько символов,что перевод строки в буфер уже не влез.А вот если было введено меньше,всё в буфер влезет и [FONT="Courier New"]getchar();[/FONT],сдаётся мне,будет уже ждать ввода символа



Немножко не так: если будет введено количество символов меньше, чем указано, то в буфере консоли останется \n (в нашу строку он не попадёт, т. к. указано [^\n] ). И в этом случае может нарушиться работа последующего оператора ввода с консоли (если таковой есть в программе). Поэтому нужен getchar.

А вот если символов будет введено больше, чем указано, то в нашу строку попадёт указанное количество. И в буфере консоли останутся лишние символы. Тут getchar не в тему. Да, scanf даже с такой мудрёной строкой формата работает не совсем хорошо. Помнится, я изобретал этот способ, когда не знал простого способа с fgets.




Топикстартеру:
в общем, я ожидал увидеть нечто подобное: без единого комментария...
А проблема переполнения буфера решена его увеличением :rolleyes:

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог