Не удается динамически выделить строку - PullRequest
0 голосов
/ 25 марта 2020

Я пытался динамически распределить строку, используя функцию, которую я назвал ALLO, но когда я выполняю, я получаю ошибку, из-за которой моя функция ALLO не может получить строку, используя getc, она пропускается.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ALLO(char *str){
    char  c=0;
  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
}
int main(){
    char *NomAF;
    int NAF;
    printf("Entrer le nombre des ateliers : ");
    scanf("%d",&NAF);
    ALLO(NomAF);
    return 0 ;
}

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Семантика неверна.

Вы запрашиваете у пользователя имена спортсменов, а затем сканируете их в целое число. Сначала вы должны узнать количество спортсменов. Затем после этого вы выделяете память для размещения каждого имени.

int num_names;
scanf("%d", &num_names);

После того, как вы знаете количество имен, вы затем выделяете буфер для каждого имени отдельно.

char **names;
names = malloc(num_names * sizeof(char **));
for(int i = 0; i < num_names; i++)
    ALLOC(&names[i]);

Кроме того, вам не следует используя scanf для ввода пользователя. Вместо этого используйте fgets, что немного лучше.

Затем вы также должны использовать pointer to pointers для получения этих строк.

Немного модифицированная версия вашего кода (которую вы следует пересмотреть и исправить, если необходимо):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void ALLO(char **str){
    /* use INT for getc() return */
    int  c=0, i = 0;

    /* you are gettting 1 byte of memory */
    *str = malloc(sizeof **str);

    /* should use fprintf(stderr...) or fflush(stdout) to guarantee 
     * the sentence will be seen by user
     */
    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
        /* i = 0 in the first run,
         *
         * and you have 1 byte alloced in the first run.
         *
         * so you get 1 byte for actual getc() return
         * 1 byte for next character + NULL byte
         *
         * NOTE: you are STORING the NULL byte in your string. You only
         * check for it AFTER you do the assignment, so your strings
         * contain a newline before the NULL byte.
         */
        *str = (char*)realloc(*str, (i + 2) * sizeof **str);

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

        // you can use only 'i' for this...
        i++;
        /* @i
         * 
         * Using only 'i' requires that you understand what @i is doing
         * during execution. @i will keep the current buffer position,
         * and you know you need one more position for the next
         * character and one more for the NULL byte. 
         *
         * Therefore, in your realloc statemente, you need @(i + 2)
         */
    }

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

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

    // if you free here, you can't get the string at @main for printing.
    // free is the last step
    //free(str); // important step the pointer declared must be made free
}

int main(){
    char **NomAF;
    int NAF, i;
    char buf[100];

    printf("Number of athlets : ");
    fgets(buf, sizeof(buf), stdin);
    NAF = atoi(buf);

    NomAF = malloc(NAF * sizeof *NomAF);
    // check malloc errors

    // get names
    for(i = 0; i < NAF; i++) {
        ALLO(&NomAF[i]);
        printf("New name: %s\n", NomAF[i]);
    }

    // print names, then free() then
    for(i = 0; i < NAF; i++) {
        printf("Name: %s\n", NomAF[i]);
        free(NomAF[i]);
    }

    // free the base pointer
    free(NomAF);

    return 0 ;
}
0 голосов
/ 25 марта 2020

Добавьте это

 while((c=getchar()!='\n')&&c!=EOF);

до получения c, оно пропускает пробел.

Поскольку после этого scanf("%d",&NAF); вы даете ввод 5(+enter) это идет 5'\n' 5 получен scanf, а '\ n' находится в буфере, и эта новая строка получена вашим getc.

и измените этот str[i] = '\0'; на str[i-1] = '\0';, он заменяет новую строку на NULL и вы выделили память только для i символов.

Вы можете вернуть строку с помощью return str; и изменить тип возвращаемого значения функции на char* или, если вы не хотите, принимать параметр, выделенный с помощью mallo c.

См. Это:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void ALLO(char *str)
{
char  c=0;
int i = 0;

printf("Enter String : ");

while (c != '\n')
{
    while((c=getchar()!='\n')&&c!=EOF);
    c = getc(stdin);
    str = (char*)realloc(str, (i+1) * sizeof(char));
    if(!str) exit(1);
    str[i] = c;
    i++;
}
str[i-1] = '\0';
}

int main()
{
    char *NomAF;
    int NAF;
    NomAF=malloc(sizeof(char));
    if(!NomAF) exit(1);
    printf("Entrer le nombre des ateliers : ");
    scanf("%d",&NAF);
    ALLO(NomAF);
    printf(NomAF);
    free(NomAF);
    return 0 ;
}

вывод:

Entrer le nombre des ateliers : 5
Enter String : a
s
d
f
g
     ----->newline to stop the loop
asdfg
Process returned 0 (0x0)   execution time : 8.205 s
Press any key to continue.

Я ввел его как строку, а не символ за символом, спрашивать пользователя не практично ввод букв за буквой

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

char * inputword(char **);

int main()
{
    char *word;

    printf("Enter Word:");
    word=inputword(NULL);
    printf("Word Entered:%s",word);
    free(word);

    printf("\nEnter Word 2:");
    inputword(&word);
    printf("Word Entered:%s",word);
    free(word);
    return 0 ;
}

char *inputword(char **word)
{
    char *str=NULL,ch,*memerr="Memory Error";
    int i=0,flag=1;

    do
    {
    str=realloc(str,((i+1)*sizeof(char)));
    if(!str)
    {
        printf(memerr);
        exit(1);
    }
    ch = getch();
    switch(ch)
    {
      case 13:
         str[i] = '\0';
         putc('\n',stdout);
         flag=0;
         break;
      case '\b':
         if(i>0) i--;
         str[i--]='\0';
         printf("\b \b");
         break;
      default:
         str[i] = ch;
         putc(ch,stdout);
    }
    i++;
    }while(flag);

    if(word!=NULL)
        *word=str;

    return str;
}

вывод:

Enter Word:Hai, How are You?(1 String)
Word Entered:Hai, How are You?(1 String)
Enter Word 2:Hai, How are You?(2 string)
Word Entered:Hai, How are You?(2 string)
Process returned 0 (0x0)   execution time : 58.883 s
Press any key to continue.
...