fgets()替换 [英] fgets() replacement

查看:82
本文介绍了fgets()替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


这个小组最近有一个帖子讨论了fgets()的

缺点。我决定尝试使用fgetc()和realloc()来为fgets()写一个

替换来读取一行

任意长度。我知道这个小组中更好的程序员可以写一个更强大的功能,但不管怎么说,这是我的镜头。

我会很感激人们的评论我的fget_line()代码如下

(包括用法示例)。任何建设性的批评欢迎

逻辑,设计,风格等等。谢谢。


Paul


/ * fget_line():一个读取任意长度输入行的函数。

*

*参数:

*''in'' - 需要数据的输入流。

*''buf'' - 指向char的指针的地址。读取结果

*将在fget_line返回后包含在此缓冲区中。

* *** CALLER必须释放此指针***

*''sz'' - 调用者可以提供行长度的估计值

*读入。如果此参数为0,则fget_line()使用

*默认值。

*''validate'' - 用户提供的回调函数,用于验证每个输入字符的
*。这个参数可能是NULL,其中

*表示没有输入验证。

*

* RETURN值:

* fget_line()成功:返回读取的字节数

* realloc()相关失败:返回-1(下面#dede''dd为ERROR_MEMORY)

*非法输入:返回-2(下面#dede''d为ERROR_ILLEGAL_CHAR)

* /

#include< stdio.h>

#include< stdlib.h>

#include< string.h>

#include< ctype.h>

#include< errno.h>


#ifndef USER_DIALOG_H / *如果我不使用它作为我的

*''user_dialog''实用程序的一部分。

* /

#define LINE_LEN 80

#define DELIMITER''\ n''

#定义ERROR_MEMORY(-1)

#define ERROR_ILLEGAL_CHAR(-2)

#else

#include" user_dialog.h"

#endif

int fget_line(FILE * in,char ** buf,size_t sz,int(* validate)(int))

{

int n_bytes = 0; / *读取的总字节数或错误标志* /

size_t n_alloc = 0; / *分配的字节数* /


unsigned int mult = 1;


char * tmp,* local_buffer = NULL;

int read_in;

* buf = NULL;


if(0 == sz)sz = LINE_LEN;

read_in = fgetc(in))!= DELIMITER&& read_in!= EOF){

if(0 == n_alloc){

n_alloc = sz * mult + n_bytes + 1;

tmp = realloc(local_buffer,n_alloc);

if(NULL!= tmp){

local_buffer = tmp;

mult ++;

}

else {

local_buffer [n_bytes] = ''\''';

* buf = local_buffer;

返回ERROR_MEMORY;

}


}

if(NULL!= validate){

if(0!= validate(read_in)){

local_buffer [n_bytes ++ ] = read_in;

n_alloc--;

}

else {

local_buffer [n_bytes] ='' \0'';

* buf = local_buffer;

返回ERROR_ILL EGAL_CHAR;

}

}


}


local_buffer [n_bytes] = ''\ 0'';


/ *修剪多余的内存(如果有的话)* /

if(n_alloc> (size_t)n_bytes){

tmp = realloc(local_buffer,n_bytes);

if(NULL!= tmp){

local_buffer = tmp ;

}

}


local_buffer [n_bytes] =''\''';

* buf = local_buffer;

返回n_bytes;

}


/ *用法示例* /

int main(无效)

{

char * line = NULL;

int ret_value;

size_t len;


fputs("输入一个字符串:",stdout);

fflush(stdout);


ret_value = fget_line(stdin,& line,0,isalnum);

len = strlen(line);


fprintf(stdout, " fget_line()返回%d \ nstrlen()返回%d bytes \ n",

ret_value,len);

fprintf(stdout," String是:\"%s \" \ n",line);

free(line);

退出(EXIT_SUCCESS);

}


-

保罗D. Boyle
bo***@laue.chem.ncsu.edu

北卡罗来纳州立大学
http://www.xray.ncsu.edu

解决方案



" Paul D. Boyle" <博*** @ laue.chem.ncsu.edu>写了

大家好,

这个小组最近有一个帖子谈到了fgets()的缺点。我决定尝试使用fgetc()和realloc()来写一个替换fgets()来替换
任意长度的行。



为什么不看一下CB Falconer's" ggets()"


< http://cbfalconer.home.att.net>

或发送电子邮件至


Chuck F(cb********@yahoo.com)


你觉得你的做事方式更好吗?


Malcolm< ma ***** @ 55bank.freeserve.co.uk>写道:


:" Paul D. Boyle" <博*** @ laue.chem.ncsu.edu>写了

:>大家好,

:>

:>这个小组最近有一个帖子谈到了

:> fgets()的缺点。我决定尝试写一个

:>使用fgetc()和realloc()替换fgets()来读取一行

:>任意长度。

:>

:为什么不看一下CB Falconer's" ggets()"?


我做了,但我想尝试使用

fgetc()和realloc()来做它(主要是为了它)。


:你觉得你的做事方式更好吗?


我不认为这是更好的事情。我写了一个函数来完成

我认为会成为一个安全有用的函数的东西,我想要其他人对我所做的事情的看法。特别是在fget_line()中,

我提供了一种进行输入验证的方法。这是一个好的和有用的

设计决定吗?


Paul


-

Paul D. Boyle
bo***@laue.chem.ncsu.edu
北卡罗来纳州立大学
http://www.xray.ncsu .edu


Paul D. Boyle< bo *** @ laue.chem.ncsu.edu>写道:

:if(NULL!= validate){

:if(0!= validate(read_in)){

:local_buffer [ n_bytes ++] = read_in;

:n_alloc--;

:}

:else {

:local_buffer [ n_bytes] =''\''';

:* buf = local_buffer;

:返回ERROR_ILLEGAL_CHAR;

:}

:}



:}


:local_buffer [n_bytes] =''\'0' ';


当然,我必须在*发布到

comp.lang.c之后发现一点(?)*。 (哎呀)。我错过了一个''else''块来覆盖案例

其中''validate''函数指针为NULL。上面的代码应该是:


if(NULL!= validate){

if(0!= validate(read_in)){

local_buffer [n_bytes ++] = read_in;

n_alloc--;

}

else {

local_buffer [n_bytes] =''\''';

* buf = local_buffer;

返回ERROR_ILLEGAL_CHAR;

}

}

else {

local_buffer [n_bytes ++] = read_in;

n_alloc--;

}


}


local_buffer [n_bytes] =''\ 0'';


/ *等...... * /


保罗

-

Paul D. Boyle
< a href =mailto:bo *** @ laue.chem.ncsu.edu> bo *** @ laue.chem.ncsu.edu

北卡罗来纳州立大学/> http://www.xray.ncsu.edu

Hi all,

There was a recent thread in this group which talked about the
shortcomings of fgets(). I decided to try my hand at writing a
replacement for fgets() using fgetc() and realloc() to read a line of
arbitrary length. I know that the better programmers in this group could
write a more robust function, but here is my shot at it anyway.
I would appreciate people''s comments on my fget_line() code below
(usage example included). Any constructive criticism welcome regarding
logic, design, style, etc. Thanks.

Paul

/* fget_line(): a function to read a line of input of arbitrary length.
*
* Arguments:
* ''in'' -- the input stream from which data is wanted.
* ''buf'' -- the address of a pointer to char. The read in results
* will be contained in this buffer after the fget_line returns.
* *** THE CALLER MUST FREE THIS POINTER ***
* ''sz'' -- the caller can supply an estimate of the length of line to be
* read in. If this argument is 0, then fget_line() uses a
* default.
* ''validate'' -- a user supplied callback function which is used to validate
* each input character. This argument may be NULL in which
* case no input validation is done.
*
* RETURN values:
* fget_line() on success: returns the number of bytes read
* realloc() related failure: returns -1 (#define''d below as ERROR_MEMORY)
* illegal input: returns -2 (#define''d below as ERROR_ILLEGAL_CHAR)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#ifndef USER_DIALOG_H /* if I am not using this as part of my
* ''user_dialog'' utilities.
*/
#define LINE_LEN 80
#define DELIMITER ''\n''
#define ERROR_MEMORY (-1)
#define ERROR_ILLEGAL_CHAR (-2)
#else
#include "user_dialog.h"
#endif

int fget_line( FILE *in, char **buf, size_t sz, int (*validate)(int) )
{
int n_bytes = 0; /* total number of bytes read or error flag */
size_t n_alloc = 0; /* number of bytes allocated */

unsigned int mult = 1;

char *tmp, *local_buffer = NULL;
int read_in;
*buf = NULL;

if( 0 == sz ) sz = LINE_LEN;

while( (read_in = fgetc( in )) != DELIMITER && read_in != EOF ) {
if( 0 == n_alloc ) {
n_alloc = sz * mult + n_bytes + 1;
tmp = realloc( local_buffer, n_alloc );
if ( NULL != tmp ) {
local_buffer = tmp;
mult++;
}
else {
local_buffer[n_bytes] = ''\0'';
*buf = local_buffer;
return ERROR_MEMORY;
}

}
if( NULL != validate ) {
if( 0 != validate( read_in ) ) {
local_buffer[n_bytes++] = read_in;
n_alloc--;
}
else {
local_buffer[n_bytes] = ''\0'';
*buf = local_buffer;
return ERROR_ILLEGAL_CHAR;
}
}

}

local_buffer[n_bytes] = ''\0'';

/* trim excess memory if any */
if( n_alloc > (size_t)n_bytes ) {
tmp = realloc( local_buffer, n_bytes );
if( NULL != tmp ) {
local_buffer = tmp;
}
}

local_buffer[n_bytes] = ''\0'';
*buf = local_buffer;
return n_bytes;
}

/* usage example */
int main( void )
{
char *line = NULL;
int ret_value;
size_t len;

fputs( "Enter a string: ", stdout );
fflush( stdout );

ret_value = fget_line( stdin, &line, 0, isalnum );
len = strlen( line );

fprintf( stdout, "fget_line() returned %d\nstrlen() returns %d bytes\n",
ret_value, len );
fprintf( stdout, "String is: \"%s\"\n", line );
free( line );
exit( EXIT_SUCCESS );
}


--
Paul D. Boyle
bo***@laue.chem.ncsu.edu
North Carolina State University
http://www.xray.ncsu.edu

解决方案


"Paul D. Boyle" <bo***@laue.chem.ncsu.edu> wrote

Hi all,

There was a recent thread in this group which talked about the
shortcomings of fgets(). I decided to try my hand at writing a
replacement for fgets() using fgetc() and realloc() to read a line of
arbitrary length.


Why not look a CB Falconer''s "ggets()"?

<http://cbfalconer.home.att.net>

or email him on

Chuck F (cb********@yahoo.com)

Do you think your way of doing things is better?


Malcolm <ma*****@55bank.freeserve.co.uk> wrote:

: "Paul D. Boyle" <bo***@laue.chem.ncsu.edu> wrote
:> Hi all,
:>
:> There was a recent thread in this group which talked about the
:> shortcomings of fgets(). I decided to try my hand at writing a
:> replacement for fgets() using fgetc() and realloc() to read a line of
:> arbitrary length.
:>
: Why not look a CB Falconer''s "ggets()"?

I did, but I wanted to try doing it (mostly for the heck of it) using
fgetc() and realloc().

: Do you think your way of doing things is better?

I don''t see it as a matter of better. I wrote a function which did the
things I thought would make a safe and useful function, and I wanted
other people''s opinion of what I had done. In particular, in fget_line(),
I provided a way to do some input validation. Was that a good and useful
design decision?

Paul

--
Paul D. Boyle
bo***@laue.chem.ncsu.edu
North Carolina State University
http://www.xray.ncsu.edu


Paul D. Boyle <bo***@laue.chem.ncsu.edu> wrote:
: if( NULL != validate ) {
: if( 0 != validate( read_in ) ) {
: local_buffer[n_bytes++] = read_in;
: n_alloc--;
: }
: else {
: local_buffer[n_bytes] = ''\0'';
: *buf = local_buffer;
: return ERROR_ILLEGAL_CHAR;
: }
: }
:
: }

: local_buffer[n_bytes] = ''\0'';

Naturally, I have to discover a little(?) *after* I post to
comp.lang.c. (grrr). I am missing an ''else'' block to cover the case
where the ''validate'' function pointer is NULL. The above code should be:

if( NULL != validate ) {
if( 0 != validate( read_in ) ) {
local_buffer[n_bytes++] = read_in;
n_alloc--;
}
else {
local_buffer[n_bytes] = ''\0'';
*buf = local_buffer;
return ERROR_ILLEGAL_CHAR;
}
}
else {
local_buffer[n_bytes++] = read_in;
n_alloc--;
}

}

local_buffer[n_bytes] = ''\0'';

/* and so on ... */

Paul
--
Paul D. Boyle
bo***@laue.chem.ncsu.edu
North Carolina State University
http://www.xray.ncsu.edu


这篇关于fgets()替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆