Символ 'N' появляется в конце строки - PullRequest
0 голосов
/ 01 сентября 2018

Я новичок в C и имею дело с проблемой при попытке ввода строки. Более конкретно, при печати строки в конце появляется символ «Ν», и в результате я не могу измерить точное количество символов. Вот мой код:

int main()
{
    int j = 0;
    char c[15];
    printf("Give surname: ");
    scanf(" %s", c);
    for (int i = 0; i<sizeof(c) / sizeof(c[1]); i++)
    {
        if (isalpha(c[i]))
        {
            printf("%c ", c[i]);
            j++;
        }
    }
    printf("\nNumber of characters: %d", j);

    return 0;
}

Например: если ввод "john", то я получаю следующий вывод:

enter image description here

Что я делаю не так?

Ответы [ 3 ]

0 голосов
/ 01 сентября 2018

Это потому, что вы используете оператор sizeof для массива символов, который длиннее фактической строки. Вы можете использовать strlen из string.h, как указано выше, или просто перебирать символы до \0, вот так:

char * p = c;
while(*p++)
    if (isalpha(*p))
        printf("%c ", *p);

А если вас интересует количество символов, вы можете просто вычесть указатели.

0 голосов
/ 01 сентября 2018

Ваш предел цикла неверен. Это заставляет вас оценивать неопределенные данные. Что конкретно не так:

  • Не проверяется на успех scanf
  • Не указывать строку формата с ограниченной длиной, чтобы избежать переполнения массива c[].
  • Как уже упоминалось, итерация всего массива, а не только данных, которые вы предполагаете, была прочитана успешно.

Все это можно исправить, некоторые из них тривиально.

  • Проверьте, что scanf вернул 1
  • Поскольку ваш массив c состоит из 15 символов, а для завершающего nullchar необходимо учитывать пробел, используйте %14s в качестве строки формата
  • Либо используйте strlen в качестве предела для for (каким-то образом, будь то сохранение во временном или непосредственно в условном предложении), либо используйте указатель.

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

Переписано, вот результат:

#include <stdio.h>
#include <ctype.h>

int main()
{
    char c[15];
    int j = 0;

    printf("Give surname: ");
    if (scanf("%14s", c) == 1)
    {
        for (const char *p = c; *p; ++p)
        {
            if (isalpha(*p))
            {
                printf("%c ", *p);
                ++j;
            }
        }

        printf("\nNumber of characters: %d", j);
    }

    return 0;
}

Input

123john456

выход

j o h n
Number of characters: 4
0 голосов
/ 01 сентября 2018

Попробуйте вместо этого использовать функцию strlen(). Он проверяет наличие символа нулевого завершения в конце вашей фактической строки (в отличие от полного массива, который может содержать символы мусора после нулевого символ завершения).

int length = strlen(c);
for (int i = 0; i < length; i++){

Не забудьте #include <string.h>

Смотрите это в действии здесь: https://repl.it/repls/SugaryUnfoldedCleaninstall

Если вам интересно, почему для этого нужно полагаться на функцию, взгляните на источник strlen(). Написание такой функции, которая хорошо работает и является правильной во всех случаях, сложнее, чем кажется.

Дополнительная литература
Как перебрать строку в C

...