Строка и функция работают странно, как ее исправить? [Дубликат]

В то время как , что вызывает NullReferenceExceptions и подходит к avoid / fix , такое исключение было рассмотрено в других ответах, что многие программисты не имеют " t узнал еще, как независимо отлаживать такие исключения во время разработки.

В Visual Studio это обычно легко благодаря Visual Studio Debugger .


Во-первых, убедитесь, что правильная ошибка будет обнаружена - см. . Как разрешить нарушение «Исключение System.NullReferenceException» в VS2010? Примечание1

Затем либо Начать с отладки (F5) , либо Приложить [отладчик VS] к запуску процесса . Иногда может быть полезно использовать Debugger.Break , в котором будет предложено запустить отладчик.

Теперь, когда NullReferenceException выбрано (или необработанно), отладчик остановится ( помните правило, указанное выше?) в строке, на которой произошло исключение. Иногда ошибка может быть легко обнаружена.

Например, в следующей строке единственный код, который может , вызывает исключение, если myString имеет значение null. Это можно проверить, посмотрев окно Watch или выполнив выражения в окне Immediate Window .

var x = myString.Trim();

В более сложных случаях, таких как следуя ниже, вам нужно будет использовать один из методов выше (Watch или Immediate Windows) для проверки выражений, чтобы определить, было ли str1 пустым или если str2 имеет значение null.

var x = str1.Trim() + str2.Trim();

Once , где было выбрано исключение, это обычно тривиально по отношению к разуму назад, чтобы выяснить, где введенное значение null было [неправильно] -

. Найдите время, необходимое для понимания причина исключения. Проверьте нулевые выражения. Проверьте предыдущие выражения, которые могли бы привести к таким нулевым выражениям. Добавьте контрольные точки и, по мере необходимости, пройдите через программу. Используйте отладчик.


1 Если Break on Throws слишком агрессивен и отладчик останавливается на NPE в библиотеке .NET или сторонних разработчиков, Break на User-Unhandled можно использовать для ограничения выловленных исключений. Кроме того, VS2012 представляет Just My Code , который я рекомендую также включить.

Если вы отлаживаете с включенным Just My Code, поведение немного отличается. При включенном Just My Code отладчик игнорирует исключения, связанные с привилегиями обычного языка (CLR) первого шанса, которые выходят за пределы My Code и не проходят через My Code

blockquote>

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

7 ответов

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

18
ответ дан geekosaur 26 August 2018 в 18:41
поделиться

Следующее работает, если 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 26 August 2018 в 18:41
поделиться

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 26 August 2018 в 18:41
поделиться

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

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

Я знаю, что это очень старый. Я новичок в 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 26 August 2018 в 18:41
поделиться

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

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

1
ответ дан phantom_ab 26 August 2018 в 18:41
поделиться

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

    #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 26 August 2018 в 18:41
поделиться
Другие вопросы по тегам:

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