Wie kopiere ich ein char-Array in C?

77

In C habe ich zwei Char-Arrays:

char array1[18] = "abcdefg";
char array2[18];

Wie kopiere ich den Wert von array1nach array2? Kann ich das einfach machen : array2 = array1?

user2131316
quelle
3
strcpyoder memcpy.
Alok Save
1
char array1[18] = {"abcdefg"};ist kein richtiges char-Array.
Aragaer
Verwenden Sie die Funktion strcpy (array2, array1)
Rohan
1
Während es als char-Array funktioniert (funktioniert zufällig), sollte es entweder als char array1[18] = "abcdefg";oderchar array1[18] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
aragaer
13
@aragaer 6.7.9 (14): "Ein Array vom Zeichentyp kann durch ein Zeichenfolgenliteral oder ein UTF-8-Zeichenfolgenliteral initialisiert werden, das optional in geschweiften Klammern eingeschlossen ist ." char array1[18] = {"abcdefg"};ist ungewöhnlich, aber 100% pukka.
Daniel Fischer

Antworten:

82

Sie können dies nicht direkt tun array2 = array1, da Sie in diesem Fall die Adressen der Arrays ( char *) und nicht deren innere Werte ( char) bearbeiten .

Konzeptionell möchten Sie alle Zeichen Ihrer Quelle ( Array1 ) durchlaufen und in das Ziel ( Array2 ) kopieren . Es gibt verschiedene Möglichkeiten, dies zu tun. Zum Beispiel könnten Sie eine einfache for-Schleife schreiben oder verwenden memcpy.

Die empfohlene Methode für Zeichenfolgen ist jedoch die Verwendung strncpy. Es verhindert häufige Fehler, die beispielsweise zu Pufferüberläufen führen (was besonders gefährlich ist, wenn array1sie durch Benutzereingaben gefüllt werden: Tastatur, Netzwerk usw.). Wie so:

// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);

Als @Prof. Falken in einem Kommentar erwähnt, strncpy kann böse sein . Stellen Sie sicher, dass Ihr Zielpuffer groß genug ist, um den Quellpuffer zu enthalten (einschließlich des \0am Ende der Zeichenfolge).

Aymericbeaumet
quelle
warum können wir nicht einfach array2 = array1 machen?
user2131316
2
@ user2131316: Dies liegt an der Art und Weise, wie Array-Namen semantisch in Zeigerwerte konvertiert werden. Ich erkläre dies in meiner Antwort.
jxh
Es hat mich verwirrt, dass Sie erwähnen array1=array2, was impliziert, dass array1 den neuen Wert erhält, aber Ihr Code macht es umgekehrt. Nur für den Fall, dass jemand anderes darauf hereinfällt.
Lucidbrot
33

Wenn Ihre Arrays keine String-Arrays sind, verwenden Sie: memcpy(array2, array1, sizeof(array2));

kAmol
quelle
19
Das erste Argument von memcpy ist das Zielarray, das array2 sein sollte!
Bert Regelink
Würde sizeof () nicht die Größe des Zeigers zurückgeben (dh die Wortgröße auf Ihrem Computer)?
Wecherowski
1
@Wecherowski: Wenn Sie ein Array an eine Funktion übergeben, wird es zu einem Zeiger. Innerhalb dieser Funktion können Sie dann nicht sizeof()die Größe des Arrays bestimmen. Ansonsten sizeof()funktioniert gut für diese Aufgabe.
Bugfinger
26

Wenn Sie sich vor nicht terminierten Zeichenfolgen schützen möchten, die alle möglichen Probleme verursachen können, kopieren Sie Ihre Zeichenfolge wie folgt:

char array1[18] = {"abcdefg"};
char array2[18];

size_t destination_size = sizeof (array2);

strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';

Diese letzte Zeile ist eigentlich wichtig, da strncpy()sie nicht immer mit Null endet Zeichenfolgen . (Wenn der Zielpuffer zu klein ist, um die gesamte Quellzeichenfolge zu enthalten, beendet sntrcpy () die Zielzeichenfolge nicht mit Null.)

In der Manpage für strncpy () heißt es sogar: "Warnung: Wenn unter den ersten n Bytes von src kein Nullbyte vorhanden ist, wird die in dest platzierte Zeichenfolge nicht nullterminiert."

Der Grund, warum sich strncpy () so seltsam verhält, ist, dass es ursprünglich nicht als sichere Methode zum Kopieren von Zeichenfolgen gedacht war.

Eine andere Möglichkeit besteht darin, snprintf () als sicheren Ersatz für strcpy () zu verwenden:

snprintf(array2, destination_size, "%s", array1);

(Danke jxh für den Tipp.)

Prof. Falken
quelle
2
Beachten Sie, dass snprintf()das Problem strncpy()nicht besteht.
jxh
Erzeugt dies keine Warnung? strncpy akzeptiert const char als Quelle.
Kon Psych
@konpsych das sollte keine Warnung generieren.
Prof. Falken
6

Sie können keine Arrays zuweisen, die Namen sind Konstanten, die nicht geändert werden können.

Sie können den Inhalt kopieren mit:

strcpy(array2, array1);

Angenommen, die Quelle ist eine gültige Zeichenfolge und das Ziel ist groß genug, wie in Ihrem Beispiel.

entspannen
quelle
5

Wie andere angemerkt haben, werden Zeichenfolgen mit strcpy()oder deren Varianten kopiert . In bestimmten Fällen können Sie auch verwenden snprintf().

Sie können Arrays im Rahmen einer Strukturzuweisung nur so zuweisen, wie Sie es möchten:

typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;

array2 = array1;

Wenn Ihre Arrays an eine Funktion übergeben werden, können Sie sie anscheinend zuweisen, dies ist jedoch nur ein Zufall der Semantik. In C zerfällt ein Array in einen Zeigertyp mit dem Wert der Adresse des ersten Mitglieds des Arrays, und dieser Zeiger wird übergeben. Ihr Array-Parameter in Ihrer Funktion ist also wirklich nur ein Zeiger. Die Zuordnung ist nur eine Zeigerzuweisung:

void foo (char x[10], char y[10]) {
    x = y;    /* pointer assignment! */
    puts(x);
}

Das Array selbst bleibt nach der Rückkehr von der Funktion unverändert.

Diese Semantik "Zerfall auf Zeigerwert" für Arrays ist der Grund dafür, dass die Zuweisung nicht funktioniert. Der l-Wert hat den Array-Typ, aber der r-Wert ist der verfallene Zeigertyp, sodass die Zuordnung zwischen inkompatiblen Typen erfolgt.

char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
                    but array2 is still an array type */

Um herauszufinden, warum die Semantik "Zerfall in Zeigerwert" eingeführt wurde, sollte eine Quellcode-Kompatibilität mit dem Vorgänger von C erreicht werden. Weitere Informationen finden Sie unter Die Entwicklung der C-Sprache .

jxh
quelle
Die einzige Antwort, die erklärt, warum array2 = array1;nicht funktioniert. Upvote.
Miljen Mikic
3

es sollte so aussehen:

void cstringcpy(char *src, char * dest)
{
    while (*src) {
        *(dest++) = *(src++);
    }
    *dest = '\0';
}
.....

char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
Boris
quelle
1
Ihre cstringcpyFunktion beendet das Zielarray nicht mit Null.
Chqrlie
habe es nicht verstanden. Bitte geben Sie Ihren "Fix" an.
Boris
@ zett42: Beachten Sie, dass diese cstringcpyFunktion strcpymit denselben Mängeln fast genau semantisch äquivalent ist , nämlich keine Überprüfung auf Pufferüberlauf.
Chqrlie
2

Ich empfehle, memcpy () zum Kopieren von Daten zu verwenden. Auch wenn wir einen Puffer einem anderen als zuweisen array2 = array1, haben beide Arrays den gleichen Speicher und jede Änderung in arrary1 wird auch in Array2 abgelenkt. Aber wir verwenden memcpy, beide Puffer haben unterschiedliche Arrays. Ich empfehle memcpy (), da strcpy und die zugehörige Funktion kein NULL-Zeichen kopieren.

akhil
quelle
1
array2 = array1;

wird in c nicht unterstützt. Sie müssen Funktionen wie strcpy () verwenden, um dies zu tun.

MOHAMED
quelle
1

c Funktionen nur unten ... c ++ Sie müssen ein char-Array ausführen, dann eine Zeichenfolgenkopie verwenden und dann die Zeichenfolgen-Tokenizor-Funktionen verwenden ... c ++ hat es sehr viel schwieriger gemacht, irgendetwas zu tun

#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;
}
geneemailbox1 geneemailbox1
quelle
0

für ganzzahlige Typen

#include <string.h>    

int array1[10] = {0,1,2,3,4,5,6,7,8,9};
int array2[10];


memcpy(array2,array1,sizeof(array1)); // memcpy("destination","source","size")
D0rm1nd0
quelle
1
Das wird nicht kompiliert. Verwenden Sie int array1[10] = {0,1,2,3,4,5,6,7,8,9};stattdessen.
Tim
0

Sie können keine Arrays zum Kopieren zuweisen. Wie Sie den Inhalt eines in einen anderen kopieren können, hängt von mehreren Faktoren ab:

charWenn Sie für Arrays wissen, dass das Quellarray nullterminiert ist und das Zielarray groß genug für die Zeichenfolge im Quellarray ist, einschließlich des Nullterminators, verwenden Sie strcpy():

#include <string.h>

char array1[18] = "abcdefg";
char array2[18];

...

strcpy(array2, array1);

Wenn Sie nicht wissen, ob das Zielarray groß genug ist, die Quelle jedoch eine C-Zeichenfolge ist und das Ziel eine richtige C-Zeichenfolge sein soll, verwenden Sie snprinf():

#include <stdio.h>

char array1[] = "a longer string that might not fit";
char array2[18];

...

snprintf(array2, sizeof array2, "%s", array1);

Wenn das Quellarray nicht unbedingt nullterminiert ist, Sie jedoch wissen, dass beide Arrays dieselbe Größe haben, können Sie Folgendes verwenden memcpy:

#include <string.h>

char array1[28] = "a non null terminated string";
char array2[28];

...

memcpy(array2, array1, sizeof array2);
chqrlie
quelle
0

Technisch gesehen können Sie ...

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" */

aber es wird nicht sehr schön aussehen.

… Es sei denn, Sie verwenden den C-Präprozessor…

#define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
    { struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }

Sie können dann tun:

char array1[18] = "abcdefg";
char array2[18];

CC_MEMCPY(array2, array1, sizeof(array1));

printf("%s\n", array2);     /* "abcdefg" */

Und es funktioniert mit jedem Datentyp, nicht nur 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" */

(Ja, über der Code gewährt , um Arbeit immer und es ist tragbar)

Madmurphy
quelle
0

Keines der oben genannten hat bei mir funktioniert .. das funktioniert namehier perfekt , char *namewas über die Funktion übergeben wird

  1. Holen Sie sich die char *nameNutzungsdauerstrlen(name)
  2. Das Speichern in einer const-Variablen ist wichtig
  3. Erstellen Sie ein charArray mit der gleichen Länge
  4. Kopieren Sie nameden Inhalt zu tempverwendenstrcpy(temp, name);

Verwenden Sie, wie Sie möchten, wenn Sie den ursprünglichen Inhalt zurückhaben möchten. Kopiertemp strcpy(name, temp);zurück nach nameund voila funktioniert perfekt

    const int size = strlen(name);
    char temp[size];
    cout << size << endl;
    strcpy(temp, name);
Bilal Haider Qureshi
quelle