| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1040 人关注过本帖
标题:C 和指针 程序 6.3 在一组字符串中查找: 版本 2
只看楼主 加入收藏
xiehou314159
Rank: 2
等 级:论坛游民
帖 子:35
专家分:86
注 册:2011-5-11
收藏
 问题点数:0 回复次数:16 
C 和指针 程序 6.3 在一组字符串中查找: 版本 2
#include <stdio.h>
#include <assert.h>

#define TRUE 1
#define FALSE 0

int
find_char(char **strings, int value)
{
    assert(strings != NULL);

    while (*strings != NULL) {
        while (**strings != '\0') {
            if (*(*strings)++ == value)
                return TRUE;
        }
        strings++;
    }

    return FALSE;
}

书上说由于存在副作用,这个程序将破坏这个指针数组,它只适用于字符串只需要查找一次的情况。
我也运行过这个程序了,的确是会破坏,但没有想通理由。
指向当前字符串字符的指针值增加1后,第二次再应用这个查找程序时为何指向字符的指针不会重新指向字符串第一个字符,而strings却会重新指向第一个指针。
搜索更多相关主题的帖子: include return 副作用 字符串 
2014-09-27 22:23
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
问题出在自加(++)那里。其实,要提前预防也可以,把变量(形参)声明为const的,那么编译器就会警告你修改了目标数据,事实上按照逻辑,你本来就不想修改数据,那么也应主动写出const,而不是在运行时有bug也不知道(当你没有测试第二次运行的情况下或没细心审视数据被修改的时候)。

[ 本帖最后由 TonyDeng 于 2014-9-28 12:18 编辑 ]

授人以渔,不授人以鱼。
2014-09-28 12:15
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这个陷阱确实很隐蔽,它在第二次调用该函数时也未必出错,触发错误是有条件的。

授人以渔,不授人以鱼。
2014-09-28 12:29
xiehou314159
Rank: 2
等 级:论坛游民
帖 子:35
专家分:86
注 册:2011-5-11
收藏
得分:0 
回复 2 楼 TonyDeng
首先谢谢你的解答

#include <stdio.h>

#define NUM 50
#define TRUE 1
#define FALSE 0

int
find_char(char **strings, int value);

int main(void)
{
    char *strings[NUM] = {"abcdefg", "hijklmn"};

    fprintf(stdout, "%d\n", find_char(strings, 'a'));
    fprintf(stdout, "%d\n", find_char(strings, 'a'));

    return 0;
}

//int find_char(char **strings, int value)
//{
//
//    while (*strings != NULL) {
//        while (**strings != '\0') {
//            if (*(*strings)++ == value) {
//                return TRUE;
//            }
//        }
//        strings++;
//    }
//
//    return FALSE;
//}


int find_char(char **strings, int value)
{
    char *string;

    while ((string=*strings++) != NULL) {
        while (*string != '\0') {
            if (*string++ == value) {
                return TRUE;
            }
        }
    }

    return FALSE;
}

用下面的这个版本执行程序得出的结果是1(换行)1,而用注释掉的那个版本结果是1(换行)0
我明白问题是出在++那个地方,就是还没搞清楚,为什么用注释掉的那个版本,在第二次调用那个函数时,指针数组内的指针指向字符的最初位置,会是第一次执行结束时的位置,而不是字符串的起始位置
2014-09-28 23:09
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
没有改变内存块头的地址,但改了块内子块的入口地址,即*strings的地址被改了,**strings的地址是没变的。你原先的程序(1楼代码),当第二次查的时候,如果结果在第一次的后面,也是可以成功的,但若在前面,才会出错——那是因为*(*strings)++改了扫描过的部分,但在中途return跳出后来不及改后面的。

授人以渔,不授人以鱼。
2014-09-29 01:46
love云彩
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:青藏高原
等 级:贵宾
威 望:53
帖 子:3663
专家分:11416
注 册:2012-11-17
收藏
得分:0 
回复 5 楼 TonyDeng
T版又要上夜班?赶紧去水区水一水

思考赐予新生,时间在于定义
2014-09-29 01:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这个查找函数的设计思想本身就不对路,可以说是自己主动引入错误,有好的简单设计不用,搞复杂的、容易错的。我不知道这书中拿这例子用来讲什么问题。

授人以渔,不授人以鱼。
2014-09-29 15:09
xiehou314159
Rank: 2
等 级:论坛游民
帖 子:35
专家分:86
注 册:2011-5-11
收藏
得分:0 
回复 7 楼 TonyDeng
以下引用于《C和指针》
书上列出版本2是为了做个比较,它能实现版本1的功能。一方面不需要对指向的每个字符串的指针作一份拷贝,这是它的相对优势所在,另一方面,由于存在副作用,版本2将破坏这个指针数组,这个副作用使得它不如版本1有用,因为它只适用于字符串只需要查找一次的情况。
2014-09-29 20:07
xiehou314159
Rank: 2
等 级:论坛游民
帖 子:35
专家分:86
注 册:2011-5-11
收藏
得分:0 
回复 5 楼 TonyDeng
这样的解释,我目前只能觉得是那么回事,从程序运行的结果来看是这样的,但还是不能从本质上理解,估计还需多看些书才能理解
2014-09-29 20:13
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
既然知道这种代码是不应该写出的,弄懂它有什么用?

授人以渔,不授人以鱼。
2014-09-30 10:25
快速回复:C 和指针 程序 6.3 在一组字符串中查找: 版本 2
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.012513 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved