У C я маю два масиви char:
char array1[18] = "abcdefg";
char array2[18];
Як скопіювати значення array1
to array2
? Чи можу я просто зробити це array2 = array1
:?
У C я маю два масиви char:
char array1[18] = "abcdefg";
char array2[18];
Як скопіювати значення array1
to array2
? Чи можу я просто зробити це array2 = array1
:?
char array1[18] = {"abcdefg"};
не є належним масивом символів.
char array1[18] = "abcdefg";
абоchar array1[18] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
char array1[18] = {"abcdefg"};
незвично, але 100% пукка.
Відповіді:
Ви не можете безпосередньо це зробити array2 = array1
, оскільки в цьому випадку ви маніпулюєте адресами масивів ( char *
), а не їх внутрішніми значеннями ( char
).
Що вам, концептуально, хочеться зробити, це перебрати всі символи вашого джерела ( array1 ) і скопіювати їх до місця призначення ( array2 ). Є кілька способів зробити це. Наприклад, ви можете написати простий цикл for, або використовувати memcpy
.
З огляду на це, рекомендованим способом для рядків є використання strncpy
. Це запобігає типовим помилкам, що призводять, наприклад, до переповнення буфера (що особливо небезпечно, якщо array1
заповнюється за допомогою вводу користувача: клавіатури, мережі тощо). Подобається так:
// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
Як @Prof. Фалькен, згаданий у коментарі, strncpy
може бути злим . Переконайтеся, що цільовий буфер достатньо великий, щоб містити вихідний буфер (включаючи \0
кінець рядка).
array1=array2
, що означає, що array1 отримує нове значення, але ваш код робить це навпаки. Про всяк випадок, якщо хтось інший на це впаде.
Якщо ваші масиви не є масивами рядків, використовуйте:
memcpy(array2, array1, sizeof(array2));
sizeof()
Тоді в цій функції ви не можете визначити розмір масиву. В іншому випадку це sizeof()
добре працює.
Якщо ви хочете захиститися від незавершених рядків, які можуть спричинити всілякі проблеми, скопіюйте свій рядок таким чином:
char array1[18] = {"abcdefg"};
char array2[18];
size_t destination_size = sizeof (array2);
strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';
Цей останній рядок насправді важливий, оскільки strncpy()
не завжди нуль закінчує рядки. (Якщо буфер призначення занадто малий, щоб містити весь вихідний рядок, sntrcpy () не буде нульовим завершенням цільового рядка.)
У керівництві для strncpy () навіть зазначено "Попередження: Якщо серед перших n байт src немає нульового байта, рядок, розміщений у dest, не буде закінчуватися нулем."
Причина, по якій strncpy () поводиться дещо дивно, полягає в тому, що вона насправді спочатку не задумувалася як безпечний спосіб копіювання рядків.
Інший спосіб - використовувати snprintf () як безпечну заміну strcpy ():
snprintf(array2, destination_size, "%s", array1);
(Дякую jxh за підказку.)
snprintf()
немає проблеми, яка strncpy()
має.
Як зазначали інші, рядки копіюються з strcpy()
або його варіантами. У певних випадках ви можете також використовувати snprintf()
.
Ви можете призначити масиви лише так, як вам потрібно, як частину призначення структури:
typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;
array2 = array1;
Якщо ваші масиви передаються функції, здається, що вам дозволено їх призначати, але це просто випадковість семантики. У C масив перетворюється на тип покажчика зі значенням адреси першого члена масиву, і цей покажчик передається. Отже, ваш параметр масиву у вашій функції насправді є лише покажчиком. Призначення - це просто призначення покажчика:
void foo (char x[10], char y[10]) {
x = y; /* pointer assignment! */
puts(x);
}
Сам масив залишається незмінним після повернення з функції.
Ця семантика "спаду до значення покажчика" для масивів є причиною того, що призначення не працює. Значення l має тип масиву, але значення r є типом впалого вказівника, тому присвоєння відбувається між несумісними типами.
char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
but array2 is still an array type */
Щодо того, чому було введено семантику "спаду до значення покажчика", це було для досягнення сумісності вихідного коду з попередником C. Ви можете прочитати Детальніше про розробку мови C.
array2 = array1;
не працює. Проголосувати.
це повинно виглядати так:
void cstringcpy(char *src, char * dest)
{
while (*src) {
*(dest++) = *(src++);
}
*dest = '\0';
}
.....
char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
cstringcpy
функція не закінчує нуль завершення цільового масиву.
cstringcpy
функція майже точно семантично еквівалентна strcpy
, з тими ж недоліками, а саме не перевіряє переповнення буфера.
Я рекомендую використовувати memcpy () для копіювання даних. Крім того, якщо ми призначаємо буфер іншому як array2 = array1
, обидва масиви мають однакову пам'ять, і будь-яка зміна arrar1 відхиляється в array2. Але ми використовуємо memcpy, обидва буфери мають різний масив. Я рекомендую memcpy (), оскільки strcpy та відповідна функція не копіюють символ NULL.
функції c лише нижче ... c ++ вам потрібно зробити масив char, потім скопіювати рядок, а потім скористатися функцією tokenizor рядка ... c ++ набагато важче робити щось
#include <iostream>
#include <fstream>
#include <cstring>
#define TRUE 1
#define FALSE 0
typedef int Bool;
using namespace std;
Bool PalTrueFalse(char str[]);
int main(void)
{
char string[1000], ch;
int i = 0;
cout<<"Enter a message: ";
while((ch = getchar()) != '\n') //grab users input string untill
{ //Enter is pressed
if (!isspace(ch) && !ispunct(ch)) //Cstring functions checking for
{ //spaces and punctuations of all kinds
string[i] = tolower(ch);
i++;
}
}
string[i] = '\0'; //hitting null deliminator once users input
cout<<"Your string: "<<string<<endl;
if(PalTrueFalse(string)) //the string[i] user input is passed after
//being cleaned into the null function.
cout<<"is a "<<"Palindrome\n"<<endl;
else
cout<<"Not a palindrome\n"<<endl;
return 0;
}
Bool PalTrueFalse(char str[])
{
int left = 0;
int right = strlen(str)-1;
while (left<right)
{
if(str[left] != str[right]) //comparing most outer values of string
return FALSE; //to inner values.
left++;
right--;
}
return TRUE;
}
Ви не можете призначити масиви для їх копіювання. Спосіб копіювання вмісту одного в інший залежить від багатьох факторів:
Для char
масивів, якщо ви знаєте , що вихідний масив є нулем і цільової масив досить велике для рядка в початковому масиві, в тому числі нульового термінатора, використання strcpy()
:
#include <string.h>
char array1[18] = "abcdefg";
char array2[18];
...
strcpy(array2, array1);
Якщо ви не знаєте, чи достатньо великий масив призначення, але джерелом є рядок C, і ви хочете, щоб призначення було правильним рядком C, використовуйте snprinf()
:
#include <stdio.h>
char array1[] = "a longer string that might not fit";
char array2[18];
...
snprintf(array2, sizeof array2, "%s", array1);
Якщо вихідний масив не обов'язково закінчується нулем, але ви знаєте, що обидва масиви мають однаковий розмір, ви можете використовувати memcpy
:
#include <string.h>
char array1[28] = "a non null terminated string";
char array2[28];
...
memcpy(array2, array1, sizeof array2);
Ну, технічно ви можете ...
typedef struct { char xx[18]; } arr_wrap;
char array1[18] = "abcdefg";
char array2[18];
*((arr_wrap *) array2) = *((arr_wrap *) array1);
printf("%s\n", array2); /* "abcdefg" */
але це буде виглядати не дуже красиво.
... Якщо ви не використовуєте препроцесор C ...
#define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
{ struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }
Потім ви можете зробити:
char array1[18] = "abcdefg";
char array2[18];
CC_MEMCPY(array2, array1, sizeof(array1));
printf("%s\n", array2); /* "abcdefg" */
І це буде працювати з будь-яким типом даних, а не тільки char
:
int numbers1[3] = { 1, 2, 3 };
int numbers2[3];
CC_MEMCPY(numbers2, numbers1, sizeof(numbers1));
printf("%d - %d - %d\n", numbers2[0], numbers2[1], numbers2[2]); /* "abcdefg" */
(Так, вище код надається на роботу завжди , і це портативний)
Жодне з перерахованого вище не працювало для мене .. це чудово працює
name
ось char *name
що передається через функцію
char *name
використанняstrlen(name)
char
масив однакової довжиниname
вміст до temp
використанняstrcpy(temp, name);
використовуйте як завгодно, якщо хочете повернути оригінальний вміст. strcpy(name, temp);
скопіювати temp назад до name
і voila працює ідеально
const int size = strlen(name);
char temp[size];
cout << size << endl;
strcpy(temp, name);
strcpy
абоmemcpy
.