Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > strlen() incompatiable implicit declaration


Автор: paperstreet7 1.9.2011, 20:28
Здравствуйте!
Читаю книгу Стивена Прата "Язык Си" 1988 года. Многое там не совпадает с нынешней действительностью, но это единственная бумажная книга, которая у меня есть. 
До этого немного учил С++. Вот решил забегая вперед написать код с двумя функциями. 

Коротко о том, что делает программа - она спрашивает имя пользователя, заносит в переменную и по желанию пользователя подсчитывает количество букв в его имени. 

Код

#include<stdio.h>
#include<stdlib.h>

char OK_function(char);
char NO_function(void);

int main()
{
    char username[30];
    char answer = 'y';

    printf("What's your name?\n");
    scanf("%s", username);
    printf("Hello, %s! ", username);
    printf("My name is Gerty. Nice to meet you.\n");
    printf("I can tell you how many letters there are in your name.\n");
    printf("Do you want to know? Y/N\n");
    scanf("%c", answer);

    if(answer == 'y' || answer == 'Y')
    {
        OK_function(username);
    }
    else
    {
        NO_function();
    }

    getchar();
    return 0;
}

char OK_function(char username)
{
    printf("Your name consists of %d letters.\n", strlen(username));
    return 0;
}
char NO_function(void)
{
    printf("Very sad. May be some other time. Bye!\n");
    return 0;
}


Code::blocks после компиляции выдает 0 ошибок и 2 предупреждения:

\Documents\hello_world.c||In function 'main':|
\Documents\hello_world.c|20|warning: passing argument 1 of 'OK_function' makes integer from pointer without a cast|
\Documents\hello_world.c|4|note: expected 'char' but argument is of type 'char *'|
\Documents\hello_world.c||In function 'OK_function':|
\Documents\hello_world.c|33|warning: incompatible implicit declaration of built-in function 'strlen'|
||=== Build finished: 0 errors, 2 warnings ===|

Во время запуска программы Windows 7 выдает сообщение об ошибке и предлагает сделать отладку с помощью MS Visual Studio 2010. Я отклоняю предложение и вижу что консоль тоже выдала ошибку:

process returned -107374...

Теперь собственно сам вопрос: я так понял, что здесь что-то не так с указателями (я эту тему еще не проходил и их не использовал) и с функцией strlen(). А вот что именно не так, не понятно.

Добавлено через 11 минут и 35 секунд
Я вот думаю, правильно ли я сделал, что поставил return 0; в функциях или надо было return void;
И еще не уверен в синтаксисе strlen()

Компилятор gcc-mingw

Система Win 7 64-bit;
процессор Intel Celeron D 3333 Ghz;

Автор: newbee 1.9.2011, 20:50
#include<string.h> - в начало и OK_FUNCTION должен принимать тип char*, так как это строка, а просто char - это один символ, грубо говоря буква, строки.

Автор: volatile 2.9.2011, 00:16
Цитата(paperstreet7 @  1.9.2011,  20:28 Найти цитируемый пост)
  char username[30];
    char answer = 'y';

    printf("What's your name?\n");
    scanf("%s", username);

Программка очень недружелюбно обойдется с пользователями чье имя длиннее 29 символов.
Может даже диск им отформатировать, если повезёт.

Автор: Чoо 2.9.2011, 07:40
с диском это фантастика, не?

Автор: rodnover 2.9.2011, 07:46
Не. Стандартная фича переполнения стека. smile

Автор: paperstreet7 2.9.2011, 21:19
Цитата(newbee @  1.9.2011,  20:50 Найти цитируемый пост)
#include<string.h> - в начало и OK_FUNCTION должен принимать тип char*, так как это строка, а просто char - это один символ, грубо говоря буква, строки.

Сделал все как написано. Ошибок 0, предупреждений 0. При выполнении все равно выдает ошибку. 
Пробовал тоже самое в Dev-C++. Тот же результат. 

Вот код:
Код

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

char OK_function(char*);
char NO_function(void);

int main()
{
    char username[30];
    char answer = 'y';

    printf("What's your name?\n");
    scanf("%s", username);
    printf("Hello, %s! ", username);
    printf("My name is Gerty. Nice to meet you.\n");
    printf("I can tell you how many letters there are in your name.\n");
    printf("Do you want to know? Y/N\n");
    scanf("%c", answer);

    if(answer == 'y' || answer == 'Y')
    {
        OK_function(username);
    }
    else
    {
        NO_function();
    }

    getchar();
    return 0;
}

char OK_function(char* username)
{
    printf("Your name consists of %d letters.\n", strlen(username));
    return 0;
}
char NO_function(void)
{
    printf("Very sad. May be some other time. Bye!\n");
    return 0;
}



Автор: paperstreet7 2.9.2011, 21:39
Я понял в чем было дело. Пришлось комментировать куски кода, чтобы выявить проблемную строку. 
Код

scanf("%c", answer);


А нужно было вот так:
Код

scanf("%c", &answer);


Вот окончательная рабочая версия кода:
Код

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

char OK_function(char*);
char NO_function();

int main()
{
    char username[50];
    char answer = 'y';

    printf("What's your name?\n");
    scanf("%s", username);
    printf("Hello, %s! ", username);
    printf("My name is Gerty. Nice to meet you.\n");
    printf("I can tell you how many letters there are in your name.\n");
    printf("Do you want to know? Y/N\n");
    getchar();
    scanf("%c", &answer);

    if(answer == 'y' || answer == 'Y')
    {
        OK_function(username);
    }
    else
    {
        NO_function();
    }
    return 0;
}


char OK_function(char *username)
{
    printf("Your name consists of %d letters.\n", strlen(username));
    return 0;
}
char NO_function()
{
    printf("Very sad. May be some other time. Bye!\n");
    return 0;
}


Добавлено через 3 минуты и 23 секунды
Все. Всем спасибо! Тема закрыта. 

Автор: Чoо 2.9.2011, 23:01
Цитата(rodnover @  2.9.2011,  07:46 Найти цитируемый пост)
Не. Стандартная фича переполнения стека. smile 

есть где почитать об этом?

Автор: volatile 2.9.2011, 23:46
Цитата(Чoо @  2.9.2011,  23:01 Найти цитируемый пост)
есть где почитать об этом? 

Чoо, недалеко после строки, расположен адрес возврата из функции.
Если введенная строка превысит размер, она затрет этот адрес.
В результате функция после завершения, вернется не туда, откуда она была вызвана, а неизвестно куда.
И выполнит там неизвестно что. Скорей всего конечно прога просто повиснет, но может и диск отформатировать...

наберите в поисковике "переполнеие стека", если уж нужна более подробная инфа...


Цитата(paperstreet7 @  2.9.2011,  21:39 Найти цитируемый пост)
 char username[50];

Это не решение проблемы. У пользователя может запасть клавиша, и диск таки будет отформатирован  smile 

Более менее маломальская защита от дурака:
Код

   char username[50];
   printf("What's your name?\n");
   fgets(username, sizeof(username), stdin);
   printf("Hello, %s! ", username);


Автор: Чoо 3.9.2011, 01:26
volatile, оК, погуглю, спасиб smile
вообще я первое время за пределы массива выходил довольно часто, пока не привык как надо работать. Хорошо программа завершалась не так фатально smile

Автор: rodnover 3.9.2011, 06:35
Ну запавшей клавишей диск только у клавиатуры Чака Норриса диск сможет отформатироваться, но если контроллер клавиатуры заглючит и начнет двоичную строку в стек писать. smile

wasm.ru там куча подобной инфы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)