Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/40: Рейтинг темы: голосов - 40, средняя оценка - 4.88
 Аватар для cyber_girl=)
0 / 0 / 0
Регистрация: 17.09.2010
Сообщений: 15

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

25.01.2011, 15:41. Показов 7504. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.01.2011, 15:41
Ответы с готовыми решениями:

Заполнить матрицу случайными числами не используя библиотечную функцию rand
Здравствуйте!!! У меня есть такое задание не могу решать может поможете?? Случайные целые числа в диапазоне от - 32768 до 32678 можно...

Используя указатели написать функцию strcat
Упражнение 5.3. Используя указатели, напишите функцию strcat, которую мы рассматривали в главе 2 (функция strcat(s, t) копирует строку t...

Написать собственную функцию strcat - сцепление строк
Добрый день! Было задано написать собственную функцию strcat -сцепление строк. Сравнить работу функции со стандартной из библиотеки...

14
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
25.01.2011, 15:51
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;
}
1
 Аватар для cyber_girl=)
0 / 0 / 0
Регистрация: 17.09.2010
Сообщений: 15
25.01.2011, 15:54  [ТС]
Спасибо большое!
0
 Аватар для evsign
2 / 2 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 03:56
Цитата Сообщение от 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? Был бы оочень благодарен.
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
26.09.2014, 04:13
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() не определено.
Ахтунг: есть опасность вылезти за пределы первой строки
1
 Аватар для evsign
2 / 2 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 04:24
Дело в том, что у меня на курсах сейчас попалось такое задание. Написать функцию конкатенации 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 *** - это и есть то вылезание за пределы, что вы имели ввиду?
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
26.09.2014, 04:32
Цитата Сообщение от КОП Посмотреть сообщение
Ахтунг: есть опасность вылезти за пределы первой строки
компилятор резервирует под a[] память на 8 символов, вы же после 8ого дописываете вторую строку, а там уже чужая память. Сравните:
Цитата Сообщение от evsign Посмотреть сообщение
char str1[BUFSIZ]
Цитата Сообщение от evsign Посмотреть сообщение
char a[] = "Hello, ";
И да, введите в варианте easybudda 2 строки в сумме дающие 512+ символов и посмотрите на результат.
1
 Аватар для evsign
2 / 2 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 04:39
А почему тогда, если в моём варианте, к примеру указать char a[9] = "Hello, "; то код выполнится без ошибки?
Ведь 9ти ячеек серавно мало для этих 2х строк вместе взятых.
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
26.09.2014, 04:49
Цитата Сообщение от evsign Посмотреть сообщение
то код выполнится без ошибки?
может просто не детектит ошибку. У меня лично она есть при значениях до 14. Пробуйте запустить не из отладчика а exe'шник. Возможно память просто выделилась подряд и перезаписываются не левые адреса, а к примеру память, выделенная под второй массив (можете помимо вывода результата проверить целостность 2ого массива)
В любом случае, выделяйте достаточно памяти под первый массив, либо делайте проверку.
0
 Аватар для evsign
2 / 2 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 05:02
Цитата Сообщение от КОП Посмотреть сообщение
может просто не детектит ошибку. У меня лично она есть при значениях до 14. Пробуйте запустить не из отладчика а exe'шник. Возможно память просто выделилась подряд и перезаписываются не левые адреса, а к примеру память, выделенная под второй массив (можете помимо вывода результата проверить целостность 2ого массива)
В любом случае, выделяйте достаточно памяти под первый массив, либо делайте проверку.
Ясно. Спасибо)
компилятор g++ 4.9. Ubuntu)
Целостность второго массива проверял выводом его значения и через sizeof. Т.к. вывело ожидаемые значения, то получается что массив цел, правильно?

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

Добавлено через 4 минуты
А вот sizeof(a) вывело 9. Хотя там должно быть больше)
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
26.09.2014, 05:03
разыменованное значение
Просто подумайте, был бы там адрес, инкременируя его, мы бы достигла когда-нибудь значения false (0), которое необходимо для выхода из цикла.
А так мы натыкаемся на адрес нулевого символа, разыменовываем его и опаньки, false.

Не по теме:

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



[del]

Не по теме:

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

1
 Аватар для evsign
2 / 2 / 0
Регистрация: 26.09.2014
Сообщений: 13
26.09.2014, 05:26
Блин, не могу догнать тогда немного другой момент.
Почему 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 байт.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2014, 06:01
Цитата Сообщение от 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;
       
    }
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.09.2014, 11:23
На С++ (а мы в этом разделе) это выглядит так:
C++
1
std::string s1 = "Hello ", s2 = "world!", s3 = s1 + s2;
0
26.09.2014, 13:51

Не по теме:

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

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
26.09.2014, 13:51
Помогаю со студенческими работами здесь

Конкатенация строк через функцию
Пытался я сделать программу, которая соединяет две строки. Сделал я все это так порнографично (через функцию), так-как такое домашнее...

Используя функцию копирования строк, организуйте конкатенацію и копирование строк в четвертый массив, содержащий полные имена
Пожалуйста с этим заданием. Написать программу, которая описывает четыре массива. Три первых массива должны содержать имена, фамилии и...

Максимальный размер строки отправляемый в библиотечную функцию
Здравствуйте. Сделал dll библиотеку. Использую её в другом ЯП. Передаю функции аргумент строку размером 535 символов. Но выдает...

Почему компилятор ругается на библиотечную функцию _atold() ?
Помогите с ошибкой, компилятор не принимает функцию _atold() встроенную в C++ #include &lt;iostream&gt; #include &lt;iomanip&gt; ...

Посоветуйте библиотечную функцию ввода, не ожидающую нажатия Enter
Подскажите пожалуйста, как можно сделать такой ввод, чтобы цикл не вставал в ожидании нажатия клавиши, а лишь рассматривал, был ли ввод на...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru