Wie weist man dynamisch Speicherplatz für eine Zeichenfolge zu und erhält diese Zeichenfolge vom Benutzer?

Lesezeit: 5 Minuten

Dineshs Benutzeravatar
Dinesh

Ich möchte Eingaben von Benutzern mit einem C-Programm lesen. Ich möchte kein Array wie verwenden,

char names[50];

denn wenn der Benutzer eine Zeichenfolge der Länge 10 angibt, werden die verbleibenden Leerzeichen verschwendet.

Wenn ich Zeichenzeiger wie verwende,

char *names;

dann muss ich dafür Speicher so zuweisen,

names = (char *)malloc(20 * sizeof(char));

Auch in diesem Fall besteht die Möglichkeit einer Speicherverschwendung.

Was ich also brauche, ist, Speicher für eine Zeichenfolge dynamisch zuzuweisen, die genau der Länge der Zeichenfolge entspricht.

Angenommen,

Wenn die Benutzereingabe ist "stackoverflow"dann sollte der zugewiesene Speicher von sein 14 (dh Länge des Strings = 13 und 1 zusätzliches Leerzeichen für ‘\0’).

Wie könnte ich das erreichen?

  • Einige der Compiler haben sich diese Lösung ausgedacht char a[ ] stattdessen heißt das dynamisches Array!

    – Niko

    17. November 2011 um 8:29 Uhr


Lesen Sie jeweils ein Zeichen (mit getc(stdin)) und wachsen Sie die Zeichenfolge (realloc) wenn du gehst.

Hier ist eine Funktion, die ich vor einiger Zeit geschrieben habe. Beachten Sie, dass es nur für die Texteingabe gedacht ist.

char *getln()
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
            ch = 0;

        /* Check if we need to expand. */
        if (size <= index) {
            size += CHUNK;
            tmp = realloc(line, size);
            if (!tmp) {
                free(line);
                line = NULL;
                break;
            }
            line = tmp;
        }

        /* Actually store the thing. */
        line[index++] = ch;
    }

    return line;
}

  • Es ist im Allgemeinen effizienter, die Größe um einen Multiplikationsfaktor zu erhöhen (dh 1,5-mal oder doppelt so groß), es sei denn, Sie wissen, dass Ihre Daten in Datensätzen mit fester Größe vorliegen.

    – Martin Beckett

    2. Dezember 2011 um 17:31 Uhr


  • Dies getln() kehrt nicht zurück NULL am Ende der Datei. Wie prüfen Sie das Dateiende?

    – chqrlie

    4. Januar 2016 um 3:30 Uhr


  • CHUNK ist, wie viele Bytes zugewiesen werden sollen. Sie können es anrufen CHUNKSIZE falls es dadurch klarer wird.

    – Jetblau

    10. August 2019 um 5:18 Uhr

Sie könnten ein Array haben, das mit 10 Elementen beginnt. Eingabe Zeichen für Zeichen lesen. Wenn es vorbei ist, ordnen Sie weitere 5 weitere zu. Nicht das Beste, aber dann können Sie den anderen Speicherplatz später freigeben.

  • Im Linux-Handbuch für vsnprintf genau das tun sie in ihrem Beispiel (obwohl es um die Formatierung der Zeichenfolge geht, nicht um die Eingabe, aber das Prinzip ist dasselbe.)

    – Irgendein Programmierer-Typ

    17. November 2011 um 8:24 Uhr

Wenn Sie Speicherplatz sparen sollten, lesen Sie Zeichen für Zeichen und ordnen Sie jedes Mal neu zu. Die Leistung wird sterben, aber Sie werden diese 10 Bytes verschonen.

Ein weiterer guter Kompromiss besteht darin, eine Funktion (unter Verwendung einer lokalen Variablen) einzulesen und dann zu kopieren. Der große Puffer wird also funktionsbezogen sein.

Sie können auch einen regulären Ausdruck verwenden, zum Beispiel den folgenden Code:

char *names
scanf("%m[^\n]", &names)

erhält die gesamte Zeile von stdin und weist dynamisch den benötigten Speicherplatz zu. Danach muss man sich natürlich befreien names.

Benutzeravatar von Kunal Wadhwa
Kunal Wadhwa

Unten ist der Code zum Erstellen einer dynamischen Zeichenfolge:

void main()
{
  char *str, c;
  int i = 0, j = 1;

  str = (char*)malloc(sizeof(char));

  printf("Enter String : ");

  while (c != '\n') {
    // read the input from keyboard standard input
    c = getc(stdin);

    // re-allocate (resize) memory for character read to be stored
    str = (char*)realloc(str, j * sizeof(char));

    // store read character by making pointer point to c
    str[i] = c;

    i++;
    j++;
  }

  str[i] = '\0'; // at the end append null character to mark end of string

  printf("\nThe entered string is : %s", str);

  free(str); // important step the pointer declared must be made free
}

  • Undefiniertes Verhalten, weil c wird für ersten Test, Endlosschleife und abschließenden Absturz bei leerer Eingabedatei nicht initialisiert.

    – chqrlie

    4. Januar 2016 um 3:24 Uhr

  • Außerdem, was ist mit free(c)? Sollte imo auch notwendig sein!

    – knacker123

    24. Februar 2016 um 23:22 Uhr

Definieren Sie zunächst eine neue Funktion zum Lesen der Eingabe (entsprechend der Struktur Ihrer Eingabe) und speichern Sie die Zeichenfolge, dh den verwendeten Speicher im Stapel. Stellen Sie die Länge der Zeichenfolge so ein, dass sie für Ihre Eingabe ausreicht.

Zweitens verwenden strlen um die exakte verbrauchte Länge der zuvor gelagerten Schnur zu messen, und malloc um Speicher im Heap zuzuweisen, dessen Länge durch definiert ist strlen. Der Code ist unten gezeigt.

int strLength = strlen(strInStack);
if (strLength == 0) {
    printf("\"strInStack\" is empty.\n");
}
else {
    char *strInHeap = (char *)malloc((strLength+1) * sizeof(char));
    strcpy(strInHeap, strInStack);
}
return strInHeap;

Kopieren Sie schließlich den Wert von strInStack zu strInHeap verwenden strcpyund geben Sie den Zeiger auf zurück strInHeap. Das strInStack wird automatisch freigegeben, da es nur in dieser Unterfunktion beendet wird.

  • Undefiniertes Verhalten, weil c wird für ersten Test, Endlosschleife und abschließenden Absturz bei leerer Eingabedatei nicht initialisiert.

    – chqrlie

    4. Januar 2016 um 3:24 Uhr

  • Außerdem, was ist mit free(c)? Sollte imo auch notwendig sein!

    – knacker123

    24. Februar 2016 um 23:22 Uhr

Benutzeravatar von André Fael
Andre Fael

Dies ist ein Funktionsausschnitt, den ich geschrieben habe, um die Benutzereingabe nach einer Zeichenfolge zu durchsuchen und diese Zeichenfolge dann in einem Array mit der gleichen Größe wie die Benutzereingabe zu speichern. Beachten Sie, dass ich j mit dem Wert 2 initialisiere, um das Zeichen „\0“ speichern zu können.

char* dynamicstring() {
    char *str = NULL;
    int i = 0, j = 2, c;
    str = (char*)malloc(sizeof(char));
    //error checking
    if (str == NULL) {
        printf("Error allocating memory\n");
        exit(EXIT_FAILURE);
    }

    while((c = getc(stdin)) && c != '\n')
    {
        str[i] = c;
        str = realloc(str,j*sizeof(char));
        //error checking
        if (str == NULL) {
            printf("Error allocating memory\n");
            free(str);
            exit(EXIT_FAILURE);
        }

        i++;
        j++;
    }
    str[i] = '\0';
    return str;
}

In main() können Sie eine weitere char*-Variable deklarieren, um den Rückgabewert von dynamicstring() zu speichern, und diese char*-Variable dann freigeben, wenn Sie sie nicht mehr verwenden.

1411410cookie-checkWie weist man dynamisch Speicherplatz für eine Zeichenfolge zu und erhält diese Zeichenfolge vom Benutzer?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy