| 项目搜索 |
| |
|
代码片段库:
查看代码片段
浏览
| 提交新的代码片段
| 创建代码包
多字节函数库系列:文件读取:cy_mbsrfgets()
|
类型:
Function |
类别:
Other
|
许可证:
GNU Library Public License |
语言:
C++
|
描述:
按字符数读取文本文件中的一行,但支持有“状态改变”的编码系统(如日文的“SJIS/Shift JIS”编码)。功能类似于标准函数:fgets()
|
该代码片段的版本系列:
片段ID |
下载版本 |
提交时间 |
提交人 |
删除 |
4567 | 0.1 | 2002-06-26 20:28 | renxiao | |
点击"下载版本"来下载该代码片段.
最新版本的代码片段: 0.1
/*-----------------------Own_lib函数库系列 mbsrfgets.cc-------------------------
cy_mbsrfgets() /mbsrfgets.o /libcyfunc.a
描述: 当处理多字节文本文件(如中文)时, 标准fgets()函数只能按字节读入, 这样很容易
读入半个字符而使读入的字符串不完整, 为此, 程序中需增加一些额外的处理代码,
但这样又让代码看起来不够简洁.
本函数试图封装这一过程, 使对东亚文本的读取操作直接一些, 代码也简洁一些. 函
数使用了"mbsrtowcs()/wcsrtombs()"标准库函数(在您的程序开头应setlocale()),
因此, 它能处理有"状态改变"的编码系统(如日文的"SJIS/Shift JIS"编码).
与cy_mbsfgets()函数相比, 参数表中增加了一个"mbstate_t"的设置开关, 默认值为
false(假, 即不再设置函数内部的"mbstate_t"静态变量), 但当第一次读入某种语言
编码的文本文件时, 请置其为true!
与"fgets()"标准库函数类似, 文件中行尾的换行符被与其它字符同样对待的读入.
同样, 字符串的末尾附上了'\0'(空字符)结束符.
用户调用函数时: 传递有足够大(MB_CUR_MAX * max_chars +1)内存空间的目的字符
串地址(指针) | 最多字符(非字节)数 | 文件流指针 | "mbstate_t"设置开关 | 和
"LC_CTYPE"区域设置字符串(如: "zh_CN.GBK", 默认值为NULL, 表示不改变系统设置.
另当传递了一个无效的区域设置时, 函数不改变当前的该设置, 但该"设置"已为真!).
下一个函数为重载函数, 增加了返回实际读取字串字节数的引用变量和返回实际读取
字串字符数的引用变量.
dest_str:
保存读入字符串的内存空间的指针/或NULL值.
max_chars:
需要从文件流stream中读入的最多字符个数.
stream:
FILE结构的文件流指针.
[length]:
返回实际读取字符串的字节数.
[chars]:
返回实际读取字符串的字符数.
state_is = false:
一个处理有"状态改变"的编码文本的开关. 只需初次读取文本时置其为true(真).
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"的设置. 在退出时会恢复其原来
的设置.
4. 函数内部处理采用"mbsrtowcs()/wcsrtombs()", 故其应当也适用于无状态改变的
编码系统(如中文).
作者: 任逍 |2002.05.11.
版权: 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 <string.h> // usr for memset()
#include <wchar.h> // usr for mbsrtowcs()|wcsrtombs() |mbrtowc()|wcrtomb()
#include "cyinclude/cyfget.h"
char * cy_mbsrfgets(char * dest_str, int max_chars, FILE * stream,
bool state_is = false, 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;
}
static mbstate_t state_towcs; // 设置记录字符串编码"状态"的静态变量
static mbstate_t state_tombs; // 设置记录字符串编码"状态"的静态变量
if (state_is)
memset(&state_towcs, '\0', sizeof(mbstate_t));
memset(&state_tombs, '\0', sizeof(mbstate_t));
char * del_chars = tmp_chars; //! 保存堆中字符串地址, 用于删除.
test_length = mbsrtowcs(tmp_wchars, (const char**)&tmp_chars, max_chars, &state_towcs);
if ( (test_length == (size_t)-1) || (test_length == max_chars) )
tmp_wchars[max_chars] = L'\0';
wchar_t * del_wchars = tmp_wchars; //! 保存堆中字符串地址, 用于删除.
size_t chars_length; // 实际读取字串字节长(并用于设置文件流指针偏移量)
char * return_chars = NULL;
if (locale_check)
{
chars_length = wcsrtombs(NULL, (const wchar_t**)&tmp_wchars, num + 1, &state_tombs);
return_chars = new char[chars_length + 1];
if (! return_chars)
{
setlocale(LC_CTYPE, locale_original);
delete[] del_chars;
del_chars = NULL;
delete[] del_wchars;
del_wchars = NULL;
return NULL;
}
wcsrtombs(return_chars, (const wchar_t**)&tmp_wchars, chars_length + 1, &state_tombs);
}
else
chars_length = wcsrtombs(dest_str, (const wchar_t**)&tmp_wchars, num + 1, &state_tombs);
if (locale_check)
setlocale(LC_CTYPE, locale_original);
delete[] del_chars;
del_chars = NULL;
delete[] del_wchars;
del_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_mbsrfgets(char * dest_str, int max_chars, FILE * stream, int & length, int & chars,
bool state_is = false, 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;
}
static mbstate_t state_towcs; // 设置记录字符串编码"状态"的静态变量
static mbstate_t state_tombs; // 设置记录字符串编码"状态"的静态变量
if (state_is)
memset(&state_towcs, '\0', sizeof(mbstate_t));
memset(&state_tombs, '\0', sizeof(mbstate_t));
char * del_chars = tmp_chars; //! 保存堆中字符串地址, 用于删除.
test_length = mbsrtowcs(tmp_wchars, (const char**)&tmp_chars, max_chars, &state_towcs);
if ( (test_length == (size_t)-1) || (test_length == max_chars) )
{
tmp_wchars[max_chars] = L'\0';
chars = max_chars; //!.引用传递返回实际字串字符数
}
else
chars = test_length; //!.引用传递返回实际字串字符数
wchar_t * del_wchars = tmp_wchars; //! 保存堆中字符串地址, 用于删除.
size_t chars_length; // 实际读取字串字节长, 用于设置文件流指针偏移量和返回值
char * return_chars = NULL;
if (locale_check)
{
chars_length = wcsrtombs(NULL, (const wchar_t**)&tmp_wchars, num + 1, &state_tombs);
return_chars = new char[chars_length + 1];
if (! return_chars)
{
setlocale(LC_CTYPE, locale_original);
delete[] del_chars;
del_chars = NULL;
delete[] del_wchars;
del_wchars = NULL;
return NULL;
}
wcsrtombs(return_chars, (const wchar_t**)&tmp_wchars, chars_length + 1, &state_tombs);
length = chars_length;
}
else
{
chars_length = wcsrtombs(dest_str, (const wchar_t**)&tmp_wchars, num + 1, &state_tombs);
length = chars_length; //!.引用传递返回实际字串字节数
}
if (locale_check)
setlocale(LC_CTYPE, locale_original);
delete[] del_chars;
del_chars = NULL;
delete[] del_wchars;
del_wchars = NULL;
if (fseek(stream, fpos_before + chars_length, SEEK_SET))
return NULL; // 重置文件流指针, 当有错误时, 返回-1
if (locale_check)
return return_chars;
else
return dest_str;
}
如果您修改了一个代码片段并且觉得很应该让别人共享,您可以把这作为这个代码片段的最新版本提交上来. |
|