注册 登录
编程论坛 VFP论坛

请教二表随机整行替换代码中的一个错误提示

fdxxhjc 发布于 2022-02-13 20:38, 4238 次点击
先生们好,有A、B二表都是10行6列,现在随机的从B表中取几整行去替换A表中相对应的整行,搞了点代码,但在运行中总是提示“记录超出范围”,检查了多次,总觉得记录没超出范围,请先生指点,谢放,。
ACTIVATE SCREEN
CLEAR
CLOSE DATABASES
SET DEFAULT TO "d:\请教"
use  交换结果记录表.dbf alias a in 0
USE b IN 0

SET SAFETY OFF
********************************************************************************
*A表中的任一行与B表中的行只交换一行
    * 本块应该有10种可能性,共有100行

*A表中的任二行与B表中的行只交换二行
    * 本块应该有9+8+...+2+1种即45种可能性,共有450行
   
*A表中的任三行与B表中的行只交换三行
    * 本块应该有8+7+...+2+1种即36种可能性,共有360行
   
*A表中的任四行与B表中的行只交换四行
    * 本块应该有7+...+2+1种即28种可能性,共有280行   

*A表中的任五行与B表中的行只交换五行
    * 本块应该有6+5+...+2+1种即21种可能性,共有210行   
   
*A表中的任六行与B表中的行只交换六行
    * 本块应该有5+4+...+2+1种即15种可能性,共有150行   
   
*A表中的任七行与B表中的行只交换七行
    * 本块应该有4+3+2+1种即10种可能性,共有100行   
   
*A表中的任八行与B表中的行只交换八行
    * 本块应该有3+2+1种即6种可能性,共有60行
   
*A表中的任九行与B表中的行只交换九行
    * 本块应该有2+1种即3种可能性,共有30行   
   
*A表中的十行与B表中的行交换十行
    * 本块应该有1种可能性,共有10行

LOCAL 随机行数值
随机行数值 = 获取一个随机整数值(1,10)

LOCAL 随机行号串A, 随机行号串B
随机行号串A = 获取任意一组数字(1,10,随机行数值)
随机行号串B = 获取任意一组数字(1,10,随机行数值)
ACTIVATE SCREEN
?随机行数值, ": " , 随机行号串A,随机行号串B

LOCAL m.i
LOCAL m.nA, m.nB

FOR m.i = 1 TO 随机行数值
    m.nA = VAL(GETWORDNUM(随机行号串A,m.i,","))
    m.nB = VAL(GETWORDNUM(随机行号串B,m.i,","))
   
    ? m.i, "将B表的行【" + ALLTRIM(STR(m.nB)) + "】替换到表A的行【" + ALLTRIM(STR(m.nA)) + "】"
   
    SELECT b
    GOTO m.nB
    SCATTER MEMVAR
   
    SELECT a
    ? "       m.nA=" ,m.nA
    GOTO m.nA
    GATHER MEMVAR
NEXT

FUNCTION 获取一个随机整数值()
    LPARAMETERS 最小值,最大值
   
    LOCAL m.n
    m.n = ROUND(RAND() * (最大值-最小值+1),0)
   
    IF m.n = 0
        m.n = m.n + 1
    ENDIF
   
    m.n = 最小值 + m.n -1
    IF m.n<最小值
        m.n = 最小值
    ENDIF
    IF m.n>最大值
        m.n=最大值
    ENDIF
   
    RETURN m.n
ENDFUNC

FUNCTION 获取任意一组数字()
    LPARAMETERS 开始行,结束行, 个数
   
    LOCAL 行数
    行数 = 结束行 - 开始行 + 1

    LOCAL ARRAY 行号数组(行数,2)
    LOCAL m.n
   
    FOR m.n = 1 TO 行数
        行号数组(m.n,1) = 开始行 + m.n - 1
        行号数组(m.n,2) = RAND()
   
        ACTIVATE SCREEN
        ?m.n, 行号数组(m.n,1), 行号数组(m.n,2)
    NEXT
   
    ?"=========================================A"

    LOCAL m.i, m.j
    LOCAL m.A, m.B
    LOCAL m.T1, m.T2
   
    FOR m.i = 1 TO 行数 -1
        m.A = 行号数组(m.i,2)
        
        FOR m.j = m.i + 1 TO 行数
            m.B = 行号数组(m.j,2)
            
            IF m.A > m.B
                m.T1 = 行号数组(m.i,1)
                m.T2 = 行号数组(m.i,2)
                行号数组(m.i,1) = 行号数组(m.j,1)
                行号数组(m.i,2) = 行号数组(m.j,2)
                行号数组(m.j,1) = m.T1
                行号数组(m.j,2) = m.T2
               
                m.A = 行号数组(m.i,2)
            ENDIF
            
        NEXT
    NEXT
   
    ?"=========================================B"
   
    FOR m.n = 1 TO 行数
        ACTIVATE SCREEN
        ?m.n, 行号数组(m.n,1), 行号数组(m.n,2)
    NEXT
   
    LOCAL m.s
    m.s = ""
   
    FOR m.n = 1 TO 个数
        m.s = m.s + "," + ALLTRIM(STR(行号数组(m.n,1)))
    NEXT
   
    m.s = SUBSTR(m.s,2)
    ?"=========================================C"
    ?""
    RETURN m.s   
   
ENDFUNC

程序及A、B表等在压缩包中
只有本站会员才能查看附件,请 登录
43 回复
#2
sdta2022-02-13 21:20
use  交换结果记录表.dbf alias a in 0 && 此处 a 为表别名
.........
........
   SELECT a && 此处 a 是指A表,还是别名为 a 表名为交换结果记录表
    ? "       m.nA=" ,m.nA
    GOTO m.nA
    GATHER MEMVAR

这两处的 a 是否是一个意思
#3
laowan0012022-02-13 21:38
问题既然是“记录超出范围”,那就在go语句之前,检查表的recc()和要跳转的记录号,是否合理,
另:强烈建议不要使用单个字母做表的alias,楼顶程序中的alias a可以改为alias a1,或alias aa

2楼提到的疑问确实很可疑
#4
fdxxhjc2022-02-14 08:23
回复 2楼 sdta
先生早上好,我将这行  use  交换结果记录表.dbf alias a in 0
                改成  use  交换结果记录表.dbf alias a1 in 0
运行还是提示记录超出
#5
schtg2022-02-14 08:34
回复 楼主 fdxxhjc
先在“交换结果记录表”增加多于10个的空记录,再试一试。


[此贴子已经被作者于2022-2-14 19:23编辑过]

#6
laowan0012022-02-14 08:34
use 交换结果记录表.dbf alias a in 0
这行语句打开了交换结果记录表,初始记录数为0,指定别名是a。
问题背景说明“有A、B二表都是10行6列”,这里的表A是另一个实体表,表名与上个语句的别名重复了。
楼主估计是把结果表的别名a当成是实体表A了,所以会出错
在程序中其实并没有打开那个实体表A
#7
吹水佬2022-02-14 10:26
是不是这意思:从B表随机取m条记录放到A表(对应记录号入座)
暂时忽略A表的处理过程,说说每次从B表随机取m条记录的过程
#8
fdxxhjc2022-02-14 15:06
回复 7楼 吹水佬
先生是的,是随机的从B表中取几行(如在B表中随机的取第2、5、6、8行去替换A表中的第2、5、6、8行【整行数字替换】)并将替换后的结果记录到“替换结果记录表.dbf”中
这时替换结果记录表中的行的次序变成
a1、b2、a3、a4、b5、b6、a7、b8、a9、a10的整行的数字了,谢谢先生
#9
吹水佬2022-02-14 15:21
回复 8楼 fdxxhjc
B表只进行了一次随机取记录就完结了?
#10
fdxxhjc2022-02-14 15:48
回复 9楼 吹水佬
最好是要有可选择多次的,谢谢先生
#11
吹水佬2022-02-14 15:58
以下是引用fdxxhjc在2022-2-14 15:48:45的发言:

最好是要有可选择多次的,谢谢先生

就如例举的10行记录,每次随机记录数最小1行、最大10行。
多次进行,B表不变的话,随机获取的记录数就有可能出现重复。
#12
fdxxhjc2022-02-14 16:12
回复 11楼 吹水佬
打个比方,共选择5次,这5次的总的情况是有重复的可能,但第一次、第二次、、、、这样每一次中是不会有重复的
(每次的替换时可用文字来分隔,如第一次交换结果如下、第二次交换结果如下、、、)
#13
吹水佬2022-02-14 18:07
有可能.......又不会有
还是不太明白,就好象8楼举例说明一下:第一次、第二次......之后的结果
#14
fdxxhjc2022-02-14 19:15
回复 13楼 吹水佬
具体例子如下
A                            B                            随机的B中的行替换对应的A中的行记录表                    
列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6
280    56    182    172    147    30        9    233    107    117    142    259        280    56    182    172    147    30
284    60    158    123    202    40        5    229    131    166    87    249        5    229    131    166    87    249
2    238    95    138    150    244        287    51    194    151    139    45        2    238    95    138    150    244
121    203    217    47    246    33        168    86    72    242    43    256        168    86    72    242    43    256
29    126    195    227    49    241        260    163    94    62    240    48        260    163    94    62    240    48
93    129    173    218    253    1        196    160    116    71    36    288        93    129    173    218    253    1
25    63    113    190    237    239        264    226    176    99    52    50        25    63    113    190    237    239
271    102    89    85    69    251        18    187    200    204    220    38        271    102    89    85    69    251
278    28    162    96    91    212        11    261    127    193    198    77        11    261    127    193    198    77
266    24    179    100    82    216        23    265    110    189    207    73        23    265    110    189    207    73

以上是B中的第2、4、5、9、10行替换了A中对应的行(A的其他的行保持不变)
#15
fdxxhjc2022-02-14 19:17
回复 14楼 fdxxhjc
更直观的例子
只有本站会员才能查看附件,请 登录
#16
吹水佬2022-02-14 20:21
回复 14楼 fdxxhjc
只是选择了一次(5行):2、4、5、9、10 行
不是要选择多次吗, 再次选择后结果又怎样?
#17
fdxxhjc2022-02-14 20:37
回复 16楼 吹水佬
哦,先生我是这样设想的,第一次产生了5个随机数对应了5个行号即交换了这5个行号的5行,第二次若产生了7个随机数,则交换这7个随机数所对应行的数字,以此类推,谢谢先生
在1--10之间的随机数有大有小,即交换的行数有多有少了


[此贴子已经被作者于2022-2-14 20:39编辑过]

#18
吹水佬2022-02-14 20:54
回复 17楼 fdxxhjc
每次随机选择B表,结果只是A表不断在变,B表保持不变。
可以这样:随机乱序B表,再随机选前几条记录,然后按原记录号对号入座A表。



[此贴子已经被作者于2022-2-14 20:55编辑过]

#19
fdxxhjc2022-02-14 21:03
回复 18楼 吹水佬
哦,谢谢先生,按您的逻辑我想一想,谢谢
#20
laowan0012022-02-14 21:47
感觉运行次数越多,A表与B表的相似度就会越高
如果就10条记录的话,估计没几次,两个表可能就一样了
#21
fdxxhjc2022-02-15 08:05
回复 20楼 laowan001
只10条的话是不会很多,从遍历的角度讲也不多的,但每一次替换时都是以原来的A为标准被B的随机几行替换了,所以相似度也不会越来越高的


[此贴子已经被作者于2022-2-15 08:08编辑过]

#22
吹水佬2022-02-15 08:38
回复 21楼 fdxxhjc
那就只是对原A表、B表做一次随机选择替换,不存在多次随机选择替换过程。
#23
fdxxhjc2022-02-15 09:23
回复 22楼 吹水佬
打个比方,我共要进行3次替换(这个次数多少可以让人选择),第一次产生了3个随机数此时将B表中的3整行替换了原A的对应3行,第二次产生了7个随机数此时将B表中的7整行替换了原A的对应7行,第三次产生了1个随机数此时将B表中的1整行替换了原A的对应1行,而原A表是保持原样不变的
#24
laowan0012022-02-15 09:28
既然替换了A表,A表怎么还保持原样不变呢?
#25
吹水佬2022-02-15 10:23
只有本站会员才能查看附件,请 登录

程序代码:
CREATE CURSOR ta (bh I, f1 C(4))
CREATE CURSOR tb (bh I, f1 C(4))
FOR i=1 TO 9
    INSERT INTO ta VALUES (i,"a"+TRANSFORM(i))
    INSERT INTO tb VALUES (i,"b"+TRANSFORM(i))
ENDFOR
SELECT ta
INDEX on bh TAG ta_bh
RAND(-1)
SELECT tb
INDEX ON RAND() TAG tb_r
SET RELATION TO bh INTO "ta"
ran = INT((RECCOUNT("tb")-1)*RAND()+1)
? " 取 "+TRANSFORM(ran)+" 条记录"
i = 0
SCAN FOR i<ran
    ? bh,f1
    i = i+1
    SCATTER MEMVAR
    SELECT ta
    GATHER MEMVAR
ENDSCAN
SELECT * FROM ta
#26
fdxxhjc2022-02-15 12:33
回复 25楼 吹水佬
先生我是这样认为的,原A表当被B表替换后所得的结果是记录在“替换结果记录表.dbf”中的,所以原A表保持不变,或者说是从原A拷贝一份临时表来被B表替换,这样原A表就一直保持不变了,我的这个逻辑不知能否行得通,谢谢先生
#27
吹水佬2022-02-15 12:51
示例中的ta、tb都是临时表,不影响原表。
可以从A表、B表取数或复制得到。
ta就是结果表,表名字不是问题。

[此贴子已经被作者于2022-2-15 12:54编辑过]

#28
fdxxhjc2022-02-15 17:17
回复 27楼 吹水佬
先生您好,我用 COPY  TO  替换结果记录表.dbf 在记录表中得到的结果与您的查询中的结果怎么不一样的,并且在记录表中记录下的不是替换后的数字(10行6列的形式)
#29
吹水佬2022-02-15 17:36
回复 28楼 fdxxhjc
给代码测试看看
#30
fdxxhjc2022-02-15 18:19
回复 29楼 吹水佬
谢谢先生

ACTIVATE SCREEN
CLEAR
CLOSE DATABASES
SET SAFETY OFF
CREATE CURSOR ta (bh I, f1 C(4))
CREATE CURSOR tb (bh I, f1 C(4))
FOR i=1 TO 9
    INSERT INTO ta VALUES (i,"a"+TRANSFORM(i))
    INSERT INTO tb VALUES (i,"b"+TRANSFORM(i))
ENDFOR
SELECT ta
INDEX on bh TAG ta_bh
RAND(-1)
SELECT tb
INDEX ON RAND() TAG tb_r
SET RELATION TO bh INTO "ta"
ran = INT((RECCOUNT("tb")-1)*RAND()+1)
? " 取 "+TRANSFORM(ran)+" 条记录"
i = 0
SCAN FOR i<ran
    ? bh,f1
    i = i+1
    SCATTER MEMVAR
    SELECT ta
    GATHER MEMVAR
ENDSCAN
SELECT * FROM ta
COPY  TO  替换结果记录表.dbf
#31
吹水佬2022-02-15 18:59
测试没问题
只有本站会员才能查看附件,请 登录

#32
fdxxhjc2022-02-15 19:08
回复 31楼 吹水佬
哦,那先生如何才能得到替换后的数字形式呢
#33
吹水佬2022-02-15 19:12
以下是引用fdxxhjc在2022-2-15 19:08:15的发言:

哦,那先生如何才能得到替换后的数字形式呢

数字形式是什么?
#34
fdxxhjc2022-02-15 19:17
回复 33楼 吹水佬
就是替换后的真实表格呵
A                            B                            随机的B中的行替换对应的A中的行记录表                    
列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6
280    56    182    172    147    30        9    233    107    117    142    259        280    56    182    172    147    30
284    60    158    123    202    40        5    229    131    166    87    249        5    229    131    166    87    249
2    238    95    138    150    244        287    51    194    151    139    45        2    238    95    138    150    244
121    203    217    47    246    33        168    86    72    242    43    256        168    86    72    242    43    256
29    126    195    227    49    241        260    163    94    62    240    48        260    163    94    62    240    48
93    129    173    218    253    1        196    160    116    71    36    288        93    129    173    218    253    1
25    63    113    190    237    239        264    226    176    99    52    50        25    63    113    190    237    239
271    102    89    85    69    251        18    187    200    204    220    38        271    102    89    85    69    251
278    28    162    96    91    212        11    261    127    193    198    77        11    261    127    193    198    77
266    24    179    100    82    216        23    265    110    189    207    73        23    265    110    189    207    73


[此贴子已经被作者于2022-2-15 19:19编辑过]

#35
吹水佬2022-02-15 19:19
以下是引用fdxxhjc在2022-2-15 19:17:28的发言:

就是替换后的真实表格呵

真实表格又是什么呵
#36
fdxxhjc2022-02-15 19:19
回复 35楼 吹水佬
就是替换后的真实表格呵
A                            B                            随机的B中的行替换对应的A中的行记录表                    
列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6        列1    列2    列3    列4    列5    列6
280    56    182    172    147    30        9    233    107    117    142    259        280    56    182    172    147    30
284    60    158    123    202    40        5    229    131    166    87    249        5    229    131    166    87    249
2    238    95    138    150    244        287    51    194    151    139    45        2    238    95    138    150    244
121    203    217    47    246    33        168    86    72    242    43    256        168    86    72    242    43    256
29    126    195    227    49    241        260    163    94    62    240    48        260    163    94    62    240    48
93    129    173    218    253    1        196    160    116    71    36    288        93    129    173    218    253    1
25    63    113    190    237    239        264    226    176    99    52    50        25    63    113    190    237    239
271    102    89    85    69    251        18    187    200    204    220    38        271    102    89    85    69    251
278    28    162    96    91    212        11    261    127    193    198    77        11    261    127    193    198    77
266    24    179    100    82    216        23    265    110    189    207    73        23    265    110    189    207    73
#37
吹水佬2022-02-15 19:23
回复 36楼 fdxxhjc
示例代码只用了一个bh字段,其他字段随便都可以。
加个类似bh的字段就是了
思路对了就OK,不可能照抄
#38
fdxxhjc2022-02-15 19:33
回复 37楼 吹水佬
先生我代码这样修改了下(先试验只是1列),但提示说数据类型不对

ACTIVATE SCREEN
CLEAR
CLOSE DATABASES
SET SAFETY OFF
CREATE CURSOR ta (bh I, 列1 n(4))
CREATE CURSOR tb (bh I, 列1 n(4))
FOR i=1 TO 9
    INSERT INTO ta VALUES (i,"列"+TRANSFORM(i))
    INSERT INTO tb VALUES (i,"列"+TRANSFORM(i))
ENDFOR
SELECT ta
INDEX on bh TAG ta_bh
RAND(-1)
SELECT tb
INDEX ON RAND() TAG tb_r
SET RELATION TO bh INTO "ta"
ran = INT((RECCOUNT("tb")-1)*RAND()+1)
? " 取 "+TRANSFORM(ran)+" 条记录"
i = 0
SCAN FOR i<ran
    ? bh,列1
    i = i+1
    SCATTER MEMVAR
    SELECT ta
    GATHER MEMVAR
ENDSCAN
SELECT * FROM ta
COPY  TO  替换结果记录表.dbf
#39
吹水佬2022-02-15 19:50
回复 38楼 fdxxhjc
CREATE CURSOR tb (bh I, 列1 n(4))
    INSERT INTO ta VALUES (i,"列"+TRANSFORM(i))

列1 n(4) ........... 是什么类型?
"列"+TRANSFORM(i) .. 是什么类型?
#40
fdxxhjc2022-02-15 20:06
回复 39楼 吹水佬
先生 列1 n(4) ........... 是数值类型
"列"+TRANSFORM(i) .. 这个是何类型我确不准了,对不起
#41
吹水佬2022-02-15 20:15
回复 40楼 fdxxhjc
"列"+TRANSFORM(i) 是字符串
字符串是什么类型:
?VARTYPE("列"+TRANSFORM(i))
#42
fdxxhjc2022-02-15 20:33
回复 41楼 吹水佬
哦,我再翻下书,对不起
#43
吹水佬2022-02-15 21:02
不好意思,原来是有真实表格,开头没留意,刚看到。
实测了一下
只有本站会员才能查看附件,请 登录

程序代码:
SELECT RECNO() bh, * FROM a INTO TABLE 交换结果记录表
SELECT RECNO() bh, * FROM b INTO CURSOR tb
SELECT 交换结果记录表
INDEX on bh TAG ta_bh
RAND(-1)
SELECT tb
INDEX ON RAND() TAG tb_r
SET RELATION TO bh INTO "交换结果记录表"
ran = INT((RECCOUNT("tb")-1)*RAND()+1)
? " 取 "+TRANSFORM(ran)+" 条记录"
SCAN NEXT ran
    ? bh
    SCATTER MEMVAR
    SELECT 交换结果记录表
    GATHER MEMVAR
ENDSCAN
SELECT 交换结果记录表
BROWSE
CLOSE TABLES ALL
#44
fdxxhjc2022-02-15 21:19
回复 43楼 吹水佬
先生太客气了,谢谢先生,已成功,我再对照书本细学下,诚挚的感谢
1