LINUX.ORG.RU

C и попытки вернуть из функции указатель на массив символов


0

0
#include <stdio.h>
#define BUFSIZE 10000

int main ( int argc, char *argv[] )
{
    char *str;
    FILE *stream = fopen( *++argv, "r" );
    getvar( stream, str );
    while ( *str )
        putchar( *str++ );
    return 0;
}

int getvar( FILE *istream, char *pvar )
{
    static int a;
    static int b = '\n';
    static char *parr, arr[BUFSIZE];
    pvar = parr = arr;

    while (( *parr = fgetc(istream) ) != EOF )
    {
        if ( b == '\n' && a == '=' )           
            b = *parr;
        if ( *parr == '\n' && a == b )
            break;
        a = *parr; 
        parr++; 
    }
    return 0;
}

Почему конструкция while ( *str ) putchar( *str++ ) выводит чёрт знает что, а конструкция while ( *pvar ) putchar( *pvar++ ) помещённая в getvar выводит то что прочитано из файла?

★★★★★

А потому что передача по значению. Ты передаешь _значение указателя_,
а не переменную.

Svoloch ★★★
()

OMFG!

1. Время жизни переменных. Массив arr функции getvar создается в стеке при вызове функции и уничтожается при выходе из нее.

2. pvar у тебя только передает значение в функцию - на внешний мир pvar не влияет - это копия указателя которая принимает значение str, но не меняет его. Или возвращай указатель вместо '0', или же в C используй указатель на переменные в аргументах вместо передачи их значений.

Резюме: учи указатели и время жизни переменных.

Spectr ★★★
()

#include <stdio.h>
#define BUFSIZE 10000

int main ( int argc, char *argv[] )
{
char *str;
FILE *stream = fopen( *++argv, "r" );
getvar( stream, &str );
while ( *str )
putchar( *str++ );
return 0;
}

int getvar( FILE *istream, char **pvar )
{
static int a;
static int b = '\n';
static char *parr, arr[BUFSIZE];
*pvar = parr = arr;

while (( *parr = fgetc(istream) ) != EOF )
{
if ( b == '\n' && a == '=' )
b = *parr;
if ( *parr == '\n' && a == b )
break;
a = *parr;
parr++;
}
return 0;
}

Так должно работать. Проверить сейчас негде.

Svoloch ★★★
()
Ответ на: комментарий от Spectr

> Резюме: учи указатели и время жизни переменных.

Резюме: учи вызовы функций и время жизни переменных.

fixed.

Spectr ★★★
()
Ответ на: комментарий от Spectr

while (( *parr = fgetc(istream) ) != EOF )
при фиксированном размере BUFSIZE...
Тут много чего еще учить надо...
Может проще учить сразу Си...

Svoloch ★★★
()
Ответ на: комментарий от Svoloch

да, я ошибся - с разу не заметил static (т.е. с указателем на указатель должно работать).

Просто сбил с толку подход - static в функциях так не используют - весьма странный подход к менеджменту памяти.

Spectr ★★★
()
Ответ на: комментарий от Spectr

>Резюме: учи указатели и время жизни переменных.

Под рукой только K&R. Может быть в силу невнимательности, но я не нашёл там ничего про время жизни переменных. Что ещё можно посмотреть на эту тему?

KblCb ★★★★★
() автор топика
Ответ на: комментарий от Spectr

>Просто сбил с толку подход - static в функциях так не используют - весьма странный подход к менеджменту памяти.

Почему static в функциях так не используют? И где можно посмотреть о том как используют?

KblCb ★★★★★
() автор топика
Ответ на: комментарий от Elverion

>Переменная живет в пределах блока {}

А статики живут вечно

Elverion
()
Ответ на: комментарий от Elverion

>Переменная живет в пределах блока {}

Все? Без какого-либо разделения на локальные и глобальные?

KblCb ★★★★★
() автор топика
Ответ на: комментарий от Elverion

Статичная? Глобальная? Локальная?
Воистину порой лучше соврать, чем умолчать...

Svoloch ★★★
()
Ответ на: комментарий от KblCb

Лучше поискать подробную книгу по Си.
Только я вряд ли смогу посоветовать какую.

Svoloch ★★★
()
Ответ на: комментарий от Svoloch

>1. Время жизни переменных. Массив arr функции getvar создается в стеке при вызове функции и уничтожается при выходе из нее.

Бред. Парень правильно объявил статичный массив. Так что никуда он не исчезнет.

Да, он передал в функцию значение указателя, а надо было передать адрес указателя так, как написал Svoloch. А в остальном не понимаю вашей озабочености и воплей, что его надо учить. Поднимите руки те, кто на первых шагах работы с указателями не делал такой же ошибки? Вот и парень наступил на эти грабли. В следующий раз будет знать ;-)

velik_S
()
Ответ на: комментарий от Spectr

> 1. Время жизни переменных. Массив arr функции getvar создается в стеке при вызове функции и уничтожается при выходе из нее.

tons of facepalm.

zh
()
Ответ на: комментарий от velik_S

Да просто судя по коду, парень учится.
И судя по тому же коду, учится не совсем по тому, по чему стоило бы.

Svoloch ★★★
()
Ответ на: комментарий от Svoloch

>while (( *parr = fgetc(istream) ) != EOF ) >при фиксированном размере BUFSIZE... >Тут много чего еще учить надо... >Может проще учить сразу Си...

Ой, да ладно! Ну добавил бы он в while : && (parr - arr) / sizeof(char) < BUFSIZE

и как бы это повлияло на проблему? ;) А читабельности коду для этого форума бы точно не прибавило :)

velik_S
()

топик доставляет :)

lester ★★★★
()
Ответ на: комментарий от velik_S

Ну ладно, может я и не прав.
Просто у меня обострение аллергии на magic numbers вообще
и на не используемые в частности.

Svoloch ★★★
()
Ответ на: комментарий от Svoloch

Да нет, по сути ты, как мне, кажется таки прав. Просто, когда у меня возникали вопросы и проблемы, я и сам бросал куски кода, которые в обрезанном варианте выглядели через (извините) Ж%пу. Главное, что вы коллегу пихнули в правильном направлении - передача значения и адреса в функцию - в этом месте у него была в голове каша (или пробел) ;-)

velik_S
()

#include <stdio.h>
#define BUFSIZE 1000

int main ( int argc, char *argv[] ) {
char buf[BUFSIZE+1], *tmp;
if( argc <= 1 )
return 1;
FILE * stream = fopen( argv[1], "r" );
if( stream == NULL )
return 1;
tmp = buf;
getvar( stream, &tmp );
printf("%s", buf);
return 0;
}

int getvar( FILE *stream, char **pstr ) {
static int a = '\0', b = '\n';
int t;
char *ptmp = *pstr;
while( (t = fgetc(stream)) != EOF && (ptmp - *pstr) < BUFSIZE ) {
/* copy */
*ptmp = t;
ptmp++;
}
*ptmp = '\0';
return 0;
}

-----------------------------

как-то так. только while можно лучше сделать, ну и добавить туда что нужно.

P.S. есть вопрос. почему gcc ничего не пишет в данном коде на конструкцию
getvar( stream, &buf ), но это приводит к сегфолту?

aninamous
()
Ответ на: комментарий от aninamous

Может быть он на fopen сегфолтится? Ты же ему вместо имени файла подсовываешь указатель на массив первого аргумента.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от aninamous

ибо buf ниразу не указатель (сегфол). а пот почему не пишет. может какие опции не указаны при копиляции ? ..

getvar( stream, & (char *) buf );

если я все правильно помню )

adminus
()
Ответ на: комментарий от Svoloch

int getvar( FILE *stream, char *buf, int buf_len ) {

- вроде такого - передавать размер буфера вместе с указателем на негою

Spectr ★★★
()
Ответ на: комментарий от Svoloch

>Что-то я не понял зачем вообще &buf городить? Сам buf передать не проще?

ну да с С строками так и нужно. но так и проблемы нет.

aninamous
()
Ответ на: комментарий от adminus

>а пот почему не пишет. может какие опции не указаны при копиляции ?

не, с объявлением функции пишет.

>если я все правильно помню

да я и сам не помню, как там указатели на массивы и многомерные массивы передаются в функции.

>getvar( stream, & (char *) buf );

не работает. но через присваивание указателю всё работает( как в том что я привёл). но всё равно как-то странно получается с типами получается.

aninamous
()

ГЛАВНОЕ, что не ясно -- что эта программа должна делать, т.к. распечатать кучу файлов можно поточно, т.е. не выделяя arr[BUFSIZE] и не огребая там ошибки.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>ГЛАВНОЕ, что не ясно -- что эта программа должна делать, т.к. распечатать кучу файлов можно поточно, т.е. не выделяя arr[BUFSIZE] и не огребая там ошибки.

А эта программа не делает ничего. Она нужна только для того чтобы убедиться в том что getvar умеет вытаскивать из потока var и возвращать указатель на массив с этим var'ом.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

>тогда более логично было бы char* getvar(FILE* stream)

Так то оно так, но проблемы у меня возникли до того как я решил придать функции законченный вид. Сейчас уже так и переписал. Вот только как лучше char* getvar или char *getvar?

KblCb ★★★★★
() автор топика
Ответ на: комментарий от ttnl

>>Вот только как лучше char* getvar или char *getvar?

>Абсолютно пофигу

C технической точки зрения таки да - пофигу. Только лучше сначала заставить себя называть переменные так, чтоб потом легче было читать код - это избавит вас от путаницы в программировании больших кусков и облегчит читабельность кода всем, кто после вас с ним будет работать.

char* getvar

Я б определил как

char* pcGetvar

Конечно, фигня, но потом оч помогает ;-)

velik_S
()
Ответ на: комментарий от velik_S

> char* pcGetvar

фу! ужасно.
тогда уж pc_getvar или pc_get_var.

хотя я бы оставил getvar или get_var.


да даже если с этими вендузяцими преподвыподвертами (не про pc, а про регистр) - pcGetVar.

zh
()
Ответ на: комментарий от velik_S

Любители венгерской (или чья она там) нотации должны сдохнуть в муках. Идите к себе в венду и не мусорьте в приличных местах.

kemm
()
Ответ на: комментарий от Dudraug

>Так точно не должно работать.

Почему? Вопрос далеко не праздный потому что всё работает.

KblCb ★★★★★
() автор топика
Ответ на: комментарий от KblCb

Я ошибся, все правильно. Просто запись очень не привычная. Мои извинения.

Dudraug ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.