PDA

Просмотр полной версии : Помогите исправить ошибку в задаче на символьные массивы (язык C)



Katiox-xa
02.10.2008, 09:43
Здравствуйте,
Помогите, пожалуйста исправить ошибку в программе, написанную на языке С
В некоторых случаях не работает
Например в строке dshfhjd hjghjg
Выводит hjd


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



#include <stdio.h>
#define MAXLINE 100

void main (void)
{
int f;
int i, j, k, p, i2, t;
char c;
char str1[MAXLINE];
char str2[MAXLINE]="";
i2=0;
i=0;
while ( (c=getchar())!=EOF && c!='\n')
{
str1[i]=c;
++i;
}
if (c=='\n')
{
str1[i]=c;
++i;
}
str1[i]='\0';

i=p=f=t=0;
while (str1[i]!='\0')
{
if ((str1[i]==' ') || (str1[i]=='.') || (str1[i]=='\n') || (str1[i]==', '))
{
i2=i-1;
if (str1[p]==str1[i2])
f=f+1;
p=i+1;
}
if (f!=0)
{
for (f=t; f<=(t+i-i2+1); f+=1)
str2[f]=str1[i2+f-t-2];
t=f;
f=0;
}
i++;
}
printf ("%s\n", str2);
}

Albor
02.10.2008, 19:59
Несколько сумбурно. Алгоритм должен быть примерно такой: делим входной массив на слова, из этих слов выбираем те у которых крайние символы равны. Важно правильно найти начало и конец слова. Можно воспользоваться функциями STL, например, isalpha(), определяющей, является ли символ буквой, или isspace() - является ли пробелом, или ispunct() - является ли знаком пунктуации.

MrVenom
06.10.2008, 03:07
(Не использовать встроенных функций обработки строк)

а не проще сразу считать строку, а не забивать в массив ее getchar'ом?
getchar полезен тогда, когда посимвольно надо обрабатывать, не храня ничего. Конечно лучше всего и геморнее было б сделать с getcharom и динамическим распределением памяти, но мне лень))) ща так сделаю, если захочешь - переделаешь потом.

MrVenom
06.10.2008, 03:54
Извиняюсь)) ты был прав. Вот код, вроде работает:)))))

#include <iostream>
using namespace std;
void main(){
cout << "Input string:";
bool space = false;
char out[100], temp[25], c;
int i = 0, i1 = 0;
while ((c = getchar())) {
if ((c != ' ') && (c != '\n')) {
temp[i] = c;
i++;
} else
if ((c == ' ') || (c == '\n')){
if (temp[0] == temp[i-1]) {
for (int j = 0; j < i; j++) {
out[i1] = temp[j];
i1++;
}
out[i1] = ' ';
i1++;
}
i = 0;
}
if (c == '\n') {
out[i1] = '\0';
break;
}
}
cout << "Output string: " << out << "\n";
system("pause");
}

Albor
06.10.2008, 10:49
MrVenom, перечисленные мною функции обрабатывают отдельные символы, а не строки. А для решения данной задачи достаточно одного цикла при считывании строки посимвольно, и, если подумать, то можно обойтись и одним массивом.

MrVenom
06.10.2008, 11:10
Подумал :D вот с одним массивом:

#include <iostream>
using namespace std;
void main(){
cout << "Input string:";
bool space = false;
char out[100], c, first;
bool f = false;
int i = 0, i1 = 0;
while ((c = getchar())) {
if ((c != ' ') && (c != '\n')) {
if (!f) {
first = c;
f = true;
i1 = i;
}
out[i] = c;
i++;
} else
if ((c == ' ') || (c == '\n')){
if (out[i-1] == first) {
out[i] = ' ';
i++;
}
else i = i1;
f = false;
}
if (c == '\n') {
out[i] = '\0';
break;
}
}
cout << "Output string: " << out << "\n";
system("pause");
}

Albor
06.10.2008, 14:12
Подумал :D вот с одним массивом:
:DНу, вот, продолжаем разговор: а если во входной строке появятся запятые или тире, или двоеточие и т.п.? Можно ещё избавиться от "флаговой" переменной типа bool, а также, вместо индекса, запоминающего начало слова, попробовать использовать указатель, а если в условных операторах использовать рекомендуемые выше функции, то получится ещё красивее.

MrVenom
06.10.2008, 17:41
Так:
1. тире, и двоеточия всякие будут расцениватся как обычные символы. т.е. если +выа+ то он это слово добавит.
2. чем тебе bool не нравится?
3. если делать с указателями и ваще динамическим выделением памятигемора пипец будет, но вполне возможно
4. ваще какими функциями можно пользоваться?
Хочешь красиво это тебе в денюшку встанет уже))

Albor
06.10.2008, 18:17
1. В условии сказано о буквах, но ни как не о символах '+' и им подобных.
2.Против типа bool абсолютно ни чего не имею против, но в приведенном листинге много ненужных переменных.
3. А ты попробуй, только память динамически выделять не нужно - это лишнее.
4. Какими хочешь, кроме ф-ций обработки строк (условие запрещает). Можно и без функций, но придётся писать сравнительно длинные выражения в if.
Красиво научиться писать - сделает тебе честь, после чего можно и денюжку попросить. Лично для себя я и сам напишу, если понадобится - в этой теме я не проситель.

MrVenom
06.10.2008, 18:35
1. дык ты описал бы конкретно... символы типа "+" будут расцениватся как буквы. с ними что надо делать тоГ? пропускать или удалять или как, или ошибку выводить?... не вводить тогда да и все. ну будет ddg+dd он его запишет все равно.
2. В твоем коде переменных больше по-моему.
3. что указатель - 4 байта, что инт 4 байта, разницы не вижу.
4. тут сам поправь, легче легкого
А вот оскорблять не надо. тоже могу.

Albor
06.10.2008, 20:23
Ещё раз для тех, кто на бронепоезде: я не автор темы и код ни какой не представлял. Смотри выше.
А какое моё высказывание воспринято как оскорбление?

MrVenom
06.10.2008, 20:28
Блин)) я в бронепоезде))) тут я мешок)))


А какое моё высказывание воспринято как оскорбление?

Красиво научиться писать - сделает тебе честь

Albor
06.10.2008, 20:32
MrVenom, Вы правда считаете, что представили красивый код? Не обижайтесь пожалуйста, ибо ни чего обидного я не пытался вложить в свои слова! Раз вы считаете себя асом в программировании, то пусть так и будет.

MrVenom
06.10.2008, 20:37
Не, я не грю что представил, я грю, что если делать красиво с точки зрения расхода памяти, то это надо думать))) А асом не считаю)) нет предела совершенству)) Расфлудились блин... Мир))

Albor
06.10.2008, 22:15
Вот мой вариант. Не судите строго, ибо не сделана проверка выхода за пределы массива и не учитывается регистр букв, оставляю это автору поста. Хотелось показать, что можно обойтись без флагов и индексов.


#include"iostream"
using namespace std;
void main()
{
cout << "Input string:";
char out[100]={0};// выходной массив
char c;
const char chSep(' ');//разделитель слов в результирующей строке
char *pFirst=out;// указатель на первую букву считанного слова
char *pLast=out;// указатель на последнюю букву считанного слова
while ((c = getchar())!='\n')
{
if (isalpha(c)) // если буква
{
*pLast++=c;// сохраняем в массиве
*pLast=0;//затираем следующий символ
}
else //любой другой символ считается разделителем слов
{
if(*pFirst!=*(pLast-1))
{
pLast=pFirst;// возвращаемся в начало только что считанного слова, не удовлетворяющего условию
*pLast=0;// вставляем конец строки
}
else
{
pFirst=pLast+1;//готовим место для следующего слова
*pLast++=chSep;// вставляем сепаратор
}
}
}
cout << "Output string: " << out << "\n";
system("pause");
}

Katiox-xa
08.10.2008, 20:44
Всем спасибо большое