>

stdin 버퍼에 문제가 있습니다. 통찰력에 감사드립니다.성에 대한 사용자 입력을받는이 함수가 있습니다.

void lastName(int *counter, User *pt) {
    for (int i = *counter; i < (*counter + 1); i++) {
        pt[i].lastName = calloc (MAX_LENGTH, sizeof(char));
        printf("Enter Last Name: ");
        fgets(pt[i].lastName, MAX_LENGTH, stdin);
        strtok(pt[i].lastName, "\n");
    }
}

ID에 대한 사용자 입력을받는이 기능도 있습니다

void id(int *counter, User *pt) {
    char num[MAX_LENGTH];
    long temp;
    for (int i = *counter; i < *counter + 1; i++) {
        printf("Enter the ID of %s: ", pt[i].firstName);
        fgets(num, MAX_LENGTH, stdin);
        strtok(num, "\n");
        temp = strtol(num, NULL, 10);
        pt[i].id = (int) temp;
    }
}

이것은 내가 메인에서 전화하는 방법입니다

lastName(&counter, pt);
id(&counter, pt);

성이 매우 긴 성을 입력하면 잘라내어 MAX_LENGTH로 표시되지만 ID의 fget은 건너 뛰고 그렇지 않으면 제대로 작동합니다. 이 경우 내 fgets가 어떻게 작동하는지 궁금합니다. MAX_LENGTH는 10입니다. while (getchar ()! = '\ n');작동하지만 Enter 키를 두 번 눌러야합니다.

Enter First Name: Test
Enter Last Name: Williamsamsmases
Enter the ID of Test: Would you like to enter a User?(Y/N):N


  • 답변 # 1

    목적지 버퍼가 보유 할 수있는 것보다 긴 행을 입력하면 fgets  대상이 가득 찰 때까지 가능한 모든 것을 읽습니다. 나머지 입력은 입력 버퍼에 남아 있으므로 다음 fgets  전화는 남은 내용을 읽습니다.

    대상 버퍼에 줄 바꿈이 없으면 3 가지 옵션이 있습니다 :

    <올>

    입력 한 행이 대상이 보유 할 수있는 것보다 깁니다. 이 경우 fgets 에게 계속 전화해야합니다  개행 문자가 버퍼에 올 때까지

    이 기능으로 입력 버퍼를 "청소"할 수 있습니다 :

    void clean_stdin(void)
    {
        int c;
        while((c = getchar()) != '\n' && c != EOF);
    }
    
    

    다음에 줄 바꿈이 없다는 것을 알게되면 호출 할 수 있습니다 대상 버퍼. 하지만 fgets 에 전화 할 때마다 전화하지 마십시오 , 당신은 할 수 있습니다 입력에 문자가 남아 있음을 알면이 함수를 호출하십시오. 버퍼 (대상 버퍼에 줄 바꿈이없는 경우) 그렇지 않으면이 함수는 사용자 입력을 기다립니다.

    시스템에서 getline 를 지원하는 경우 그러면 읽을 수 있습니다. 전체 라인과 getline  필요한 메모리 할당을 처리합니다. 그것 :

    char *line = NULL;
    size_t n = 0;
    if(getline(&line, &n, stdin) == -1)
    {
        // error
    }
    ...
    free(line);
    
    

    getline 인 경우  시스템에서 사용할 수 없으면 함수를 작성할 수 있습니다 그것은 getline 를 모방 , 이와 같은 것 :

    char *fgets_long(FILE *fp)
    {
        size_t size = 0, currlen = 0;
        char line[1024];
        char *ret = NULL, *tmp;
        while(fgets(line, sizeof line, fp))
        {
            int wholeline = 0;
            size_t len = strlen(line);
            if(line[len - 1] == '\n')
            {
                line[len-- - 1] = 0;
                wholeline = 1;
            }
            if(currlen + len >= size)
            {
                // we need more space in the buffer
                size += (sizeof line) - (size ? 1 : 0);
                tmp = realloc(ret, size);
                if(tmp == NULL)
                    break; // return all we've got so far
                ret = tmp;
            }
            memcpy(ret + currlen, line, len + 1);
            currlen += len;
            if(wholeline)
                break;
        }
        if(ret)
        {
            tmp = realloc(ret, currlen + 1);
            if(tmp)
                ret = tmp;
        }
        return ret;
    }
    
    
    이 기능은 fgets 처럼 작동합니다  그러나 그것은 당신이 전체를 읽는 것을 보장합니다 라인에서이 함수는 대상에 충분한 메모리를 할당합니다.

  • 답변 # 2

    fgets 에 전화 할 때 stdin 에서 입력을 읽습니다.  삽입되는 변수가 가득 찰 때까지. 일단 입력되면 입력 버퍼의 나머지 입력은 그대로 유지됩니다. 한 가지 해결책은 각 값을 읽은 후 입력 버퍼를 지우는 것입니다.

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

    본질적으로 버퍼에서 읽고 \n 까지 값을 버립니다.  또는 EOF  도달했습니다.

관련 자료

  • 이전 ibm cloud infrastructure - 데이터 센터별로 CreateObjectOptions를 얻는 방법
  • 다음 php - mysqli_stmt_bind_result를 사용하여 세션 값을 데이터베이스 값으로 설정