ENGLISH 意见建议 网站地图 网站帮助
广泛智力汇聚   高效成果传播   先进机制培育
联盟首页  |  协同开发  |  开放源码库  |  安全告警  |  开源导航  |  文档中心  |  服务支持  |  共创论坛  |  关于联盟


注册会员 网站帮助
    您的位置 »
    今天是: 2010年11月22日    
项目搜索

完全匹配   
开源软件
软件分类表
新发布软件
其它网站镜像
代码片断
协同开发
文档
论坛
寻求协助
热点项目
站点状态
编译工厂

联系我们
关于联盟

代码片段库:
查看代码片段

浏览 | 提交新的代码片段 | 创建代码包

多字节函数库系列:文件读取:cy_mbsfgets()

类型:
Function
类别:
Other
许可证:
GNU Library Public License
语言:
C++
 
描述:
按字符数读取文本文件中的一行,功能类似于标准函数:fgets()

(*前文说明*:ID:4564之“多字节函数库系列:文件读取”一页应为:“多字节函数库系列:文件读取:cy_mbfgetc()”,为单字符读取函数,功能类似于标准函数:fgetc()。)

该代码片段的版本系列:

片段ID 下载版本 提交时间 提交人 删除
45680.12002-06-26 20:42renxiao

点击"下载版本"来下载该代码片段.


最新版本的代码片段: 0.1


/*-----------------------Own_lib函数库系列 mbsfgets.cc-------------------------
cy_mbsfgets() /mbsfgets.o /libcyfunc.a

描述: 当处理多字节文本文件(如中文)时, 标准fgets()函数只能按字节读入, 这样很容易
      读入半个字符而使读入的字符串不完整, 为此, 程序中需增加一些额外的处理代码,
      但这样又让代码看起来不够简洁.
      本函数试图封装这一过程, 使对东亚文本的读取操作直接一些, 代码也简洁一些. 函
      数使用了"mbstowcs()/wcstombs()"标准库函数, 所以在您的程序开头应setlocale().
      与"fgets()"标准库函数类似, 文件中行尾的换行符被与其它字符同样对待的读入.
      同样, 字符串的末尾附上了'\0'(空字符)结束符.
      用户调用函数时: 传递有足够大(MB_CUR_MAX * max_chars +1)内存空间的目的字符
      串地址(指针) |  最多字符(非字节)数 | 文件流指针 | 和"LC_CTYPE"区域设置字符
      串(如: "zh_CN.GBK", 默认值为NULL, 表示不改变系统设置. 另当传递了一个无效的
      区域设置时, 函数不改变当前的该设置, 但该"设置"已为真!).
      下一个函数为重载函数, 增加了返回实际读取字串字节数的引用变量和返回实际读取
      字串字符数的引用变量.
dest_str:
      保存读入字符串的内存空间的指针/或NULL值.
max_chars:
      需要从文件流stream中读入的最多字符个数.
stream:
      FILE结构的文件流指针.
[length]:
      返回实际读取字符串的字节数.
[chars]:
      返回实际读取字符串的字符数.
locale_ctype = NULL:
      读入字串所属的LC_CTYPE区域(语系/编码). 一般程序开头已经设定, 故此可不管它.
返回值:
      返回指向dest_str内存空间的字符串指针(末尾已加'\0'). 若有错误返回NULL.

注意! 1. 函数从stream读入字符串直到出现换行或到文件尾或已读了max_chars个字符为止.
      2. 当传递LC_CTYPE区域设置时, 参数dest_str应为NULL, 函数返回指向自由存储区
         的字符串指针(用完后应delete[]掉, 并赋值为NULL), 若参数dest_str不为NULL,
         函数移动文件流指针一行/或指定字符数(不足一行时), 返回NULL.
         当不传递LC_CTYPE设置, 并且设定参数dest_str为NULL时, 其行为与LC_CTYPE为真
         && dest_str为真(可传递空字符串"")时一样(只有文件流指针移动 && 返回NULL).
      3. 传入区域字符串后函数将临时改变系统"LC_CTYPE"的设置. 在退出时会恢复其原
         来的设置.

作者: 任逍 |2002.05.08.
版权: GNU General (Library) Public License (GPL/LGPL)

* 编辑器: vim-6.0 |操作系统: TurboLinux7.0简体中文版 *
------------------------------------------------------------------------------*/

#include <stdio.h>		// usr for fgets()
#include <stdlib.h>		// usr for MB_CUR_MAX --当前多字节环境下每字最大字节长.
						// usr for mbs* and others.
#include <locale.h> 	// usr for setlocale().--函数提供改变环境"LC_CTYPE"的机会

#include "cyinclude/cyfget.h"


char *  cy_mbsfgets(char * dest_str, int max_chars, FILE * stream,
                    const char * locale_ctype = NULL)
{
	long fpos_before;
	if ( (fpos_before = ftell(stream)) == -1 )	// 获取读取前的文件流指针位置
		return NULL;

	int 	num = max_chars * MB_CUR_MAX;
	bool	locale_check = false;
	char*	locale_original = setlocale(LC_CTYPE, NULL);	// LC_CTYPE原来的值
	if (locale_ctype)
	{
		if (! dest_str)
		{
			setlocale(LC_CTYPE, locale_ctype);
			num = max_chars * MB_CUR_MAX;
			locale_check = true;
		}
		else
			dest_str = NULL;
	}

	size_t 	test_length = 0;	// 用于测试输入字符数是否超过需求
	char*	tmp_chars = new char[num + 1];	// 字串所需最大可能空间, 临时存放用
	wchar_t*	tmp_wchars = new wchar_t[max_chars + 1];

	if ( (! tmp_chars) || (! tmp_wchars) )
	{	// 其中可能已经有一个申请成功!
		if (locale_check)
			setlocale(LC_CTYPE, locale_original);
		delete[] tmp_chars;
		tmp_chars = NULL;
		delete[] tmp_wchars;
		tmp_wchars = NULL;
		return NULL;
	}

	if (! fgets(tmp_chars, num + 1, stream))	// 接收最大限定数量的输入字符串
	{
		if (locale_check)
			setlocale(LC_CTYPE, locale_original);
		delete[] tmp_chars;
		tmp_chars = NULL;
		delete[] tmp_wchars;
		tmp_wchars = NULL;
		return NULL;
	}

	test_length = mbstowcs(tmp_wchars, tmp_chars, max_chars + 1);
	if ( (test_length == (size_t)-1) || (test_length == max_chars + 1) )
		tmp_wchars[max_chars] = L'\0';	// 多出来的字符或非法字节被截断或覆盖

	size_t	chars_length;	// 实际读取字串字节长(用于设置文件流指针偏移量)
	char *	return_chars = NULL;
	if (locale_check)
	{
		chars_length = wcstombs(NULL, tmp_wchars, num + 1);
		return_chars = new char[chars_length + 1];
		if (! return_chars)
		{
			setlocale(LC_CTYPE, locale_original);
			delete[] tmp_chars;
			tmp_chars = NULL;
			delete[] tmp_wchars;
			tmp_wchars = NULL;
			return NULL;
		}
		wcstombs(return_chars, tmp_wchars, chars_length + 1);
 	}
	else
		chars_length = wcstombs(dest_str, tmp_wchars, num + 1);
	
	if (locale_check)
		setlocale(LC_CTYPE, locale_original);

	delete[] tmp_chars;
	tmp_chars = NULL;
	delete[] tmp_wchars;
	tmp_wchars = NULL;
	
	if (fseek(stream, fpos_before + chars_length, SEEK_SET))
		return NULL;	// 重置文件流指针, 当有错误时, 返回NULL

	if (locale_check)
		return return_chars;
	else
		return dest_str;
}
//-----------------------------------------------------------------------------


// 上一函数的重载函数. 

char *  cy_mbsfgets(char * dest_str, int max_chars, FILE * stream,
                    int & length, int & chars, const char * locale_ctype = NULL)
{
	long fpos_before;
	if ( (fpos_before = ftell(stream)) == -1 )	// 获取读取前的文件流指针位置
		return NULL;

	int 	num = max_chars * MB_CUR_MAX;
	bool	locale_check = false;
	char*	locale_original = setlocale(LC_CTYPE, NULL);	// LC_CTYPE原来的值
	if (locale_ctype)
	{
		if (! dest_str)
		{
			setlocale(LC_CTYPE, locale_ctype);
			num = max_chars * MB_CUR_MAX;
			locale_check = true;
		}
		else
			dest_str = NULL;
	}

	size_t 	test_length = 0;	// 用于测试输入字符数是否超过需求
	char*	tmp_chars = new char[num + 1];	// 字串所需最大可能空间, 临时存放用
	wchar_t*	tmp_wchars = new wchar_t[max_chars + 1];

	if ( (! tmp_chars) || (! tmp_wchars) )
	{	// 其中可能已经有一个申请成功!
		if (locale_check)
			setlocale(LC_CTYPE, locale_original);
		delete[] tmp_chars;
		tmp_chars = NULL;
		delete[] tmp_wchars;
		tmp_wchars = NULL;
		return NULL;
	}

	if (! fgets(tmp_chars, num + 1, stream))	// 接收最大限定数量的输入字符串
	{
		if (locale_check)
			setlocale(LC_CTYPE, locale_original);
		delete[] tmp_chars;
		tmp_chars = NULL;
		delete[] tmp_wchars;
		tmp_wchars = NULL;
		return NULL;
	}

	test_length = mbstowcs(tmp_wchars, tmp_chars, max_chars + 1);
	if ( (test_length == (size_t)-1) || (test_length == max_chars + 1) )
	{
		tmp_wchars[max_chars] = L'\0';	// 多出来的字符或非法字节被截断或覆盖
		chars = max_chars;	//!.引用传递返回实际字串字符数
	}
	else
		chars = test_length;	//!.引用传递返回实际字串字符数

	size_t	chars_length;	// 实际读取字串字节长, 用于设置文件流指针偏移量和返回值
	char *	return_chars = NULL;
	if (locale_check)
	{
		chars_length = wcstombs(NULL, tmp_wchars, num + 1);
		return_chars = new char[chars_length + 1];
		if (! return_chars)
		{
			setlocale(LC_CTYPE, locale_original);
			delete[] tmp_chars;
			tmp_chars = NULL;
			delete[] tmp_wchars;
			tmp_wchars = NULL;
			return NULL;
		}
		wcstombs(return_chars, tmp_wchars, chars_length + 1);
		length = chars_length;	//!.引用传递返回实际字串字节数
 	}
	else
	{
		chars_length = wcstombs(dest_str, tmp_wchars, num + 1);
		length = chars_length;	//!.引用传递返回实际字串字节数
	}
	
	if (locale_check)
		setlocale(LC_CTYPE, locale_original);

	delete[] tmp_chars;
	tmp_chars = NULL;
	delete[] tmp_wchars;
	tmp_wchars = NULL;
	
	if (fseek(stream, fpos_before + chars_length, SEEK_SET))
		return NULL;	// 重置文件流指针, 当有错误时, 返回-1
	
	if (locale_check)
		return return_chars;
	else
		return dest_str;
}

		

提交新版本

如果您修改了一个代码片段并且觉得很应该让别人共享,您可以把这作为这个代码片段的最新版本提交上来.


联盟团体会员
合作伙伴
© 共创软件联盟 版权所有
联盟服务条款 | 联盟隐私权规则 | 联系我们
电话: (8610)68313388-5949 | 传真: (8610)88377936
京ICP备05056057号