The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Фиксированный размер ввода в scanf"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 13-Дек-05, 15:32  (MSK)
Допустим, что нам надо реализовать ввод в какой-то буфер при помощи функции scanf. Она позволяет избежать переполнения буфера, задав число считываемых символов в строке формата. Например:

char buf[10];

memset( buf, 0 , 10 );
scanf( "%9s", buf );

Вопрос такой: как быть, если этот размер буфера задается в виде директивы define

#define MAX_SIZE 10

char buf[ MAX_SIZE + 1 ];
memset( buf, 0 , MAX_SIZE + 1 );
// До этого момента все пучком
// А вот то, что ниже - не срабатывает так, как надо
scanf( "%MAX_SIZEs", buf );

Как превратить "%MAX_SIZEs" в "s", чтобы scanf это съел?

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]

1. "Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 13-Дек-05, 15:34  (MSK)
Поправка:
Как превратить "%MAX_SIZEs" в "10s", чтобы scanf это съел?
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Фиксированный размер ввода в scanf" 
Сообщение от SergeiZz Искать по авторуВ закладки on 13-Дек-05, 17:05  (MSK)
>Поправка:
>Как превратить "%MAX_SIZEs" в "10s", чтобы scanf это съел?
Составить строку для scanf() с помощью препроцессора, а затем подставить как аргумент в scanf().

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Фиксированный размер ввода в scanf" 
Сообщение от A Искать по авторуВ закладки on 13-Дек-05, 17:25  (MSK)
#define MAX_SIZE 10

char buf[ MAX_SIZE + 1 ];
buf[MAX_SIZE] = '\0';
fread(buf , MAX_SIZE , 1 , stdin);
printf("%s",buf); //все ок

аргументы fread
куда читать void *
сколько байт читать тип size_t
сколько раз читать тип size_t
откуда читать последний аргумент fread имеет тип (FILE *stream)
так что можно из файлового потока читать

т.е будет прочитано, в вашем случае, (MAX_SIZE*1) байт

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Фиксированный размер ввода в scanf" 
Сообщение от СергейК emailИскать по авторуВ закладки(??) on 13-Дек-05, 18:15  (MSK)
>#define MAX_SIZE 10
>
>scanf( "%MAX_SIZEs", buf );
>
>Как превратить "%MAX_SIZEs" в "s", чтобы scanf это съел?


#define MAX_SIZE "10"

scanf("%"MAX_SIZE"s",buf);

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 14-Дек-05, 06:57  (MSK)
>>#define MAX_SIZE 10
>>
>>scanf( "%MAX_SIZEs", buf );
>>
>>Как превратить "%MAX_SIZEs" в "s", чтобы scanf это съел?
>
>
>#define MAX_SIZE "10"
>
>scanf("%"MAX_SIZE"s",buf);

Этот вариант не компилируется.

fread в данном контексте использовать нежелательно (хотя я сейчас именно так и сделал - сам очень люблю эту функцию), так как идет фактически двойной перерасход памяти. Хотелось бы задать этот размер на этапе компиляции. Так то при помощи strcpy и strcat можно забащать любую строку.

Вопрос: а как создать строку при помощи препроцессора. Я пытался, но у меня не получилось.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Фиксированный размер ввода в scanf" 
Сообщение от СергейК emailИскать по авторуВ закладки(??) on 14-Дек-05, 07:08  (MSK)
>>#define MAX_SIZE "10"
>>
>>scanf("%"MAX_SIZE"s",buf);
>
>Этот вариант не компилируется.

Что-то Вы не так делаете...

[math@fortune tests 05:04:08]$ cat yy.c
#include <stdio.h>
main()
{
char buf[11];
#define MAX_SIZE "10"
scanf("%"MAX_SIZE"s",buf);
printf("%s",buf);
}
[math@fortune tests 05:04:13]$ gcc yy.c
[math@fortune tests 05:04:17]$ ./a.out
test
test[math@fortune tests 05:04:24]$

Все прекрасно компилится и работает... И опирается на стандартную фичу С -- склейку строковых констант.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 14-Дек-05, 08:07  (MSK)
>>>#define MAX_SIZE "10"
>>>
>>>scanf("%"MAX_SIZE"s",buf);
>>
>>Этот вариант не компилируется.
>
>Что-то Вы не так делаете...
>
>[math@fortune tests 05:04:08]$ cat yy.c
>#include <stdio.h>
>main()
>{
>char buf[11];
>#define MAX_SIZE "10"
>scanf("%"MAX_SIZE"s",buf);
>printf("%s",buf);
>}
>[math@fortune tests 05:04:13]$ gcc yy.c
>[math@fortune tests 05:04:17]$ ./a.out
>test
>test[math@fortune tests 05:04:24]$
>
>Все прекрасно компилится и работает... И опирается на стандартную фичу С --
>склейку строковых констант.

bash-3.00$ cat test.cpp
#include <stdio.h>

#define MAX_SIZE        "10"

char    buf[ MAX_SIZE + 1 ];

int     main( int argc, char* argv[] )
{
        scanf("%"MAX_SIZE"s", buf );
        printf( "%s\n", buf );
        return  0;
}

bash-3.00$ make
g++ -Wall -g -c test.cpp
test.cpp:5: error: size of array `buf' has non-integer type
make: *** [test.o] Ошибка 1

И не удивительно, так как в вашем примере 10 - это строковая константа. А строковой константой нельзя задать размер буфера - ее надо как-то в число превратить. А лучше - как-то превратить число в строковую константу. Вопрос в том - как. Должен же быть какой-то способ, как это сделать на этапе компиляции.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "Фиксированный размер ввода в scanf" 
Сообщение от СергейК emailИскать по авторуВ закладки(??) on 14-Дек-05, 08:16  (MSK)
>И не удивительно, так как в вашем примере 10 - это строковая
>константа. А строковой константой нельзя задать размер буфера - ее надо
>как-то в число превратить. А лучше - как-то превратить число в
>строковую константу. Вопрос в том - как. Должен же быть какой-то
>способ, как это сделать на этапе компиляции.

Вспомнил :)))

[math@fortune tests 06:13:50]$ cat yy.c
#include <stdio.h>
main()
{
#define MAX_SIZE 10
#define str1(s) str0(s)
#define str0(s) #s
char buf[MAX_SIZE+1];
scanf("%"str1(MAX_SIZE)"s",buf);
printf("%s",buf);
}
[math@fortune tests 06:14:05]$ gcc yy.c
[math@fortune tests 06:14:10]$ ./a.out
test
test[math@fortune tests 06:14:14]$

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 14-Дек-05, 08:36  (MSK)
>Вспомнил :)))
>
>[math@fortune tests 06:13:50]$ cat yy.c
>#include <stdio.h>
>main()
>{
>#define MAX_SIZE 10
>#define str1(s) str0(s)
>#define str0(s) #s
>char buf[MAX_SIZE+1];
>scanf("%"str1(MAX_SIZE)"s",buf);
>printf("%s",buf);
>}
>[math@fortune tests 06:14:05]$ gcc yy.c
>[math@fortune tests 06:14:10]$ ./a.out
>test
>test[math@fortune tests 06:14:14]$

Спасибо!
Действительно работает! Только я не пойму, как :) В чем фокус? Почему, когда определяешь define через другой define, то работает, а если допустим написать
#define MAX_LEN(s)      #s
...
scanf("%"MAX_LEN(MAX_SIZE)"s", buf );
то вываливается сообщение о неизвестном типе конверсии?

Заранее спасибо.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "Фиксированный размер ввода в scanf" 
Сообщение от СергейК emailИскать по авторуВ закладки(??) on 14-Дек-05, 08:53  (MSK)
>
>Спасибо!
>Действительно работает! Только я не пойму, как :) В чем фокус? Почему,

Почитайте в мануале gcc про препроцессор: http://gcc.gnu.org/onlinedocs/

А вкратце,

#define MAX_SIZE 10
#define str1(s) str0(s)
#define str0(s) #s
char buf[MAX_SIZE+1];
scanf("%"str1(MAX_SIZE)"s",buf);

есть такой оператор  у препроцессора # который  превращает аргумент в строку. Например
str0(45.24)  превратится в "45.24"
Причем в аргументах str0 макросы не подставляются! (это св-во оператора #)
Но проблема такая, что нам нужно в качестве аргумента ему дать имя другого макроса... Поэтому и определяется доплнительный макрос str1()

так что в моем примере сначала
str1(MAX_SIZE) превратится в str1(10), а потом в str0(10) потом в  "10".


  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

11. "Фиксированный размер ввода в scanf" 
Сообщение от dimus Искать по авторуВ закладки(??) on 14-Дек-05, 09:01  (MSK)
>>
>>Спасибо!
>>Действительно работает! Только я не пойму, как :) В чем фокус? Почему,
>
>Почитайте в мануале gcc про препроцессор: http://gcc.gnu.org/onlinedocs/
>
>А вкратце,
>
>#define MAX_SIZE 10
>#define str1(s) str0(s)
>#define str0(s) #s
>char buf[MAX_SIZE+1];
>scanf("%"str1(MAX_SIZE)"s",buf);
>
>есть такой оператор  у препроцессора # который  превращает аргумент в
>строку. Например
>str0(45.24)  превратится в "45.24"
>Причем в аргументах str0 макросы не подставляются! (это св-во оператора #)
>Но проблема такая, что нам нужно в качестве аргумента ему дать имя
>другого макроса... Поэтому и определяется доплнительный макрос str1()
>
>так что в моем примере сначала
>str1(MAX_SIZE) превратится в str1(10), а потом в str0(10) потом в  "10".
>


Век живи - век учись... Спасибо за объяснение и за ссылку. Я сейчас же обязательно почитаю.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

12. "Фиксированный размер ввода в scanf" 
Сообщение от SergeiZz Искать по авторуВ закладки on 14-Дек-05, 09:08  (MSK)
>Действительно работает! Только я не пойму, как :) В чем фокус? Почему,
>когда определяешь define через другой define, то работает, а если допустим
>написать
>#define MAX_LEN(s)      #s
>...
>scanf("%"MAX_LEN(MAX_SIZE)"s", buf );
>то вываливается сообщение о неизвестном типе конверсии?
Потому что MAX_LEN(MAX_SIZE) тогда будет равно "MAX_SIZE", а не "10".
Вот параграф на эту тему с тем же примером в конце:
http://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_3.html#SEC17
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру