Я'м работает в C, и мне нужно объединить несколько вещей.
Сейчас у меня есть это:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Теперь, если у вас есть опыт работы в C я'м уверена, что вы понимаете, что это дает ошибку сегментации при попытке запустить его. Так как я могу обойти это?
В C, то "строки" и просто голец
массивы. Таким образом, вы можете't напрямую соединить их с прочим "ниточки" по.
Вы можете использовать функции strcatфункция, которая добавляет строку, на которую указывает
srcв конце строки, на которую указывает
назначение`:
char *strcat(char *dest, const char *src);
char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");
Для первого параметра, необходимо обеспечить себе буфер назначения. Буфер назначения должен быть буфер char массив. Е. Г.: буфер типа char[1024];
Убедитесь, что, что первый параметр имеет достаточно места для хранения, что вы'вновь пытается копировать в него. Если вам доступно, это безопаснее, чтобы использовать функции, такие как: предоставляя strcpy_s
и strcat_s
, где вы явно не укажите размер буфера назначения.
Note: строковый литерал не может быть использован в качестве буфера, так как он является постоянным. Таким образом, вы всегда должны выделить char массив для буфера.
Возвращаемое значение функции strcat` можно просто игнорировать, он просто возвращает тот же указатель, как был передан в качестве первого аргумента. Он есть для удобства, и позволяет цепи звонки в одну строку кода:
strcat(strcat(str, foo), bar);
Так что ваша проблема может быть решена следующим образом:
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
Избегайте использования функции strcat
в C код. Самый чистый и, главное, безопасным способом является использование и snprintf
:
char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);
Некоторые комментаторы подняли вопрос о том, что количество аргументов не соответствует строке формата и код будет по-прежнему компилироваться, но большинство компиляторов уже выдавать предупреждение в этом случае.
Люди, используйте ул.<б>Н</б>КПЮ(), ул.<б>Н</б>кат(), или S<б>Н</б>функции printf(). <БР>превышение места в буфере мусор все остальное в памяти! <БР>(и не забудьте оставить пространство для трейлинг-нулевой '\0' характер!)
Строки также могут быть объединены во время компиляции.
#define SCHEMA "test"
#define TABLE "data"
const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry = // include comments in a string
" SELECT * " // get all fields
" FROM " SCHEMA "." TABLE /* the table */
" WHERE x = 1 " /* the filter */
;
Также malloc и realloc полезны, если вы не'т знать заранее, сколько строк, объединяемых.
#include <stdio.h>
#include <string.h>
void example(const char *header, const char **words, size_t num_words)
{
size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
char *message = (char*) malloc(message_len);
strncat(message, header, message_len);
for(int i = 0; i < num_words; ++i)
{
message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
message = (char*) realloc(message, message_len);
strncat(strncat(message, ";", message_len), words[i], message_len);
}
puts(message);
free(message);
}
Не забудьте инициализировать буфер вывода. Первый аргумент в функции strcat должен быть нуль-терминированная строка достаточно дополнительное пространство, выделенное для итоговой строке:
char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string );
// null_terminated_string has less than 1023 chars
Как люди отмечали обработки строк значительно улучшилось. Так что вы можете научиться использовать библиотеку строку C++ вместо C-строки. Однако вот решение на C
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void appendToHello(const char *s) {
const char *const hello = "hello ";
const size_t sLength = strlen(s);
const size_t helloLength = strlen(hello);
const size_t totalLength = sLength + helloLength;
char *const strBuf = malloc(totalLength + 1);
if (strBuf == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
strcpy(strBuf, hello);
strcpy(strBuf + helloLength, s);
puts(strBuf);
free(strBuf);
}
int main (void) {
appendToHello("blah blah");
return 0;
}
Я не знаю, насколько это правильно/безопасно, но сейчас я не мог найти лучший способ, чтобы сделать это в ANSI С.
Лучший способ сделать это без того ограниченный размер буфера с помощью asprintf()
char* concat(const char* str1, const char* str2)
{
char* result;
asprintf(&result, "%s%s", str1, str2);
return result;
}
Это неопределенное поведение, чтобы попытаться изменить строковые литералы, что-то вроде:
strcat ("Hello, ", name);
попытается сделать. Он будет пытаться лавировать на " имя " строку в конец строкового литерала `"Привет " Ну, которая не определена.
Попробовать что-то этого. Это достигает, что вы пытаетесь сделать:
char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);
Это создает буферную зону, что это можно изменить и затем копирует как строковый литерал и другой текст. Просто будьте осторожны с переполнения буфера. Если вы контролируете входных данных (или проверить его, прежде чем руки), это's прекрасно, чтобы использовать фиксированную длину буфера, как у меня.
В противном случае, вы должны использовать стратегии по смягчению последствий, таких как выделение достаточного объема памяти из кучи, чтобы убедиться, что вы можете справиться с этим. Другими словами, что-то вроде:
const static char TEXT[] = "TEXT ";
// Make *sure* you have enough space.
char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);
// Need to free message at some point after you're done with it.
Первый аргумент функции strcat() должен быть способен держать достаточно места для сцепленную строку. Поэтому выделить буфер с достаточно места, чтобы получить результат.
char bigEnough[64] = "";
strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);
/* and so on */
функции strcat() будет объединять второго аргумента, первый аргумент, и сохранить результат в первый аргумент, возвращаемый тип char* - это просто это первый аргумент, и только для вашего удобства.
Вы не получите выделенную строку с первой и второй аргумент сцепляются, что я'd не думаю, что вы ожидали, основываясь на коде.
Вы можете написать свою функцию, которая делает то же самое как функции strcat ()
, но это вовсе't изменить что-либо:
#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
static char buffer[MAX_STRING_LENGTH];
strncpy(buffer,str1,MAX_STRING_LENGTH);
if(strlen(str1) < MAX_STRING_LENGTH){
strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
}
buffer[MAX_STRING_LENGTH - 1] = '\0';
return buffer;
}
int main(int argc,char *argv[]){
printf("%s",strcat_const("Hello ","world")); //Prints "Hello world"
return 0;
}
Если обе строки вместе более 1000 символов, то оно будет резать строку на 1000 символов. Вы можете изменить значение MAX_STRING_LENGTH
, чтобы удовлетворить ваши потребности.
Если у вас есть опыт в C можно заметить, что строки являются только char массивы, где последний символ является символом null.
Сейчас это совсем неудобно, так как вам придется искать последний символ для того, чтобы что-то добавить. функции strcat
будет делать это за вас.
Поэтому функции strcat поиск по первым аргументом для нуль-символа. Тогда замените это второй аргумент'ы содержание (пока что заканчивается нулем).
Теперь давайте's идти через ваш код:
message = strcat("TEXT " + var);
Вот вы что-то добавляя к указатель к тексту и"текст" и (типа на "текст" это константный тип char*. Указатель.).
Что, как правило, не будет работать. Также изменения в "текст" и массив будет работать не так, как обычно оно находится в постоянном сегменте.
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Что может лучше работать, за исключением того, что ты опять пытаешься изменить статические тексты. функции strcat не выделяя новую память для результата.
Я бы предложил сделать что-то вроде этого вместо:
sprintf(message2, "TEXT %s TEXT %s", foo, bar);
Читать документацию ом
, чтобы проверить это's параметры.
А теперь важный момент:
Убедитесь, что буфер имеет достаточно места, чтобы вместить текст и нулевой символ. Есть несколько функций, которые могут помочь вам, например, strncat и специальные версии с printf, что выделить буфер для вас. Не обеспечив размер буфера приведет к повреждению памяти и удаленное использование багов.
Если у вас есть чар[fixed_size], а не char, то вы можете использовать один, творческих макрос, чтобы сделать это все сразу с <<соиь<<как
заказ (на"а % - ов разрозненных %з\п то", то "чем-то", "В Е формате и"). Если вы работаете со встроенными системами, этот метод также позволяет оставить malloc и семьи большие `ефункции, такие как
и snprintf()` (это держит dietlibc от слишком жаловаться *е)
#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
const char *s, \
*a[] = { __VA_ARGS__,NULL}, \
**ss=a; \
while((s=*ss++)) \
while((*s)&&(++offset<(int)sizeof(buf))) \
*bp++=*s++; \
if (offset!=sizeof(buf))*bp=0; \
}while(0)
char buf[256];
int len=0;
strcpyALL(buf,len,
"The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
write(1,buf,len); //outputs our message to stdout
else
write(2,"error\n",6);
//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
write(1,buf,len); //outputs both messages
else
write(2,"error\n",6);
Вы пытаетесь скопировать строку в адрес статически. Вам нужно кота в буфер.
В частности:
...СНиП...
пунктом
Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.
...СНиП...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
Там'ы пример здесь.
int main()
{
char input[100];
gets(input);
char str[101];
strcpy(str, " ");
strcat(str, input);
char *p = str;
while(*p) {
if(*p == ' ' && isalpha(*(p+1)) != 0)
printf("%c",*(p+1));
p++;
}
return 0;
}
Это было мое решение
#include <stdlib.h>
#include <stdarg.h>
char *strconcat(int num_args, ...) {
int strsize = 0;
va_list ap;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++)
strsize += strlen(va_arg(ap, char*));
char *res = malloc(strsize+1);
strsize = 0;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++) {
char *s = va_arg(ap, char*);
strcpy(res+strsize, s);
strsize += strlen(s);
}
va_end(ap);
res[strsize] = '\0';
return res;
}
но нужно указать, сколько строк вы'ре собирается объединить
char *str = strconcat(3, "testing ", "this ", "thing");
Попробуйте что-то похожее на это:
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
// Insert code here...
char firstname[100], secondname[100];
printf("Enter First Name: ");
fgets(firstname, 100, stdin);
printf("Enter Second Name: ");
fgets(secondname,100,stdin);
firstname[strlen(firstname)-1]= '\0';
printf("fullname is %s %s", firstname, secondname);
return 0;
}