it-swarm.com.de

Wie wird Speicherplatz für eine Zeichenfolge dynamisch zugewiesen und diese Zeichenfolge vom Benutzer abgerufen?

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

char names[50];

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

Wenn ich einen Zeichenzeiger verwende,

char *names;

dann muss ich Speicher so zuweisen,

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

Auch in diesem Fall besteht die Möglichkeit, dass Speicherplatz verschwendet wird.

Was ich also brauche, ist die dynamische Zuweisung von Speicher für einen String, der genau der Länge des Strings entspricht.

Angenommen,

Wenn die Benutzereingabe "stackoverflow" ist, sollte der zugewiesene Speicher 14 sein (d. H. Länge der Zeichenfolge = 13 und 1 zusätzlicher Speicherplatz für '\ 0').

Wie kann ich das erreichen?

41
Dinesh

Lesen Sie jeweils ein Zeichen (mit getc(stdin)) und vergrößern Sie die Zeichenfolge (realloc).

Hier ist eine Funktion, die ich vor einiger Zeit geschrieben habe. Beachten Sie, dass es nur für die Texteingabe vorgesehen 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;
}
40
cnicutar

Sie könnten ein Array haben, das mit 10 Elementen beginnt. Eingabe Eingabe Zeichen für Zeichen. Wenn es vorbei geht, leiten Sie noch 5 weitere um. Nicht das Beste, aber Sie können den anderen Speicherplatz später freigeben.

6
tekknolagi

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

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

erhält die gesamte Zeile von stdin und ordnet dynamisch den benötigten Speicherplatz zu. Danach müssen Sie natürlich names freigeben.

5
Jytug

Wenn Sie Speicherplatz sparen sollten, lesen Sie jedes Mal char by char und realloc. Die Leistung wird sinken, aber Sie werden diese 10 Bytes sparen. 

Ein weiterer guter Kompromiss ist das Einlesen einer Funktion (unter Verwendung einer lokalen Variablen) und das Kopieren. Der große Puffer hat also einen Funktionsumfang.

5
BigMike

Nachfolgend finden Sie den 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
}
1
Kunal Wadhwa
char* load_string()
 {

char* string = (char*) malloc(sizeof(char));
*string = '\0';

int key;
int sizer = 2;

char sup[2] = {'\0'};

while( (key = getc(stdin)) != '\n')
{
    string = realloc(string,sizer * sizeof(char));
    sup[0] = (char) key;
    strcat(string,sup);
    sizer++

}
return string;

}

int main()
  {
char* str;
str = load_string();

return 0;
  }
1
Shihan

realloc ist eine ziemlich teure Aktion ... hier ist meine Art, einen String zu empfangen, das Realloc-Verhältnis ist nicht 1: 1:

char* getAString()
{    
    //define two indexes, one for logical size, other for physical
    int logSize = 0, phySize = 1;  
    char *res, c;

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

    //get a char from user, first time outside the loop
    c = getchar();

    //define the condition to stop receiving data
    while(c != '\n')
    {
        if(logSize == phySize)
        {
            phySize *= 2;
            res = (char *)realloc(res, sizeof(char) * phySize);
        }
        res[logSize++] = c;
        c = getchar();
    }
    //here we diminish string to actual logical size, plus one for \0
    res = (char *)realloc(res, sizeof(char *) * (logSize + 1));
    res[logSize] = '\0';
    return res;
}
0
Omer

Dies ist ein Funktionsausschnitt, den ich geschrieben habe, um die Benutzereingabe nach einer Zeichenfolge zu scannen und dann diese Zeichenfolge in einem Array zu speichern, das dieselbe Größe wie die Benutzereingabe hat. Beachten Sie, dass ich j auf den 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 andere char * -Variable deklarieren, um den Rückgabewert von dynamicstring () zu speichern, und diese char * -Variable dann freigeben, wenn Sie sie nicht mehr benötigen.

0
André Fael

Hier ist ein Ausschnitt, den ich geschrieben habe, der dieselbe Funktionalität erfüllt.

Dieser Code ähnelt dem von Kunal Wadhwa .

char *dynamicCharString()
{
char *str, c;
int i;
str = (char*)malloc(1*sizeof(char));

while(c = getc(stdin),c!='\n')
{
    str[i] = c;
    i++;
    realloc(str,i*sizeof(char));
}
str[i] = '\0';
return str;
}
0
user8311083

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

Zweitens verwenden Sie strlen, um die genaue Länge der zuvor gespeicherten Zeichenfolge zu messen, und malloc, um Speicher in Heap zuzuordnen, dessen Länge durch strlen definiert ist. Der Code wird 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 in strInHeap mit strcpy und geben Sie den Zeiger auf strInHeap zurück. Die Variable strInStack wird automatisch freigegeben, da sie nur in dieser Unterfunktion vorhanden ist.

0
Edward Xu

Dies ist ein einfacher Ansatz

char *in_str;
in_str=(char *)malloc(512000 * sizeof(char));
scanf("\n%[^\n]",in_str);
0
Kiran JD