У меня есть проблема, не для компиляции этого кода, а для выполнения этой программы. Когда я запускаю его в терминале, он печатает первые 2 cout
затем программа перестает работать, и экран в окнах, который говорит вам, я думаю, что проблема заключается в strcat
,
Я использую DEVC ++ и у меня Windows 7 Pro.
#include <iostream>
#include <string>
#include <cstdlib>
#include <string.h>
using namespace std;
int main() {
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
cout << "*c: " << *c << endl;
cout << "*cambia: " << *cambia << endl;
strcat( *cambia, *c );
cout << "*cambia: " << *cambia << endl;
}
Вы не используете strcat()
в C ++, если вам это абсолютно не нужно (например, когда вы поддерживаете устаревший код и касаетесь как можно меньшего количества материала).
использование std::string
и его функции-члены, такие как find
или же substr
для простых задач, струнные потоки или же Boost библиотеки для более сложного разделения строк.
Во всяком случае, держись подальше от strcat()
,
Метод strcat () добавляет строку из второго аргумента в буфер из которых вы подчиняетесь первому аргументу.
Во-первых, буфер должен быть доступен для записи. В вашем примере вы передаете строковый литерал в качестве буфера. Естественно, строковые литералы доступны только для чтения. Но даже тогда строковый литерал не имеет свободного места, где новая строка может быть добавлена.
Вместо того, чтобы исправлять ваш код, позвольте мне показать вам несколько примеров того, как объединять строки в C ++ и C.
В этом примере показано, как объединить две строки C ++:
#include <iostream>
#include <string>
int main(int argc, const char * argv[])
{
// Create a new C++ string with an initial text.
std::string result = "First string part ";
std::cout << "Result: " << result << std::endl;
// Add some text
std::string textToAppend = "and the second part";
result.append(textToAppend);
std::cout << "Result: " << result << std::endl;
return 0;
}
В следующем примере показано, как объединить две строки в C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main(int argc, const char * argv[])
{
// The two texts to concat
const char *firstText = "This is the first text ";
const char *secondText = "and this is the second one";
// A buffer which is large enough for the operation.
const int bufferSize = 1024;
char buffer[bufferSize];
// Copy the initial text into the buffer.
strncpy(buffer, firstText, bufferSize);
// Add the secon string
strncat(buffer, secondText, bufferSize-strlen(buffer));
// Output the string
printf("Result: %s\n", buffer);
return 0;
}
Я предлагаю, вы должны использовать строки C ++, если это возможно. Они автоматически управляют памятью, что предотвращает многие связанные с памятью проблемы со строками C.
Эта линия
char* cambia[] = {"ciao "};
создает переменную с именем cambia
в динамически создаваемой части памяти, называемой «стеком». Переменная является массивом без объявленного размера, а элементы этого массива являются указателями на символы.
Размер массива следует из инициализатора
{"ciao "}
что подразумевает, что массив будет иметь только один элемент, и этот элемент инициализируется значением, указывающим на первый символ строки "ciao "
, Тем не менее, строка "ciao "
находится в совершенно другой области памяти — в статическом блоке, инициализированном компилятором со значениями, найденными в коде программы. Компилятор не знает, как вы используете эти значения, в частности, он не знает, вы будете простираться это с strcat
, поэтому он не зарезервирует дополнительное место после строки.
В результате, когда вы объединяете "mondo"
в "ciao "
перезаписываешь немного данные в памяти, возможно, некоторые важные данные …
Я бы предложил вам объявить местный переменные для вашей строки, с явным размером:
char cambia[ 20] = "ciao ";
char c[] = "mondo";
Это сделает cambia
переменная, достаточно длинная, чтобы сохранить 19-символьную строку (плюс неявный завершающий нулевой байт ‘\ 0’, ASCII NUL) и инициализировать первые 6 байт буквами ‘c’, ‘i’, ‘a’, ‘o’, пробел ‘ и NUL. переменная c
размер неявно равен 6 (длина строки инициализации 5 плюс 1 для завершения NUL).
Тогда вы можете безопасно соединить
strcat( cambia, c);
получить 11-символьную строку «ciao mondo» и распечатать ее
cout <<"cambia: "<<cambia<<endl;
Проблема здесь в том, что вы пытаетесь записать в строковое хранилище только для чтения.
Эти декларации:
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
объявить два массива, каждый с постоянный строковый член. "ciao "
а также "mondo"
расположены в постоянной памяти.
Поэтому, когда вы звоните strcat(*cambia, *c)
вы пытаетесь написать "mondo"
на конец "ciao "
, Он не только записывает данные в постоянную память, но также записывает данные вне пространства памяти, выделенного для строки, — есть место только для 6 char
в "ciao "
строка, и вы пытаетесь добавить еще 5 к концу этого.
Решение состоит в том, чтобы зарезервировать место для каждой строки. Есть разные способы сделать это. Вот простой:
char acambia[20] = "ciao "; // Space for 20 characters.
char* cambia[] = { acambia };
Конечно, если не использовать дополнительный уровень косвенности, это упростит задачу:
char cambia[20] = "ciao ";
char c[] = "mondo";
strcat(cambia, c);
достиг бы правильного результата.
Прежде всего вам не нужны заголовки
#include <string>
#include <cstdlib>
потому что ни одна декларация от них не используется.
Также заголовок
#include <string.h>
должен быть заменен
#include <cstring>
В этих заявлениях
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
вы определили два массива, каждый из которых имеет один элемент типа const char *
, Компилятор должен выдать либо ошибку, либо предупреждение, потому что эти определения неверны. Было бы правильно определить массивы следующим образом
const char* cambia[] = {"ciao "};
const char* c[] = {"mondo"};
Эти два оператора определяют массивы константных указателей на строковые литералы. Это неопределенное поведение, если в программе предпринята попытка изменить строковый литерал. Программы могут размещать строковые литералы в только для чтения памяти.
Вы правы, утверждая, что главная проблема заключается в утверждении
strcat( *cambia, *c );
функция strcat
добавляет один массив символов в конец другого массива символов. Поэтому второй массив cjaracter должен зарезервировать достаточно памяти для размещения массива добавленных символов. Если бы вы даже правильно определили массив cambia как
char cambia[] = {"ciao "};
у него не было достаточно памяти, чтобы хранить и символы массива c.
Так что перед использованием strcat
вам нужно зарезервировать достаточно памяти, где будет размещен объединенный массив результатов.
Вы можете сделать это, например, следующим образом
char s[11];
strcpy( s, *cambia );
strcat( s, c );
cout << "s: " << s << endl;
Учтите, что вместо символьных массивов вы можете использовать объекты стандартного класса. std::string
В этом случае добавить одну строку в другую очень просто. Например
std::string cambia = "ciao ";
std::string c = "mondo";
cambia += c;
Или же
cambia.append( c );