日志标签 ‘fallseir’

谨慎的在c++中使用cin进行交互

2008年10月24日

在使用c++ 进行控制台交互时 也许你也容易忽略掉的细节

– 飞扬轻狂 20081024 fallseir[at]gmail.com

http://blog.fallseir.com/2008/10/note_std_cinnote_std_cin/

注意1: ” cin >> value ” 没有正确的读取换行
注意2: 不匹配的类型 将导致输入流错误 而在其后的调用中自动返回
注意3: 空字符 在使用 >> 赋值给变量时将自动过滤 直到读入非空字符为止

出错的代码 !!

$ vim 02-05-BasicIO-err.cpp
---------------------------------------------
#include 
using namespace std;
int main( int argc, char *argv[] ){
  int num;
  string str,line;

  cout << "Please enter a number:" ;
  cin >> num;
  cout << "Please enter a text :" ;
  cin >> str;
  cout << "Please enter some words :" ;
  getline( cin, line );

  cout << endl;
  cout << "number : " << num << endl;
  cout << "text : " << str << endl;
  cout << "some words : " << line << endl;

  return 0;
}
---------------------------------------------
$ g++ 02-05-BasicIO-err.cpp
$ a.out # 貌似正确的输入
----------------
Please enter a number:12
Please enter a text :message
Please enter some words :
number : 12
text : message
some words :
----------------
/*
 分析原因:
 第二次输入 "message" 的时候 自动过滤前次的 并得到了正确的值
 getline 的时候 因为输入流中还有一个  没有被读取 所以没有等待用户输入,直接返回了
 */
--------------------
$ a.out # 貌似正确的结果
----------------
Please enter a number:13 message some words in the line 
Please enter a text :P lease enter some words :
number : 13
text : message
some words :  some words in the line
----------------
/*
 分析原因:
 cin >> str 的时候 从流中读取了 "message"
 getline 的时候 读取了流中剩下的内容
 */
--------------------
$ a.out # 错误的开始
----------------
Please enter a number:a
Please enter a text :P lease enter some words :
number : 6696948
text :
some words :
----------------
/*
 分析原因:
 cin >> num 的时候 从流中读取了不匹配的数据 "a" ,cin 进入异常状态
 cin >> str 和 getline 的时候 因为流异常 所以没有进行读取
 */
--------------------

优化的严谨的代码

$ vim 02-05-BasicIO.cpp
---------------------------------------------
#include 
using namespace std;
int main( int argc, char *argv[] ){
  int num;
  string str,line;
  string tmp;

  cout << "Please enter a number:" ;
  cin >> num;
  while(cin.fail()){ // 如果出现错误
    cin.clear(); // 清除错误
    getline(cin,tmp); // 清除缓存
    cerr << "Error input!!,Please try again" << endl;
    cin >> num;
  }
  getline(cin,tmp); // 使用getline清除缓存,因为 >> 操作符不会对末尾的  进行读取 

  cout << "Please enter a text :" ;
  cin >> str;
  getline(cin,tmp);

  cout << "Please enter some words :" ;
  getline( cin, line );
  cout << endl;
  cout << "number : " << num << endl;
  cout << "text : " << str << endl;
  cout << "some words : " << line << endl;

  return 0;
}

---------------------------------------------
----------------
$ a.out
----------------
Please enter a number:123 message test words!
Please enter a text :word and message
Please enter some words :some words in the line!

number : 123
text : word
some words : some words in the line!
----------------

--

http://blog.fallseir.com/2008/10/note_std_cinnote_std_cin/

飞扬轻狂
fallseir[at]gmail.com
blog.fallseir.com
2008年10月24日
转载请注明

一段用于替换字符串中指定的key的代码

2008年5月6日

一段用于替换字符串中指定的key的代码

–[[User:Fallseir|飞扬轻狂]] 2008年5月6日 (二) 02:32 (PDT)
$str=mapKeys($formatstr,$maps);

$str=“replace this template string !the key maps is here
key1=>{key1},key{{2=>{key{2},key3}=>{key3{}}”
;
echo 
mapKeys($str
  
,array(“key1″=>“value 1″
  
,“key{2″=>“value 2″
  
,“key3}”=>“value 3″
  
)
);
echo 
“\n”

output>>
replace this template string !the key maps is here
key1=>value 1,key{2=>value 2,key3}=>value 3
abc[the abc value]}}%[%}%%%]%{%[0}%%,%%%,{key],%%,%%[the %value% 2],%%[the %value% 2],%$$%%{,%,
abc%%%%%%%%%,%%%,%key%,%%,%%%key,2%,%,%$$%%,%,

$ php -r ‘highlight_file(“test.php”);’


<?php
/** test */
$str="replace this template string !the key maps is here
key1=>{key1},key{{2=>{key{2},key3}=>{key3{}}"
;
echo 
mapKeys($str
  
,array("key1"=>"value 1"
  
,"key{2"=>"value 2"
  
,"key3}"=>"value 3"
  
)
);
echo 
"\n";

$str="abc{key}{}}%{%{}%%%}%{{%{0{}%%,%%%,{key},%%,%%{key,2},%%{key,2},%$$%%{,%,";
echo 
mapKeys($str,array("key"=>"[the abc value]"
,"key,2"=>"[the %value% 2]"));
echo 
"\n";

$str="abc%%%%%%%%%,%%%,%key%,%%,%%%key,2%,%,%$$%%,%,";
echo 
mapKeys($str,array("key"=>"[the abc value]"
    
,"key,2"=>"[the %value% 2]"),"|%|");
echo 
"\n";
//end test*/
/*
$ php test.php
output>>
replace this template string !the key maps is here
key1=>value 1,key{2=>value 2,key3}=>value 3
abc[the abc value]}}%[%}%%%]%{%[0}%%,%%%,{key],%%,%%[the %value% 2],%%[the %value% 2],%$$%%{,%,
abc%%%%%%%%%,%%%,%key%,%%,%%%key,2%,%,%$$%%,%,
 
 */
 
 
/**
 * 使用maps中定义的value替换对应其key的由开始标记字符和结束标记字符包含的字符串
 *
 * 当标记对外开始标记后跟着开始标记时或结束标记时表示第一个开始标记为转义符
 * 当标记对内开始标记后跟着结束标记时表示第一个开始标记为转义符
 * 末尾没有匹配的开始标记将原样输出
 */
function mapKeys($str,$maps,$fstart=null,$fend=null){
  if(!
$fstart){
      
$fstart="{";
      
$fend="}";
  }
  if(!
$fend){
    
$fend=$fstart;    
  }
  
  
// 如果标记相同则使用mapKeysBase进行替换
  
if($fstart==$fend){return mapKeysBase($str,$maps,$fstart);}
 
  
$index=0;
  
$offset=0;
  while(
false!==($index=strpos($str,$fstart,$offset))){
    
# 找到开始标记,处理开始标记之前的数据
    
$v=substr($str,$offset,$index-$offset);
    
$offset=$index+strlen($fstart);
    
$p=true;
    while((
$find=substr($str,$offset,strlen($fstart)))==$fstart
      
||($find=substr($str,$offset,strlen($fend)))==$fend){
      
$v.=$find;
      
$offset=$offset+strlen($find);
      
$p=false;# 如果这个标记是用来转义的
      
if(false!==($index=strpos($str,$fstart,$offset))){
        
$v.=substr($str,$offset,$index-$offset);
        
$offset=$index+strlen($fstart);
        
$p=true;# 查找下一个开始标记
      
}
    }
    
$o.=$v;
    
$v="";
    
# 标记了开始 并找到了 结束
    
while($p
      
&&false!==($end=strpos($str,$fend,$offset))){
      
$v.=substr($str,$offset,$end-$offset);
      
# 如果这个标记是被转义的
      
if(($find=substr($str,$end-strlen($fend),strlen($fstart)))
        ==
$fstart){
        
$v=substr($v,0,strlen($v)-strlen($fstart)).$fend;
        
$offset=$end+strlen($fend);
        continue;
      }
      
$p=false;
    }
    if(
$v){
      if(
array_key_exists($v,$maps)){
        
$v=$maps[$v];
      }else{
        
$v="[".$v."]";
      }
      
$o.=$v;
      
$offset=$end+strlen($fend);
    }
  }
  if(
$p){
    
$o.=$fstart;
  }
  
$v=substr($str,$offset);
  
$o.=$v;
  return 
$o;
}
/**
 * 使用maps中定义的value替换对应其key的由标记字符包含的字符串
 *
 * 如果标记重复出现 则第一个为转义字符(这也意味着标记字符不能作为key的开始字符)
 */
function mapKeysBase($str,$maps,$find=null){
  if(!
$find){
    
$find="%";
  }
  
$p=false;
  
$v="";
  
$index=0;
  
$offset=0;
  while(
false!==($index=strpos($str,$find,$offset))){
    
$v.=substr($str,$offset,$index-$offset);
    
$offset=$index+strlen($find);
    while(
substr($str,$offset,strlen($find))==$find){
      
$v.=$find;
      
$offset=$offset+strlen($find);
      if(
false!==($index=strpos($str,$find,$offset))){
        
$v.=substr($str,$offset,$index-$offset);
        
$offset=$index+strlen($find);
      }
    }
    if(
$p){
      if(
array_key_exists($v,$maps)){
        
$v=$maps[$v];
      }else{
        
$v="[".$v."]";
      }
      
$o.=$v;
      
$v="";
      
$p=false;
    }else{
      
$o.=$v;
      
$v="";
      
$p=true;
    }
  }
  if(
$p){
    
$v.=$find;
  }
  
$v.=substr($str,$offset);
  
$o.=$v;
  return 
$o;
}
?>


取自”http://www.fallseir.com/wiki/PHP/MapKeys.html