Форум программистов, компьютерный форум CyberForum.ru

Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.86
cyber_girl=)
 Аватар для cyber_girl=)
0 / 0 / 0
Регистрация: 17.09.2010
Сообщений: 15
25.01.2011, 15:41     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #1
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
 
char * strcat_my (char *s1, char *s2){
 
char *p1, *p2;
        p1 = s1;
        p2 = s2;
        while ( *p1 != '\0') p1++; 
                                  
        while (( *p1 = *p2) != 0){ 
         p1++;                     
         p2++;                     
        }                          
        *р1 = '\0';
        return s1;
        printf("%s\n",s1);
 
}
//Ошибка не узнает р1 и еще какая-то непонятная ошибка(((
//error C2065: 'р1' : undeclared identifier
// error C2100: illegal indirection
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.01.2011, 15:41     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat
Посмотрите здесь:

Заполнить матрицу случайными числами не используя библиотечную функцию rand C++
C++ Конкатенация строк
C++ Конкатенация строк
Конкатенация строк C++
C++ Собственная функция strcat -сцепление строк
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
25.01.2011, 15:51     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #2
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
 
char * my_strcat(char * dst, const char * src){
    char * p = dst;
    while ( *p )
        ++p;
    while ( *p++ = *src++ )
        ;
    return dst;
}
 
int main(void){
    char str1[BUFSIZ], str2[BUFSIZ];
    
    printf("First: ");
    scanf("%[^\n]%*c", str1);
    printf("Second: ");
    scanf("%[^\n]%*c", str2);
    
    printf("Together: %s\n", my_strcat(str1, str2));
    
    return 0;
}
cyber_girl=)
 Аватар для cyber_girl=)
0 / 0 / 0
Регистрация: 17.09.2010
Сообщений: 15
25.01.2011, 15:54  [ТС]     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #3
Спасибо большое!
evsign
 Аватар для evsign
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 03:56     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #4
Цитата Сообщение от easybudda Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
 
char * my_strcat(char * dst, const char * src){
    char * p = dst;
    while ( *p )
        ++p;
    while ( *p++ = *src++ )
        ;
    return dst;
}
 
int main(void){
    char str1[BUFSIZ], str2[BUFSIZ];
    
    printf("First: ");
    scanf("%[^\n]%*c", str1);
    printf("Second: ");
    scanf("%[^\n]%*c", str2);
    
    printf("Together: %s\n", my_strcat(str1, str2));
    
    return 0;
}
А не могли бы вы прокоментировать каждую строчку функции my_strcat? Был бы оочень благодарен.
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 755
26.09.2014, 04:13     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #5
evsign,
C++
1
2
3
4
5
6
7
8
char * my_strcat(char * dst, const char * src){
    char * p = dst; //присваиваем p указатель на начало первой строки
    while (*p)  //пропускаем все символы до нулевого
        ++p;
    while (*p++ = *src++) //копируем все символы, включая нулевой из 2ой строки в первую строку
        ;
    return dst; //возвращаем указатель на начало строки
}
для справки: Функция strcat() присоединяет к строке str1 копию строки str2 и завершает строку str1 нулевым символом. Конечный нуль-символ, первоначально завершающий строку str1, перезаписывается первым символом строки str2. Строка str2 при этом не изменяется. Если заданные массивы перекрываются, поведение функции strcat() не определено.
Ахтунг: есть опасность вылезти за пределы первой строки
evsign
 Аватар для evsign
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 04:24     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #6
Дело в том, что у меня на курсах сейчас попалось такое задание. Написать функцию конкатенации 2х строк и значение нужно сохранить в первую. Я адаптировал под себя этот вариант и тест на сайте прошёл, только вот локально у меня выходит ошибка *** stack smashing detected *** и происходит аварийная остановка, хотя перед этим код выполняется и выводит соединённую строку.

Адаптированный код выглядит вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
using namespace std;
 
void strcat(char *to, const char *from) {
    char *p = to;  // присваеваем указателю p адрес начала массива, т.е. &to[0]
     /* 
     ниже начало цикла, который будет выполняться и проходить
     по каждой следующей ячейке памяти пока не встретит \0,
         который в памяти выглядит как 0 == false
     ----------------------------------------------------------------------
     *p в условии будет содержать адрес ячейки или разыменованное значение?
     ----------------------------------------------------------------------
     */
 
    while (*p){ 
        ++p;
    }
 
    /*
    Ниже начинается цикл, который будет брать каждую следующую ячейку из массива p == to
    и записывать в неё разыменованное значение из массива from по тому же принципу.
    Т.е пока не встретит 0 в памяти.
    */
 
    while (*p++ = *from++){
 
    }
 
}
 
int main(){
    char a[] = "Hello, ";
    char b[] = "World!";
 
    strcat(a,b);
    cout << a << endl;
 
 
}
Скажите пожалуйста, почему происходит *** stack smashing detected *** и правильно ли я всё прокоментировал? Там ещё один вопросик в первом коменте) Просто очень хочется разобраться в этой теме)

Добавлено через 2 минуты
Спасибо. Примерно так всё и представлял) Остался только вопрос в том, что содержится в *p в условиях циклов? Там будет находиться адрес или разыменованное значение? А *** stack smashing detected *** - это и есть то вылезание за пределы, что вы имели ввиду?
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 755
26.09.2014, 04:32     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #7
Цитата Сообщение от КОП Посмотреть сообщение
Ахтунг: есть опасность вылезти за пределы первой строки
компилятор резервирует под a[] память на 8 символов, вы же после 8ого дописываете вторую строку, а там уже чужая память. Сравните:
Цитата Сообщение от evsign Посмотреть сообщение
char str1[BUFSIZ]
Цитата Сообщение от evsign Посмотреть сообщение
char a[] = "Hello, ";
И да, введите в варианте easybudda 2 строки в сумме дающие 512+ символов и посмотрите на результат.
evsign
 Аватар для evsign
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 04:39     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #8
А почему тогда, если в моём варианте, к примеру указать char a[9] = "Hello, "; то код выполнится без ошибки?
Ведь 9ти ячеек серавно мало для этих 2х строк вместе взятых.
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 755
26.09.2014, 04:49     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #9
Цитата Сообщение от evsign Посмотреть сообщение
то код выполнится без ошибки?
может просто не детектит ошибку. У меня лично она есть при значениях до 14. Пробуйте запустить не из отладчика а exe'шник. Возможно память просто выделилась подряд и перезаписываются не левые адреса, а к примеру память, выделенная под второй массив (можете помимо вывода результата проверить целостность 2ого массива)
В любом случае, выделяйте достаточно памяти под первый массив, либо делайте проверку.
evsign
 Аватар для evsign
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 05:02     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #10
Цитата Сообщение от КОП Посмотреть сообщение
может просто не детектит ошибку. У меня лично она есть при значениях до 14. Пробуйте запустить не из отладчика а exe'шник. Возможно память просто выделилась подряд и перезаписываются не левые адреса, а к примеру память, выделенная под второй массив (можете помимо вывода результата проверить целостность 2ого массива)
В любом случае, выделяйте достаточно памяти под первый массив, либо делайте проверку.
Ясно. Спасибо)
компилятор g++ 4.9. Ubuntu)
Целостность второго массива проверял выводом его значения и через sizeof. Т.к. вывело ожидаемые значения, то получается что массив цел, правильно?

Подскажите пожалуйста ещё момент по-поводу *p в условии циклов. Там будет содержаться адрес массива или разыменованное значение?

Добавлено через 4 минуты
А вот sizeof(a) вывело 9. Хотя там должно быть больше)
КОП
348 / 280 / 86
Регистрация: 15.08.2010
Сообщений: 755
26.09.2014, 05:03     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #11
разыменованное значение
Просто подумайте, был бы там адрес, инкременируя его, мы бы достигла когда-нибудь значения false (0), которое необходимо для выхода из цикла.
А так мы натыкаемся на адрес нулевого символа, разыменовываем его и опаньки, false.

Не по теме:

Цитата Сообщение от evsign Посмотреть сообщение
Ясно. Спасибо)
коль спасибо, так кнопочка есть специальная под сообщениями, чтоб официально все
а так всегда пожалуйста.



[del]

Не по теме:

что-то форум приболел даблпостом, осень...

evsign
 Аватар для evsign
0 / 0 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 05:26     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #12
Блин, не могу догнать тогда немного другой момент.
Почему cout << p << endl; выводит всю строку, ведь по идее должен же выводить адресс в 0x виде.
Или это просто фишка компилятора, что он автоматом выводит все последующие значения из памяти до \0, если увидит адрес типа чар?
И почему тогда, если первый цикл сделать:
C++
1
2
3
4
while (*p){ 
        ++p;
        cout << p << endl;
    }
выводится
C++
1
2
3
4
5
ello, 
llo, 
lo, 
o, 
,
Впринципе этот вывод соответствует моему предположению. НО
Если сделать так:
C++
1
2
3
4
while (*p){ 
        ++p;
        cout << &p << endl;
    }
то выводится:
C++
1
2
3
4
5
6
7
0x7ffff2076d90
0x7ffff2076d90
0x7ffff2076d90
0x7ffff2076d90
0x7ffff2076d90
0x7ffff2076d90
0x7ffff2076d90
Т.е. один и тот же адрес несколько раз, когда я предпологал увидеть разные адреса с разницей в 1 байт.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2014, 06:01     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #13
Цитата Сообщение от evsign Посмотреть сообщение
Или это просто фишка компилятора, что он автоматом выводит все последующие значения из памяти до \0, если увидит адрес типа чар?
Так устроен cout.
Цитата Сообщение от evsign Посмотреть сообщение
Почему cout << p << endl; выводит всю строку, ведь по идее должен же выводить адресс в 0x виде.
Чтобы выводил адрес, указатель на char нужно привести к void*.

Добавлено через 1 минуту
Цитата Сообщение от evsign Посмотреть сообщение
cout << &p << endl;
Это адрес самого указателя.

Добавлено через 9 минут
А ++p делает инкремент содержимого указателя (адреса строки, который в нём содержится). Адрес самого указателя при этом не меняется.

Добавлено через 2 минуты
Вот так будет видно:
C++
1
2
3
4
5
6
while (*p){ 
        
        cout << (void*)p << endl;
       ++p;
       
    }
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,416
26.09.2014, 11:23     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat #14
На С++ (а мы в этом разделе) это выглядит так:
C++
1
std::string s1 = "Hello ", s2 = "world!", s3 = s1 + s2;
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2014, 13:51     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat
Еще ссылки по теме:

Конкатенация строк C++
Используя функцию копирования строк, организуйте конкатенацію и копирование строк в четвертый массив, содержащий полные имена C++
C++ Конкатенация строк через функцию

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
easybudda
26.09.2014, 13:51     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat
  #15

Не по теме:

Цитата Сообщение от MrGluck Посмотреть сообщение
На С++ (а мы в этом разделе)
Раньше на форуме был общий раздел С/С++, тема ещё с тех времён осталась.

Yandex
Объявления
26.09.2014, 13:51     Назначение - конкатенация строк s1 и s2, не используя библиотечную функцию - strcat
Ответ Создать тему
Опции темы

Текущее время: 21:57. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru