ROR群(15917997)里有朋友问到一个问题
s="hello"
s[s.length,1]为什么返回"",而不是返回nil或其他
群里展开了讨论,我翻了翻ruby源代码,试着做出解释:
首先查了API,
string[integer, integer]会执行
rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
rb_str_substr是这样的:
VALUE
rb_str_substr(str, beg, len)
VALUE str;
long beg, len;
{
VALUE str2;
if (len < 0) return Qnil;
if (beg > RSTRING(str)->len) return Qnil;
if (beg < 0) {
beg += RSTRING(str)->len;
if (beg < 0) return Qnil;
}
if (beg + len > RSTRING(str)->len) {
len = RSTRING(str)->len - beg;
}
if (len < 0) {
len = 0;
}
if (len == 0) {
str2 = rb_str_new5(str,0,0);
}
else if (len > sizeof(struct RString)/2 &&
beg + len == RSTRING(str)->len && !FL_TEST(str, STR_ASSOC)) {
str2 = rb_str_new4(str);
str2 = str_new3(rb_obj_class(str2), str2);
RSTRING(str2)->ptr += RSTRING(str2)->len - len;
RSTRING(str2)->len = len;
}
else {
str2 = rb_str_new5(str, RSTRING(str)->ptr+beg, len);
}
OBJ_INFECT(str2, str);
return str2;
}
看到这两句
if (len < 0) return Qnil;
if (beg > RSTRING(str)->len) return Qnil;
意思是说要截取的字串长度如果为负数,返回nil
开始的位置超出了原字串的长度,也返回nil
往下看,因为s.lenght刚好等于RSTRING(str)->len,其实会执行到
str2 = rb_str_new5(str, RSTRING(str)->ptr+beg, len);
rb_str_new5是这样的
VALUE
rb_str_new5(obj, ptr, len)
VALUE obj;
const char *ptr;
long len;
{
return str_new(rb_obj_class(obj), ptr, len);
}
主要是调用了str_new
static VALUE
str_new(klass, ptr, len)
VALUE klass;
const char *ptr;
long len;
{
VALUE str;
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
str = str_alloc(klass);
RSTRING(str)->len = len;
RSTRING(str)->aux.capa = len;
RSTRING(str)->ptr = ALLOC_N(char,len+1);
if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
}
RSTRING(str)->ptr[len] = '\0';
return str;
}
到了
if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
}
ptr其实已经指向了"hello"的最后一个字符,也就是'\0'了,执行完memcpy后,str成了"",再最后执行
RSTRING(str)->ptr[len] = '\0';
这一句加""加上'\0',是c语言的空字符串.
最后的结果就是""了.
路线是这样的
s[s.length,1]
==> rb_str_substr("hello", 5, 1);
==> rb_str_new5("hello",ptr=5,1);
==> str_new("hello",ptr=5,1)
==>memcpy("hello",ptr=5,1)
==>""
分享到:
相关推荐
`t.length` 返回的是二维数组的长度,即行数,所以`t.length` 等于 2,而 `t[0].length` 返回第一维数组的长度,即每行的元素个数,所以`t[0].length` 等于 3。题目中描述的 `t.length=3` 和 `t[0].length=2` 是错误...
因为直接使用的串口助手,8266也设置的回传模式,所以这里可以看到相应的返回,出现了busy s... 那么这个busy对我们的实际操作有没有影响呢,结合我们浏览器显示的内容: 和实际发送的报文: HTTP/1.1 200 OK ...
j <= pos + S.length - 2 && k < S.length; j++, k++) T.ch[j] = S.ch[k]; T.length += S.length; } return OK; } ``` ### 三、其他操作 除了上述操作外,还有打印堆串、清空堆串等功能。例如,打印堆串功能...
switch(m.substr(1,1)){ case s : return v.toString() case S : return +v.replace( , \\ )+ case f : return v-0 case d : return v.getFullYear()+ - +v.getMonth()+ - +v.getDate() case D...
s=arr[--t],arr[t]=arr[e],arr[e]=s){}h.options.slides=arr}if(h.options.slides.length>1){if(h.options.slides.length>2){vars.current_slide-1<0?loadPrev=h.options.slides.length-1:loadPrev=vars.current_...
if (i < 1 || i > S.length() + 1) { cout !" ; exit(0); } for (int j = S.length(); j >= i; j--) { S.data[j] = S.data[j - 1]; } S.data[i - 1] = x; S.len++; return 0; } ``` 3. 删除所有具有给定...
default:s=Array.prototype.slice.call(arguments,1),r.apply(this,s)}else if(n(r))for(s=Array.prototype.slice.call(arguments,1),u=r.slice(),a=u.length,l=0;l;l++)u[l].apply(this,s);return!0},r.prototype....
if (s == null || s.length() == 0) return s; byte abyte0[] = s.getBytes(); char ac[] = new char[s.length()]; int i = 0; for (int k = abyte0.length; i ; i++) { int j = abyte0[i];
//s.quickSort(arr, 0, arr.length-1); //快速排序 //int[] temp = new int[arr.length]; //s.mergeSort(arr, 0, arr.length-1, temp); //归并排序 //s.headSort(arr);//堆排序 System.out.println(Arrays....
遍历字符串`s`的每个字符,更新`dp`数组,并在最后检查`dp[s.length]`是否为`true`,如果是,则返回`true`,否则返回`false`。 ### 5. JavaScript实现 ```javascript function wordBreak(s, wordDict) { const dp...
while (i < S.length && j < T.length) { if (S.str[i] == T.str[j]) { i++; j++; } else if (j == 0) { i++; } else { j = next[j]; } } if (j == T.length) v = i - T.length; else v = -1; return v...
int[,] dp = new int[s.Length + 1, t.Length + 1]; for (int i = 0; i <= s.Length; i++) dp[i, 0] = i; for (int j = 0; j <= t.Length; j++) dp[0, j] = j; for (int i = 1; i <= s.Length; i++) { for ...
printf("%d\n",*(S.top-1)); } } void Push () { scanf("%d",S.top); *S.top++; S.Length++; printf("OK\n"); } void Pop () { if(S.top==S.base) { printf("NULL\n"); } else { S.Length--;...
s.LastIndexOf('.') == s.Length - 1 || n.Length - n.LastIndexOf('.') > 3 || (s.IndexOf('0') == 0 && s.IndexOf('.') > 1)) { return false; } // 检查千位分隔符的位置和数量 int i = 1; for (i = 1...
本文实例讲述了... var S=sstr= ,L1=s1.length,L2=s2.length; if (L1>L2){ var s3=s1;s1=s2,s2=s3,L1=s2.length;} for ( var j=L1;j> 0 ;j--) for ( var i= 0 ;i<=L1-j;i++){ sstr = s1.substr(i,j); if
fwrite(&S, S.length, 1, fp); fprintf(fp,"%c", 10); //是输入换行 printf("结束输入吗?y or n: "); yn=getchar(); } fclose(fp); //关闭文件 printf("建立文件结束!"); } void SubStrCount(){ FILE *fp...
String s = Integer.toString(i+1);// "1" char[] num = s.toCharArray(); // {'1'} System.arraycopy(num, 0, ch, ch.length-num.length, num.length); String ball = new String(ch); red[i] = ball; } ...
Time elapsed.......1:01 Time remaining.....8:57 Program Call Stack AbortLog Generic_Abort ReadDiskSectorsNoOverlayTranslation ReadDiskSectors FatReadPartSectors ReadFATsector GetFATsectorOut ...
if (whitespace.indexOf(s.charAt(s.length - 1)) != -1) { var i = s.length - 1; while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1) { i--; } s = s.substring(0, i + 1); } return s; } ``` 4. ...
export function md5_hex(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} export function md5_b64(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} export function md5_str(s)...