Массив символов размером 10 отображает 11 символов при печати с использованием% s - PullRequest
0 голосов
/ 29 апреля 2018

Я пытался разгадать тайну в этом коде, но безуспешно. Следующая программа предназначена для печати длины и строки ввода. Максимальный лимит составляет 10 символов, а для строк длиной более 10 символов он учитывает все символы, но хранит только 10.

Что меня смущает, так это то, что при выводе, когда в качестве входных данных подается строка длиной более 10 символов, она печатает первые 11 символов ввода, когда я сохраняю строку в массиве размером 10 символов. Как это возможно?

Я использую GCC Compiler в Linux Mint.

#include<stdio.h>
#define MAX 10

int Getline(char arr[], int lim);

void main(){
    int len=0;
    char c=0;
    char line[MAX]={};

    len=Getline(line,MAX);
    printf("%d\n%s",len,line);
    printf("\nDo you want to continue?\t");

    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("\n%d\n%s",len,line);
        printf("\nDo you want to continue?\t");
    }
}

int Getline(char line[], int lim){
    int i=0;
    while((line[i]=getchar())!='\n' && i<lim){
        i++;
    }

    if(line[i]=='\n' && i<lim)   
    {
        line[i]='\0'; // This is line[lim+1]
        return i;
    }
    else if(i==lim){
    while(getchar()!='\n')
    i++;
    return i+1;
    }
}

Входные и выходные данные как показано ниже, и я использую компилятор gcc в Linux Mint.

ВЫВОД:

Queen
5
Queen
Do you want to continue?        yQueenOfDragons

14
QueenOfDrag
Do you want to continue?        y123456789012345

15
12345678901
Do you want to continue?        yYouKnowNothingJonSnow

21
YouKnowNoth
Do you want to continue?        n

Также, когда я меняю условия теста в цикле while следующим образом

while(i<lim && (line[i]=getchar())!='\n')

Он печатает странный символ «@» после печати первых 10 символов, когда длина строки превышает ограничение. Выходные данные приведены ниже

ВЫХОД 2:

Queen
5
Queen
Do you want to continue?        yQueenOfDragons

13
QueenOfDra@
Do you want to continue?        y12345678901

10
1234567890@
Do you want to continue?        yYouKnowNothingJonSnow

20
YouKnowNot@
Do you want to continue?        n

Пожалуйста, объясните странное поведение. Заранее спасибо!

PS: Это упражнение 1-16 из «Языка программирования C» Денниса М. Ричи и Брайана Кернигана.

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

Ваша программа вызывает неопределенное поведение для длинных входов в следующей строке путем доступа к line[i]:

while((line[i]=getchar())!='\n' && i<lim){

Вы можете убедиться в этом сами здесь .

Поскольку line указывает на массив размером lim, вам просто нужно проверить, i<lim перед записью в line[i]:

while(i<lim && (line[i]=getchar())!='\n'){

Устранение этой проблемы показывает ту же проблему через несколько строк ( ссылка ):

if(line[i]=='\n' && i<lim)   

После исправления этой проблемы остается проблема, по которой вы передаете printf("%s",… адрес массива символов, который не заканчивается на ноль ( ссылка ).

0 голосов
/ 30 апреля 2018

Я сделал некоторые изменения в вашем коде

#include<stdio.h>
#define MAX 10

int Getline(char arr[], int lim);

void main(){
    int len=0;
    char c=0;
    char line[MAX]={};

    len=Getline(line,MAX);
    printf("%d\n%s",len,line);
    printf("\nDo you want to continue?\t");

    while((c=getchar())=='y'){
        len=Getline(line,MAX);
        printf("\n%d\n%s",len,line);
        printf("\nDo you want to continue?\t");
    }
}

int Getline(char line[], int lim){
    int i=0;
    while((line[i]=getchar())!='\n' && i<lim){
        i++;
    }

    if(line[i]=='\n' && i<lim)   
    {
        line[i]='\0'; // This is line[lim+1]
        return i;
    }
    else if(i==lim){
    line[lim] = '\0'; //Change is being made here adding terminator to string
    while(getchar()!='\n')
    i++;
    return i+1;
    }
}

Пояснение: В строке читаются до нулевого указателя, то есть '\ 0'. Так как вы объявляли его в строке, если размер был больше 10, он показал такое поведение

Хотя я рекомендую практику объявления строки размером max + 1, чтобы исключить возможность переполнения

Поскольку в строке размером 10 должно быть 9 символов и 1 нулевой символ

0 голосов
/ 29 апреля 2018

Я подозреваю, что он печатает 11-й символ из-за выражения while:

while((line[i]=getchar())!='\n' && i<lim){
  i++;
}

Когда i < lim возвращает false, вы уже поместили результат getchar() в line[i].

Кроме того, не забывайте всегда оставлять место для и завершать строки нулевым терминатором. Getline(line, lim) не всегда помещает строку с нулевым символом в конце line.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...