Обнаружено *** разбивание стека *** при подсчете длины массива - PullRequest
0 голосов
/ 09 мая 2020

Я использую код VS в Ubuntu 20.04. Я изучаю программирование C. Программа должна подсчитать длину массива с помощью функции. во время работы программы я могу ввести данные в массив, но не получить длину массива. Код:

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

int length(char input[])
{
    int count=0;
    for(int i=0;input[i]!=0;i++)
    {
        count++;
    }
    return count;
}
int main()
{
    char name[10];
    printf("Enter name:");
    scanf("%s",&name[10]);
    int count=length(name);
    printf("%d",count);

}

Вывод:

Enter name:abc
*** stack smashing detected; terminated
Aborted (core dumped)

Что не так с кодом?

Ответы [ 2 ]

0 голосов
/ 09 мая 2020
char name[10];
printf("Enter name:");
scanf("%s",&name[10]);

С помощью &name[10] вы пытаетесь получить доступ к несуществующему 10-му элементу массива name и хотите записать строку из этого элемента. Подсчет индекса массива начинается с 0, а не 1. 10 в определении name означает только 10 элементов.

Указанный элемент будет элементом, в котором хранится первый символ строки. Все последующие символы go в последующие элементы name.

Вам необходимо использовать:

scanf("%s",&name[0]);

или

scanf("%s",name);

, поскольку name распадается на указатель на его первый элемент.


Но лучше используйте fgets():

fgets(name, sizeof(name), stdin);

, который гарантирует, что вы не будете писать за пределами указанного массива char .

0 голосов
/ 09 мая 2020

Введите имя: abc *** Обнаружено разрушение стека; завершено Прервано (ядро выгружено)

это потому, что в

scanf("%s",&name[10]); 

вы просите scanf записать после массива с неопределенным поведением

вы хотели

scanf("%s",&name[0]); 

или более простой

scanf("%s",name); 

Но если на входе более 9 символов, вы снова пишете другое неопределенное поведение после массива, поэтому лучше ограничить количество записанных символов, выполняющих:

scanf("%9s",name);

Я использую 9, чтобы оставить место нулевого символа, заканчивающего строку

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

if (scanf("%9s",name) == 1) {
  ...
}

но, возможно, вы также хотели прочитать пробелы среди других символов, чтобы прочитать john doe например, в этом случае:

if (scanf(" %9[^\n]",name) == 1) {
  ...
}

обратите внимание на пробел перед '%', позволяющий обходить пробелы в начале ответа (но не в конце), если вы хочу, чтобы они удалили это пространство


* 1 036 *

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
Enter name:abc
3
pi@raspberrypi:/tmp $ ./a.out
Enter name:jonh doe
8
pi@raspberrypi:/tmp $ ./a.out
Enter name:to long but cut
9
pi@raspberrypi:/tmp $ 

Обратите внимание, что в вашей функции length переменные i и count всегда имеют одно и то же значение, поэтому достаточно одного

...