Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Помощь в написании функций


Автор: babat 6.11.2011, 11:06
Помогите написать функции для работы со строками)
Я несколько написал,но не работают как надо.
1)int strlen(char*s)
2)char*strcpy(char*dest,char*s,int p,int k)
3)char*strdel(char*s,int p,int k)
4)char*strins(char*sub,char*s,int p)
5)int strpos(char*sub,char*s)
6)int strcmp(char*s1,char*s2)
7)char*strcat(char*dest,char*s1,char*s2)
1) strlen -длина строки
2) strcpy-помещает в dest K символов строки S,начиная с Р-го
3) strdel- Удаляет из S K символов,начиная с Р-го
4) strins -  вставляет sub в s с р-й позиции,с предположением,что в S достаточно места
5) strpos - возвращает позицию 1-го вхождения sub в s или -1
6) strcmp- возвращает 0 если строки равны,1 если s1>s2,-1 если s1<s2
7) strcat- Сцепляет s1 и s2 и помещает их в dest  
Задание:реализовать 6 из 7 функции в 4х вариантах каждую.
Вот написал
Код

#include "stdio.h"
#include "conio.h"
#include "string.h"

char*strcpy1(char*dest,char*s,int p,int k)
{
    for (int i=p,j=0;i<p+k;++i,++j)
        dest[j]=s[i];
    return dest;
}
void main()
{
    int k=4,p=3;
    char s[15]="123123412",dest[15];
    printf ("strcpy1(\"%s\",\"%i\",\"%i\")=\"%s\"\n",s,p,k,strcpy1(dest,s,p,k));
    getch();
}

Это без проверок всяких.Почему мусор какой-то выводит?

Автор: tzirechnoy 6.11.2011, 11:17
Как минимум строка не завершэна '\0'. Но, не зная задание, не могу сказать -- это ошыбка реализацыи strcpy1 или Вы неправильно пытаетесь его использовать.

Автор: babat 6.11.2011, 11:32
1) strlen -длина строки
2) strcpy-помещает в dest K символов строки S,начиная с Р-го
3) strdel- Удаляет из S K символов,начиная с Р-го
4) strins -  вставляет sub в s с р-й позиции,с предположением,что в S достаточно места
5) strpos - возвращает позицию 1-го вхождения sub в s или -1
6) strcmp- возвращает 0 если строки равны,1 если s1>s2,-1 если s1<s2
7) strcat- Сцепляет s1 и s2 и помещает их в dest 

Автор: borisbn 6.11.2011, 11:40
Код

char*strcpy1(char*dest,char*s,int p,int k)
{
    for (int i=p,j=0;i<p+k;++i,++j)
        dest[j]=s[i];
    dest[k]=0;  // <---
    return dest;
}

Автор: babat 6.11.2011, 11:49
спасибо,понятно)) видимо я еще не до уонца от паскаля отцепился(
еще вопрос. Почему размер массива нельзя задавать таким способом :
int k=10;
char s[k];
 или
char s[]="12334";
char s1[strlen(s)+1];

Автор: volatile 6.11.2011, 12:49
Цитата(babat @  6.11.2011,  11:49 Найти цитируемый пост)
Почему размер массива нельзя задавать таким способом :

Кое-где можно
http://liveworkspace.org/code/5adb082f5001766f1274d2a304352625

Автор: borisbn 6.11.2011, 16:09
Цитата(volatile @  6.11.2011,  12:49 Найти цитируемый пост)
Кое-где можно

хммм. как это ? там же "галочка" на Си++, а не на Си стоит  smile 

Автор: volatile 6.11.2011, 16:30
Цитата(borisbn @  6.11.2011,  16:09 Найти цитируемый пост)
там же "галочка" на Си++, а не на Си стоит    


borisbn, Ну во первых, я здесь не увидел нигде упоминания, что нужен именно С.

Ну, а раз так, то лёгким движение руки.... программка превращается....превращается... 

http://liveworkspace.org/code/4358235b7ac9f7f93246f38227a92e31

smile 

Автор: babat 6.11.2011, 18:54
Код


#include "stdio.h"
#include "conio.h"
#include "string.h"

char*strins1(char*sub,char*s,int p)
{
    int len=strlen(sub),len1=strlen(s);
    char s1[100];
    for (int i=p,j=0;i<len1;++i,++j)
        s1[j]=s[i];
    s1[len1-p]=0;
    for (int i=p,j=0;i<len+p;++i,++j)
        s[i]=sub[j];
    for (int i=p+len,j=0;i<len+len1;++i,++j)
        s[i]=s1[j];
    s[len+len1]=0;
    return(s);
}
void main()
{
     int p=3;
    char s[15]="123789",sub[15]="456";
    printf("strins1(\"%s\",\"%s\",\"%i\")=\"%s\"\n",sub,s,p,strins1(sub,s,p));
    getch();
}

Почему в строке вывода ,где должно изначальное значение s выводиться,выводится strins?
Код


char*strdel1(char*s,int p,int k)
{
    int len=strlen(s);
    char s1[100];
    for (int i=p+k,j=0;i<len;++i,++j)
        s1[j]=s[i];
    for (int i=p,j=0;i<len-k;++i,++j)
        s[i]=s1[j];
    s[len-k]=0;
    return s;
}

void main()
{
    int p=3,k=4;
    char s[15]="1234567456";
    printf ("strdel1(\"%s\",\"%i\",\"%i\")=\"%s\"\n",s,p,k,strdel1(s,p,k));
    getch();
}

Здесь такой-же вопрос

++ помогите исправить:
Код

#include "stdio.h"
#include "string.h"
#include "conio.h"

int strpos1(char*sub,char*s)
{
    int v,len=strlen(s),len1=strlen(sub);
    int p;
    for (int i=0,j=0;i<len;++i,++j)
    {
        if (s[i]=sub[j]) {
             p=i;
            for (int k=1,k1=j;k<len1;)
                if (s[k1]=sub[k])
                {
                    ++k;
                    ++k1;
                    if (k==(len1-1)) break;
                }
                else p=-1;
        }
    
    }
    return p;
}

void main()
{
    char sub[10]="123",s[15]="45512364";
    printf ("strpos1(\"%s\",\"%s\")=\"%i\"\n",sub,s,strpos1(sub,s));
    getch();
}

Автор: borisbn 6.11.2011, 21:50
Цитата(volatile @  6.11.2011,  16:30 Найти цитируемый пост)
Ну во первых, я здесь не увидел нигде упоминания, что нужен именно С.

volatile, я, почему-то, был уверен, что эти "фокусы" возможны только в Си, а в Си++ такое невозможно...


babat, в ф-ции strins1
Цитата(babat @  6.11.2011,  18:54 Найти цитируемый пост)
 for (int i=p,j=0;i<len1;++i,++j)

почему копирование в выходную строку начинается с i=p ???
должно быть так:
1) скопировать в выходную строку из входной с 0 до p-1
2) добавить к выходной строке подстроку (sub)
3) добавить к выходной строке входную от p до конца входной

в ф-ции strdel1 будь проще и к тебе потянутся smile
Код

char * strdel1( char * s, int p, int k )
{
    int len = strlen(s);
    char s1[100];
    for ( int i = p, j = p + k; j < len; ++i, ++j )
        s[ i ] = s[ j ];
    s[ len - k ] = 0;
    return s;
}


в ф-ции strpos1 вообще всё неправильно. нужно как-то так
Код

int strpos1(char*sub,char*s)
{
    int len=strlen(s),len1=strlen(sub);
    int p = -1;
    for ( int i = 0; i < len; ++i )
    {
        if ( s[ i ] == sub[ 0 ] ) {
            p = i;
            for ( int k = i + 1, k1 = 1; k < len && k1 < len1; )
                if ( s[ k ] == sub[ k1 ] )
                {
                    ++k;
                    ++k1;
                }
                else
                {
                    p = -1;
                    break;
                } 
        }
    
    }
    return p;
}

Автор: volatile 7.11.2011, 00:39
Цитата(borisbn @  6.11.2011,  21:50 Найти цитируемый пост)
а в Си++ такое невозможно

на сайте у бусткодера возможно всё!  smile 

Автор: babat 7.11.2011, 08:56
Цитата(borisbn @ 6.11.2011,  21:50)

babat, в ф-ции strins1
Цитата(babat @  6.11.2011,  18:54 Найти цитируемый пост)
 for (int i=p,j=0;i<len1;++i,++j)

почему копирование в выходную строку начинается с i=p ???
должно быть так:
1) скопировать в выходную строку из входной с 0 до p-1
2) добавить к выходной строке подстроку (sub)
3) добавить к выходной строке входную от p до конца входной


Здесь же S и есть выходная строка,а  вот этим for (int i=p,j=0;i<len1;++i,++j) я копирую в s1 строку s начиная с Р-й позиции.А потом с Р-й позиции в S я заталкиваю Sub. Затем С позиции P+strlen(sub) я заталкиваю S1. Вроде как правильно,но в строке вывода
printf("strins1(\"%s\",\"%s\",\"%i\")=\"%s\"\n",sub,s,p,strins1(sub,s,p));
 Должно выводиться вот так : strins1("456","123789","3")="123456789"
А выводит вот так: strins1("456","123456789","3")="123456789"
Почему?((

Народ,HELP!

Автор: borisbn 8.11.2011, 16:57
babat, ты изменяешь первоначальную строку, а т.к. параметры в ф-цию printf передаются с конца, то сначала выполнится strins1(sub,s,p) - при этом s изменится - затем её результат передастся в printf, затем туда передастся p, а затем s (как ты помнишь - изменённое)

Автор: bsa 8.11.2011, 17:28
Цитата(borisbn @  8.11.2011,  17:57 Найти цитируемый пост)
параметры в ф-цию printf передаются с конца

Это implementation defined, нет?  smile 

А вообще данная ситуация называется "undefined behaviour" - неопределенное поведение.

Автор: borisbn 8.11.2011, 18:04
Цитата(bsa @  8.11.2011,  17:28 Найти цитируемый пост)
Это implementation defined, нет?

почти уверен, что да. и судя по implementation'у babat у него defined именно так smile

и опять соглашусь: такой код - прямой путь к UB.

Автор: babat 8.11.2011, 18:15
а по русски?)

Автор: borisbn 8.11.2011, 18:21
babat, вот есть у тебя ф-ция int increment_value( int * x ) и функция void foo( int a, int b ); и вызываешь ты её так
Код
foo( x, increment_value( &x ) );

а incriment_value реализована так
Код
int increment_value( int * x ) { *x = *x + 1; return *x; }

теперь подумай, что получит foo в качестве a и что в качестве b..

Автор: mes 8.11.2011, 19:51
Цитата(borisbn @  6.11.2011,  20:50 Найти цитируемый пост)
возможны только в Си, а в Си++ такое невозможно...

С++11 перенял нечто из C99, чтоб сузить пропасть, возникщую за время их самостоятельног развития.. smile

Автор: Lols 8.11.2011, 20:59
Да, мне тоже казалось, что в С++ так не получится 0_о

"undefined behaviour" - неопределенное поведение - то есть, такая функция запросто может не работать?

Автор: bsa 8.11.2011, 21:39
Цитата(Lols @  8.11.2011,  21:59 Найти цитируемый пост)
"undefined behaviour" - неопределенное поведение - то есть, такая функция запросто может не работать? 

И да и нет. такая функция может работать в 99 случаев из 100... Все зависит от компилятора и параметров оптимизации. Может получиться даже так, что в режиме отладки работает, а в релизе нет, так как компилятор оптимизировал вызовы таким образом, каким не предполагал программист. А все потому, что этот код неверен...

Автор: babat 13.11.2011, 17:27
Код

char*strcpy2(char*dest,char*s,int p,int k)
{
    int len=strlen(s);
    char *p[10];
    for (int i=0;i<len;i++)
        p[i]=&s[i];
    for (int i=p,j=0;i<p+k;i++,j++)
        dest[j]=*p[i];
    dest[k]=0;
    return dest;
}
void main()
{
    char s[9]="0123123",dest[5];
    int k=3,p=4;
    printf ("%s",strcpy2(dest,s,p,k));
    getch();
}

что не так?(

Автор: mes 13.11.2011, 18:41
Цитата(babat @  13.11.2011,  16:27 Найти цитируемый пост)
char*strcpy2(char*dest,char*s,int p,int k)
{
    int len=strlen(s);
    char *p[10];


Автор: bsa 13.11.2011, 20:38
babat, для примера, как надо писать:
Код
char* strcpy2(char *dest, const char *s, int from, int size)
{
   char *d = dest;
   s += from;//по хорошему, параметр from в принципе не нужен, так как это можно сделать перед вызовом strcpy2: strcpy2(d, s + from, size)
   for(;*s && size; ++s, --size, ++d)
     *d = *s;
   *d = '\0';
   return dest;
}

Автор: babat 16.11.2011, 16:24
Код

char*strdel1(char*s,int p,int k)
{
    int len=strlen(s);
    if(p>=len)
        return s;
    if(p+k>=len)
    {
        s[p]=0;
        return s;
    }
    char*ptr1=s+p;
    char*ptr2=s+p+k;
    while(*ptr1++=*ptr2++)
        ;
    return s;
}
char*strdel2(char*s,int p,int k)
{
    int len=strlen(s);

    if(p>=len)
        return s;
    if(p+k>=len)
    {
        s[p]=0;
        return s;
    }
    for (int i=p,j=p+k;j<=len;++i,++j)
        s[i]=s[j];
    
    return(s);
}


Народ,помогите еще 2 написать плиз((

Автор: bsa 16.11.2011, 17:31
babat, помогают написать в другом разделе. Здесь же помогают найти ошибки, отвечают на вопросы и направляют на путь истинный.
У тебя нет вопроса. Поэтому даже не знаю, что ответить.

Автор: babat 16.11.2011, 20:05
ну хотябы словами опишите алгоритм))

Автор: bsa 16.11.2011, 20:19
чем функции strdel1 и strdel2 отличаются?
Делать нужно так:
1. в цикле от 0 до p (невключительно) ищешь признак конца строки. Если находишь, то выход.
2. в цикле от p до p+k (включительно) ищешь признак конца строки. Если находишь, то ставишь признак конца строки в позицию p и выход.
3. в цикле копируешь данные из p+k+i в p+i до тех пор, пока не встретится признак конца строки (его тоже надо скопировать).
4. выход

Автор: babat 19.11.2011, 19:03
Код

char*strdel3(char*s,int p,int k)
{
    int len=strlen(s);

    if(p>=len)
        return s;
    if(p+k>=len)
    {
        s[p]=0;
        return s;
    }
    int i=p,j=p+k;
    met1:s[i]=s[j];
    if (j>len) goto met2;
    i++,j++;
    goto met1;
    met2:return s;



норм?

Автор: bsa 20.11.2011, 23:13
babat, на данном уровне знания языка попрошу забыть о существовании оператора goto. Используй циклы (for(;;), while(){} или do{}while()) и continue/break.
А потом, ты сильно отклонился от моего алгоритма. У меня циклы использовались обычные, без хитрых повторов.

Автор: babat 22.11.2011, 18:10
ок,предположим что del сделали) хоть и не так,как ты сказал.Но вроде все работает,система тестов все проверяет-все норм.
Перейдем к разбору других функций)
зы спасибо огромное что помогаете))

strlen
Код

int strlen1(char*s)
{
    int len=0;
    while (s[len]!=0)
        len++;
    return len;
    
}
int strlen2(char*s)
{
    int len=0;
    for (len;;++len)
        if (s[len]!=0) len++;
        else {
            return len;
            break;
        }
    
}
int strlen3(char*s)
{
    char *ptr=s;
    int len=0;
    while (*ptr++)
        ++len;
    return len;
}

int strlen4(char*s)
{
  int len=-1;
  met1:++len;
  if (s[len]!=0) goto met1;
  else goto met2;
  met2:return len; 
}

норм?

Автор: bsa 22.11.2011, 21:14
babat, видимо оператор goto ты так и не забыл.
strlen3 наиболее близок к оптимальному решению (без оптимизаций по длине машинного слова):
Код
size_t strlen(const char *text)
{
   const char *p = text;
   for(;*p;++p);
   return p - text;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)