Использование нескольких вызовов функций fgets не работает [дублировать]

Если вы не инициализировали ссылочный тип и хотите установить или прочитать одно из его свойств, он будет генерировать исключение NullReferenceException.

Пример:

Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.

Вы можно просто избежать этого, проверив, является ли переменная не нулевой:

Person p = null;
if (p!=null)
{
    p.Name = "Harry"; // Not going to run to this point
}

Чтобы полностью понять, почему выбрано исключение NullReferenceException, важно знать разницу между типами значений и ссылочные типы .

Итак, если вы имеете дело со типами значений, NullReferenceExceptions не может произойти. Хотя вам нужно поддерживать оповещение при работе со ссылочными типами!

Только ссылочные типы, как следует из названия, могут содержать ссылки или буквально буквально ничто (или «нуль»). Если типы значений всегда содержат значение.

Типы ссылок (эти должны быть проверены):

  • динамический
  • объект
  • string

Типы значений (вы можете просто игнорировать эти):

  • Числовые типы
  • Интегральные типы
  • Типы с плавающей запятой
  • decimal
  • bool
  • Пользовательские структуры

9
задан Vayn 7 May 2011 в 00:37
поделиться

7 ответов

scanf() читает именно то, о чём вы его просили, оставив следующий \n с конца этой строки в буфере, где fgets() прочитает его. Либо сделайте что-нибудь, чтобы использовать новую строку, или (мое предпочтительное решение) fgets(), а затем sscanf() из этой строки.

18
ответ дан geekosaur 27 August 2018 в 10:11
поделиться

Следующее работает, если fgets() «пропущен» после использования scanf()

После того, как вы сказали:

scanf("%d", &loops);

Скажите:

char garbage[100];

fgets(garbage,100,stdin);

Это сохранит все, что осталось на входном буфере, в переменную мусора.

Это эффективно очистит входной буфер и позволит вам впоследствии использовать fgets().

EDIT: I недавно выяснили, что есть более легкое решение, чем выше. Если вы скажете getchar () после scanf (), это позволит вам использовать fgets () без проблем. getchar () получит следующий символ во входном буфере, который в этом случае будет «\n». После удаления '\n' из входного буфера fgets должен работать нормально.

0
ответ дан Coder Typist 27 August 2018 в 10:11
поделиться

Vayn,

Geekoaur ответил на ваш вопрос хорошо, я просто указываю еще одну «проблему» с вашим кодом.

Строка s1[strlen(s1)] = '\0'; - это no-op , если s1 уже полностью нулевое завершение до того, как оно выполняется.

Но если s1 NOT allready должным образом завершено нулем до того, как эта строка выполняется (и вам не повезло), это приведет к:

Это связано с тем, что strlen basicaly находит индекс существующего нуль-терминатора и возвращает его! Вот действительная, неоптимизированная реализация strlen:

int strlen(char *string) {
    int i = 0;
    while(string[i] != '\0') {
        ++i;
    }
    return i;
}

Итак ... Если вы ДЕЙСТВИТЕЛЬНО беспокоитесь о том, что строки НЕ были обнулены нулями, вы бы сделали что-то вроде:

  • string[sizeof(string)]='\0'; в локальных автоматических строках (где компилятор «знает» размер строки);
  • или string[SIZE_OF_STRING] для всех остальных строк, где SIZE_OF_STRING является (чаще всего) константой #define 'd или переменной, которую вы поддерживаете специально для хранения текущего SIZE (не длина) динамически выделяемой строки.

И если вы ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО беспокоились о том, что строки не заканчиваются на нуль (например, вы имеете дело с «грязными» методами libary (например, Tuxedo's ATMI, например), вы также «очищаете» свои «возвращаемые строки» перед передачей их методам подозрительной библиотеки с помощью:

  • до: memset(string, NULL, SIZE_OF_STRING);
  • invoke: DirtyFunction(/*out*/string);
  • после: string[SIZE_OF_STRING]='\0'

SIG11 - это полная привязка для поиска, потому что (если вы не «подключите» их к сигнальному процессору и сказать иначе, они заставляют unix жестко завершать вашу программу, поэтому вы не можете ничего регистрировать (после факта), чтобы помочь выяснить, где-в-а-а-а-а-о-о-о-о ... особенно учитывая, что во многих случаях строка кода, которая выбрасывает SIG11, не находится рядом с фактической причиной потери строки это нуль-терминатор.

Разве это имеет для вас смысл?

Cheers mate. Keith.

PS: ПРЕДУПРЕЖДЕНИЕ: strncpy НЕ все время имеет нулевое значение ... вы, вероятно, имели в виду strlcpy. Я усвоил этот трудный путь ... когда сработал биллинг на 60 миллионов долларов.


EDIT:

FYI: Вот «безопасная» (неоптимизированная) версия strlen который я назову strnlen (я считаю, что это должно быть в stdlib . Вздох.).

// retuns the length of the string (capped at size-1)
int strnlen(char *string, int size) {
    int i = 0;
    while( i<size && string[i]!='\0' ) {
        ++i;
    }
    return i;
}
2
ответ дан corlettk 27 August 2018 в 10:11
поделиться

scanf оставляет пробел во входном буфере, включая символы новой строки. Чтобы использовать fgets для чтения следующей строки, вам нужно вручную удалить оставшуюся часть текущей строки:

int c;
do{
    c = getchar();
}while(c != EOF && c != '\n');
4
ответ дан hugomg 27 August 2018 в 10:11
поделиться

Я знаю, что это очень старый. Я новичок в c и хотел проверить свой метод, который использует getchar:

#include <stdio.h>

int main()
{

    printf("Please enter your name\n");
    char string[10];

    scanf("%s", string);
    printf("Hello %s\n", string);

    //getchar();  # un commenting this line, fgets perfectly works!!
    printf("Please enter your name again\n");

    fgets ( string, 10, stdin );     

    printf("Hello again %s", string);

    getchar();
}
1
ответ дан Michele 27 August 2018 в 10:11
поделиться

просто положите scanf("%d\n",&loops);

вместо scanf("%d",&loops);

1
ответ дан phantom_ab 27 August 2018 в 10:11
поделиться

Я решил вашу проблему. Теперь ваша программа работает нормально. Если у вас есть сомнения, вы можете спросить меня.

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

    int main()
    {
        int i, age;
        char phone[10];
        char name[100];
        printf("ENTER YOUR NAME:");
        fgets(name , 100 , stdin);

        printf("ENTER YOUR AGE:");
        scanf("%d",&age);

        printf("ENTER YOUR PHONE NUMBER:");
        scanf(" ");
        fgets(phone,10,stdin);


        printf("\nStudent detail\n");
        printf("Name: ");
        fputs(name , stdout );
        printf("Age: %d\n",age);
        printf("Phone Number: ");
        puts(phone);
        printf("----\n");
        return 0;

    }
-1
ответ дан Rohit Kadam 27 August 2018 в 10:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: