| 项目搜索 |
| |
|
代码片段库:
查看代码片段
浏览
| 提交新的代码片段
| 创建代码包
多字节函数库系列:标准输入读取:cy_safegets()
|
类型:
Function |
类别:
Other
|
许可证:
GNU Library Public License |
语言:
C++
|
描述:
从标准输入读取一行数据,函数参数中指定最多读入的字符数(非字节数),多余的数据将被丢弃。
此函数试图代替有“缓冲溢出”安全隐患的“gets()”标准读入函数。
|
该代码片段的版本系列:
片段ID |
下载版本 |
提交时间 |
提交人 |
删除 |
4570 | 0.1 | 2002-06-26 20:52 | renxiao | |
点击"下载版本"来下载该代码片段.
最新版本的代码片段: 0.1
/*-----------------------Own_lib函数库系列 safegets.cc-------------------------
cy_safegets() /safegets.o /libcyfunc.a
描述: 代替有"缓冲溢出"安全隐患的"gets()"标准读入函数.
本函数实际使用的是"fgets()"标准文件读入函数, 但"FILE*"直接设成了'stdin'.
返回的字符串中已去掉了末尾的换行符(如果有)或超过max_chars字符数的输入.
用户调用cy_safegets()时, 传递有足够大(MB_CUR_MAX * max_chars + 1)内存空间
的目的字符串指针 | 需要读入的最多字符数(非字节数) | 和"LC_CTYPE"区域设置
字符串(如: "zh_CN.GBK", 默认值为NULL, 表示不改变系统设置). 传入区域字符串
后函数将临时改变系统"LC_CTYPE"的设置.
第二个函数为重载函数, 增加了第三个整数引用参数用于返回实际字串的单字节数,
和第四个整数引用参数用于返回实际字串的字符数.
dest_str:
保存读入字符串的内存空间的指针/或NULL值.
max_chars:
需要从标准输入设备读入的字符个数(按: 对于中文应是输入法服务器传来的字串).
locale_ctype:
读入字串所属的LC_CTYPE区域(语系/编码). 一般程序开头已经设定, 故此可不管它.
[length]:
返回实际读取字符串的字节数.
[chars]:
返回实际读取字符串的字符数.
locale_ctype = NULL:
读入字串所属的LC_CTYPE区域(语系/编码). 一般程序开头已经设定, 故此可不管它.
返回值:
返回指向dest_str内存空间/堆中的字符串指针(末尾已加'\0'). 若有错误返回NULL.
注意! 1. 函数从标准输入读入字符串直到出现换行, 或是已读了max_chars个字符为止.
2. 当传递LC_CTYPE区域设置时, 参数dest_str必须为NULL, 函数返回指向自由存储
区/堆中的字符串指针, 故用完后应立即delete[]掉, 并赋值为NULL.
作者: 任逍 |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 "cyinclude/cyfget.h"
char * cy_safegets(char * dest_str, int max_chars, const char * locale_ctype = 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
return NULL;
}
size_t test_length = 0; // 用于测试输入字数是否超过需求
char * tmp_chars = new char[num + 1]; // 字串所需最大可能空间, 临时存放用
wchar_t * tmp_wchars = new wchar_t[num + 1];
char tmp_trash_chars[256]; // 用于循环赋值-->删除多余的字串
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, stdin)) // 接收最大限定数量的输入字符串
{
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) )
tmp_wchars[max_chars] = L'\0'; // 多出来的字符或非法字节被截断或覆盖
else
if ( (test_length == max_chars) && (tmp_wchars[test_length - 1] != L'\n') )
;
else
tmp_wchars[test_length - 1] = L'\0'; // 覆盖掉末尾的换行符
char * return_chars = NULL;
if (locale_check)
{
size_t 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
wcstombs(dest_str, tmp_wchars, num + 1); //..转换目的字符串
if (locale_check)
setlocale(LC_CTYPE, locale_original);
if ( (strlen(tmp_chars) == num) && (tmp_chars[num - 1] != '\n') )
while (fgets(tmp_trash_chars, 256, stdin) != NULL)
// 循环接收标准输入缓冲中未处理的字串. (重复赋值, 函数退出时自动丢弃)
if ( (strlen(tmp_trash_chars) == 255) && (tmp_trash_chars[254] != '\n') )
continue;
else
break;
delete[] tmp_chars;
tmp_chars = NULL;
delete[] tmp_wchars;
tmp_wchars = NULL;
if (locale_check)
return return_chars;
else
return dest_str;
}
//-----------------------------------------------------------------------------
// 上一函数的重载函数.
char * cy_safegets(char * dest_str, int max_chars,
int & length, int & chars, const char * locale_ctype = 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
return NULL;
}
size_t test_length = 0; // 用于测试输入字数是否超过需求
char * tmp_chars = new char[num + 1]; // 字串所需最大可能空间, 临时存放用
wchar_t * tmp_wchars = new wchar_t[num + 1];
char tmp_trash_chars[256]; // 用于循环赋值-->删除多余的字串
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, stdin)) // 接收最大限定数量的输入字符串
{
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) )
{
tmp_wchars[max_chars] = L'\0'; // 多出来的字符或非法字节被截断或覆盖
chars = max_chars; //!.引用传递返回实际字串字符数
}
else
if ( (test_length == max_chars) && (tmp_wchars[test_length - 1] != L'\n') )
chars = max_chars; //!.引用传递返回实际字串字符数
else
{
tmp_wchars[test_length - 1] = L'\0'; // 覆盖掉末尾的换行符
chars = test_length - 1; //!.引用传递返回实际字串字符数
}
char * return_chars = NULL;
if (locale_check)
{
size_t 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
length = wcstombs(dest_str, tmp_wchars, num + 1);
//!.返回实际字串的单字节长度(字节数)
if (locale_check)
setlocale(LC_CTYPE, locale_original);
if ( (strlen(tmp_chars) == num) && (tmp_chars[num - 1] != '\n') )
while (fgets(tmp_trash_chars, 256, stdin) != NULL)
// 循环接收标准输入缓冲中未处理的字串. (重复赋值, 函数退出时自动丢弃)
if ( (strlen(tmp_trash_chars) == 255) && (tmp_trash_chars[254] != '\n') )
continue;
else
break;
delete[] tmp_chars;
tmp_chars = NULL;
delete[] tmp_wchars;
tmp_wchars = NULL;
if (locale_check)
return return_chars;
else
return dest_str;
}
如果您修改了一个代码片段并且觉得很应该让别人共享,您可以把这作为这个代码片段的最新版本提交上来. |
|