-
Notifications
You must be signed in to change notification settings - Fork 7
/
ch09-02.htm
6058 lines (3722 loc) · 375 KB
/
ch09-02.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>ch09-02</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
<script src="thumbnailviewer.js" type="text/javascript">
/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
</script> </head>
<body>
<div class="os1">9.2 顺序容器:QVector、QStack </div>
<br>
本节介绍剩下的两种顺序容器,向量 QVector 和 栈 QStack。向量 QVector
本质就是封装好的数组,向量的相邻元素在内存里是连续存储的,可以用数组下标访问,其读取和修改元素的操作是非常快的,与C++数组是一样的,但是随机插入元素和随机删除
元素需要大量腾挪后面的元素,所以不同的数据结构有不同的应用场景。如果读写操作频繁,但是随机增删操作比较少,那么这种场景就很适合向量。栈 QStack
是向量的派生类,继承了向量的全部功能,并添加了几个进栈、出栈的操作函数。<br>
<br>
本节内容安排:9.2.1 小节介绍向量 QVector 的功能,通过城市经纬度查询示例学习向量和嵌套容器的使用; 9.2.2 小节简单介绍栈
QStack 的功能,利用栈实现树形结构的遍历; 9.2.3 小节对五种顺序容器进行对比归纳,测试它们常用操作函数的执行效率。 <br>
<br>
<div class="os2">9.2.1 向量 QVector </div>
<br>
向量 QVector 就是封装好的数组,不仅支持 C++ 基本类型和 Qt
常见的数据类型,对于自定义类型也可以支持,如果希望保存大量的自定义类型对象并且能高效读写,就可以使用向量。Qt 容器还可以进行嵌套,比如下面代码就定义了
10*10 的二维向量:<br>
<div class="code"> QVector<
QVector<int> > vc;<br>
vc.resize(10);<br>
for(int i=0; i<10; i++)<br>
{<br>
vc[i].resize(10);<br>
}</div>
容器嵌套定义时,要注意在两层尖括号中间加空格,避免编译器把容器嵌套识别为流操作符。二维向量分配存储空间完成后就和二维数组用起来差不多。<b>向 量
QVector 与之前介绍的列表 QList 类似,只能存储值类型,即类型 T 必须支持默认构造函数、复制构造函数和等于号赋值函数。</b><br>
下面我们分类列举向 量模板类的功能函数:<br>
(1)构造函数<br>
<div class="code">QVector() //默认构造函数<br>
QVector(int size) //初始化 size 个元素的向量,元素初始值为类型 T
默认构造函数生成的值<br>
QVector(int size, const T & value) //用 value 值初始化
size 个元素的向量<br>
QVector(const QVector<T> & other) //复制构造函数<br>
QVector(QVector<T> && other) //移动构造函数<br>
QVector(std::initializer_list<T> args) //初始化列表构造函数<br>
~QVector() //析构函数</div>
第一个是默认构造函数,用于支持容器嵌套;<br>
第二个是构造 size 个元素的向量,每个元素初始值都是类型 T 默认构造函数设定的数值;<br>
第三个是构造 size 个元素的向量,并且每个元素都设置为 value 值;<br>
第四个是复制构造函数,将参数 other 里的元素都复制一份给新向量;<br>
第五个是移动构造函数,将参数 other 里的元素都移动到新向量里面,旧的 other 向量内容清空;<br>
第六个是初始化列表构造,支持根据类似 {1, 2, 3} 的初始化表构造新的向量;<br>
第七个是析构函数。<br>
需要注意第二和第三个构造函数,不仅仅是分配空间,而且填充了 size 个元素。<br>
<br>
(2)添加和分配空间函数<br>
将元素添加到向量头部、尾部的函数如下:<br>
<div class="code">void append(const T &
value) //将 value 添加到向量尾部<br>
void push_back(const T & value) //将 value
添加到向量尾部,STL风格<br>
void prepend(const T & value) //将
value 添加到向量头部<br>
void push_front(const T & value)//将 value
添加到向量头部,STL风格</div>
通常情况下,添加到向量尾部的开销比较小,而添加到头部意味着将向量原有的元素都向后平移,开销会很大。<br>
在向量中间位置插入一个元素或多个元素的函数如下:<br>
<div class="code">void insert(int i, const T & value)<br>
void insert(int i, int count, const T & value)</div>
第一个 insert() 是将一个 value 插入到序号 i 的位置,原本序号 i 以及后面的元素都平移,然后把 value 复制到序号 i 的位置。<br>
第二个 insert() 是将 count 个 value 值插入到序号 i 的位置,插入后从序号 i 到 i+count-1 序号都是等于 value
值的元素。<br>
insert() 函数支持的最大序号是 size() ,即元素总数,如果 i 等于 size() ,那么元素添加到向量末尾。如果 i
>size() ,程序会因为访问越界而崩溃。其他带序号 i 的函数,序号范围仅支持 0 ~ size()-1 ,只有 insert()
例外多支持一个添加到末尾。
<div style="color: red;"><b> 这里着重说明一下,向量为了提升访问效率,绝大部分带序号 i
的函数都不做越界判断,一旦出现越界程序就会崩溃,这点与普通数组是一样的!<br>
</b></div>
向量还支持自动填充元素:<br>
<div class="code">QVector<T> & fill(const T
& value, int size = -1)</div>
如果 fill() 第二个参数为默认的 -1,那么向量内所有元素都被填充为数值 value;<br>
如果第二个参数不是 -1,那么向量首先进行增长或裁剪,使得元素个数正好是 size 计数,然后将向量的 size 个元素数值设置为 value。<br>
<br>
获取向量的元素数量(即向量的长度、尺寸)函数如下:<br>
<div class="code">int count() const<br>
int size() const<br>
int length() const</div>
这三个函数是一样的,都是向量里的元素计数。如果希望改变向量元素的计数(长度、尺寸),可以用下面的重置尺寸函数:<br>
<div class="code">void resize(int size)</div>
重置向量尺寸后,向量的元素就变成 参数里的 size 个,如果元素变多,那么使用类型 T
的默认构造函数设置末尾的新元素,如果元素变少了,那么后面的元素会被删除掉。<br>
resize()
函数会直接影响向量里的元素个数,如果希望在不影响元素个数的情况下扩容,那么也有相应的函数。下面三个函数就是用于设置、获取容量,但不影响元素个数:<br>
<div class="code">void reserve(int size) //为 size
个元素分配空间,但是不增加任何新元素,向量的元素总数不变<br>
int capacity() const
//查询向量内部的存储容量,容量一般大于等于 count()<br>
void squeeze()
//释放不需要的额外容量,与 reserve() 函数功能相反</div>
<b>这三个容量操作的函数不会影响向量中的元素总数,也不改变任何元素的数值。</b>reserve( size ) 是为
size 个数元素提前分配空间,如果参数里的个数小于向量原本的尺寸,那么该函数不执行任何操作,不会截断向量;如果参数 size
大于向量原本的尺寸,那么提前分配空间。reserve( size ) 仅仅是提前分配空间,不会为向量添加新元素,向量的元素计数
count () 是不变的。<br>
capacity() 用于查询向量的存储空间,一般大于等于 count() 。<br>
squeeze() 用于释放额外空间,与 reserve( size ) 的操作正好相反。<br>
<br>
这里需要特别注意 resize( size) 和 reserve( size ) 的区别:<br>
resize( size ) 直接影响元素个数,如果参数里数值比旧的尺寸大,那么扩容并添加新元素,向量元素总数变为参数指定的个数;<br>
如果resize( size ) 参数里的数值比旧的尺寸小,那么对向量进行截断,只保留参数里指定个数的元素。<br>
而 reserve( size )
无论参数里数值是什么,都不会改变向量元素的个数,也不会修改任何元素的数值,仅仅用于提前分配空间,但不会添加任何的新元素。如果在添加元素之前,提前知道向量大概的元
素总数,那么用 reserve( size ) 提前分配空间可以避免添加新元素过程中的向量自动扩容操作。<br>
<br>
为区别这两个函数,读者可以测试下面的错误代码:<br>
<div class="code"> QVector<int> va = {1, 2, 3};<br>
va.reserve(10);<br>
va[4] = 1; //!!!错误示范</div>
reserve(10) 会为向量扩容,但没有新增元素,上面最后一句 va[4] = 1 是数组越界,会导致程序崩溃。<br>
如果使用 resize( 10 ),那么上面代码就是合法的,因为 resize( 10 ) 会为向量新添加 7 个元素到后面,va[4] 就不会越界。<br>
<br>
(3)移除和删除函数<br>
在调用移除和删除函数之前,一定要确保向量非空,用 ! empty() 或 ! isEmpty() 判断,不能对着没有元素的向量进行删除元素。<br>
如果希望从向量卸下元素并返回该元素值,使用 take**() 函数:<br>
<div class="code">T takeAt(int i) //卸下序号 i 位置元素,并返回该元素<br>
T takeFirst() //卸下向量的头部元素,并返回该元素<br>
T takeLast() //卸下向量的尾部元素,并返回该元素</div>
不返回元素,直接删除元素的函数如下:<br>
<div class="code">void remove(int
i) //删除序号 i 位置元素<br>
void removeAt(int i) //删除序号 i 位置元素 <br>
void remove(int i, int count) //从序号 i 位置开始删除参数里 count
个数的元素<br>
void removeFirst() //删除头部元素<br>
void pop_front() //删除头部元素,STL风格<br>
void removeLast() //删除尾部元素<br>
void pop_back() //删除尾部元素,STL风格</div>
向量从尾部删除元素的效率高,但是删除头部或中间的元素,意味着将后面大批量元素往前复制腾挪,效率就比较低了。 take**() 函数与
remove**() 函数效率差不多,仅仅是多个返回值。<br>
如果希望删除匹配的一个或多个元素,使用下面的函数:<br>
<div class="code">bool removeOne(const T &
t) //如果向量里存在等于 t 的元素就删除并返回 true,否则找不到返回 false<br>
int removeAll(const T & t)
//删除向量中所有等于 t 的元素,并返回删除的数量</div>
removeOne( t ) 和 removeAll( t ) 函数需要元素类型 T 支持双等号比较函数 operator==() 。<br>
如果需要清空向量,删除所有元素,那么使用如下函数:<br>
<div class="code">void clear()<br>
</div>
<br>
(4)访问和查询函数<br>
访问指定序号 i 元素的函数如下:<br>
<div class="code">const T & at(int i)
const //返回序号 i 元素的常量引用,效率最高,但是不做越界判断!<br>
T value(int i) const<br>
T value(int i, const T & defaultValue) const</div>
at( i ) 的函数效率最高,但是它不检查数组越界,一旦越界程序就会崩溃,对于该函数必须确保 0 <= i < size() 。<br>
两个 value( ) 函数都会检查参数的序号是否越界,第一个 value( i ) 如果序号越界,返回类型 T 默认构造函数设置的元素数值,第二个
value( i, defaultValue ) 如果发生序号 i 越界,那么返回参数里指定的数值 defaultValue
。如果不发生越界,两个 value() 函数都返回正常的序号 i 位置元素数值。<br>
快速获取向量头部、尾部元素的函数如下:<br>
<div class="code">T & first()
//头部元素的读写引用<br>
const T & first() const //头部元素的只读引
用<br>
T & front() //头部元素的读写引用,STL风格<br>
const_reference front() const
//头部元素的只读引用,STL风格<br>
T & last() //尾部元素的读写引用<br>
const T & last() const //尾部元素的只读引用<br>
reference back() //尾部元素的读写引用,STL风格<br>
const_reference back() const
//尾部元素的只读引用,STL风格</div>
STL风格函数返回值的 reference 是类型定义,等同 T & ; const_reference 也是类型定义,等同
const T & 。<br>
判断向量是否为空的函数如下:<br>
<div class="code">bool empty() const
//判断向量是否为空,STL风格<br>
bool isEmpty() const //判断向量是否为空</div>
查询向量里是否包含 value 数值或查询有几个等于 value 数值的元素,使用下面的函数:<br>
<div class="code">bool contains(const T & value)
const //查询向量是否包含等于 value 数值的元素,有就返回 true,没有就返回 false<br>
int count(const T & value) const
//查询向量包含几个等于 value 数值的元素,有就返回个数,没有就返回 0</div>
凡是参数里带 value 的查询函数、移除或删除函数,都需要元素类型 T 支持双等号比较函数 operator==() 。<br>
如果需要查询等于 value 数值的元素的序号,使用下面两个函数:<br>
<div class="code">int indexOf(const T & value, int
from = 0) const //从前到后查询,从 from 序号开始查找等于 value
的元素序号,找不到时返回 -1<br>
int lastIndexOf(const T & value, int from = -1)
const //从后向前查询,从 from 序号开始倒着查找等于 value 的元素序号,找不到就返回 -1</div>
indexOf() 是按照序号从小到大查找,lastIndexOf() 是反过来,按照序号从大到小来查找,这两个函数如果找不到匹配的元素,就会返回
-1,要注意返回值的判断。<br>
查询头部和尾部是否等于某数值的快捷函数如下:<br>
<div class="code">bool startsWith(const T & value)
const //查询头部元素是否等于 value<br>
bool endsWith(const T & value)
const //查询尾部元素是否等于 value</div>
向量类还有特殊的函数,可以直接获取内部的连续存储空间指针:<br>
<div class="code">T * data()
//获取向量内部存储空间的读写指针,可以修改元素值<br>
const T * data() const
//获取向量内部存储空间的只读指针<br>
const T * constData() const //获取向量内部存储空间的只读指针 </div>
data() 和 constData() 返回值就是向量里真实的数组指针,如果读者希望自己直接用指针操作各个元素,就可以用这三个函数。<br>
一般是不建议直接调用这三个函数,因为如果处理不当就容易出现越界,而且不能直接为存储空间扩容。<br>
<br>
(5)获取子序列、替换和交换函数<br>
如果希望从向量复制出来一个子序列的向量,那么使用如下函数:<br>
<div class="code">QVector<T> mid(int pos, int length
= -1) const //从序号 pos 开始复制 length 个数的元素到新向量,返回新向量</div>
mid() 函数专门提取子序列向量,从 pos 开始复制 length 个数的元素到新向量里,返回新向量。如果 length 为 -1
或超出原向量的界限,那么从 pos 开始的所有元素都会复制到新向量里。<br>
修改序号 i 位置元素数值的函数如下:<br>
<div class="code">void replace(int i, const T & value)</div>
注意序号 i 不能越界,必须合法,即 0 <= i < size() 。<br>
如果希望与其他向量交换所有的元素,使用下面函数:<br>
<div class="code">void swap(QVector<T> & other)</div>
swap() 函数执行效率非常高,并且不会失败。<br>
<br>
(6)运算符函数<br>
对于运算符函数,我们以下面三个向量来举例说明:<br>
<div class="code"> QVector<int> va = {1, 2, 3};<br>
QVector<int> vb = {4, 5, 6};<br>
QVector<int> vc;</div>
运算符使用示范如下表所示:<br>
<br>
<table class="tabel">
<tbody>
<tr class="d1">
<td style="width: 400px;" align="center"><b>运算符函数</b></td>
<td style="width: 200px;" align="center"><span style="font-weight: bold;">举
例</span></td>
<td align="center"><b> 描述</b></td>
</tr>
<tr>
<td>bool operator!=(const QVector<T> & other) const</td>
<td> va != vb;</td>
<td> va 和 vb 两个向量有元素不同,结果为 true。 </td>
</tr>
<tr class="d1">
<td>QVector<T> operator+(const QVector<T> & other)
const</td>
<td> vc = va + vb;</td>
<td> va 和 vb 复制拼接后生成新向量,赋值给 vc。</td>
</tr>
<tr>
<td>QVector<T> & operator+=(const QVector<T> &
other)</td>
<td> va += vb;</td>
<td> 复制 vb 所有元素追加到 va 末尾。 </td>
</tr>
<tr class="d1">
<td>QVector<T> & operator+=(const T & value)</td>
<td style="height: 16px;"> va += 100 ;</td>
<td> 添加一个元素 100 到 va 末尾。 </td>
</tr>
<tr>
<td>QVector<T> & operator<<(const QVector<T>
& other)</td>
<td> va << vb;</td>
<td style="height: 16px;"> 复制 vb 所有元素追加到 va 末尾。 </td>
</tr>
<tr class="d1">
<td>QVector<T> & operator<<(const T & value)</td>
<td> va << 100;</td>
<td> 添加一个元素 100 到 va 末尾。 </td>
</tr>
<tr>
<td>QVector<T> & operator=(const QVector<T> &
other)</td>
<td> vc = va;</td>
<td> va 所有元素都复制一份给 vc,va本身不变。二者相等。 </td>
</tr>
<tr class="d1">
<td>QVector<T> operator=(QVector<T> && other)
//移动赋值</td>
<td> vc = std::move(va) ; </td>
<td> va 所有元素都移动给 vc, va本身被清空。 </td>
</tr>
<tr>
<td>bool operator==(const QVector<T> & other) const</td>
<td> va == vb;</td>
<td> va 和 vb 有元素不同,结果为 false。<br>
只有两个向量的所有元素相等并且顺序一样,它们才能算相等。</td>
</tr>
<tr class="d1">
<td>T & operator[](int i)</td>
<td> va[0] = 100;<br>
</td>
<td style="height: 16px;"> 获取序号为 i 的元素的读写引用,可修改向量元素。 </td>
</tr>
<tr>
<td>const T & operator[](int i) const</td>
<td> qDebug()<<va[0] ;</td>
<td> 获取序号为 i 的元素的只读引用。 </td>
</tr>
</tbody>
</table>
<br>
上表双等号函数判断的条件非常严苛,只有在两个向量的元素完全相等、顺序一样、元素个数一样的情况下,两个向量才会相等。<br>
对于带序号 i 的中括号函数(数组下标访问函数),要求序号必须满足 0 <= i < size(),如果序号不合法,出现越界访
问,程序就会崩溃。<br>
<br>
(7)迭代器函数<br>
为了兼容 STL,向量也是一样带有迭代器的,向量内部自带的迭代器类型如下:<br>
<div class="code">typedef iterator
//读写迭代器,STL风格<br>
typedef Iterator //读写迭代器,Qt 风格<br>
typedef const_iterator //只读迭代器,STL风格<br>
typedef ConstIterator //只读迭代器,Qt风格</div>
迭代器使用示范如下:<br>
<div class="code"> QVector<int> va = {1, 2, 3};<br>
QVector<int>::iterator it = va.begin();<br>
while( it != va.end() )<br>
{<br>
qDebug()<< (*it);<br>
it++; //下一个<br>
}</div>
获取向量头部、尾部后面假想元素迭代器的函数如下:<br>
<div class="code">iterator begin()
//指向头部的读写迭代器<br>
const_iterator begin() const
//指向头部的只读迭代器<br>
const_iterator cbegin() const
//指向头部的只读迭代器<br>
const_iterator constBegin() const //指向头部的只读迭代器,Qt
风格<br>
iterator end() //指向尾部后面假想元素的读写迭代器<br>
const_iterator end() const
//指向尾部后面假想元素的只读迭代器<br>
const_iterator cend() const
//指向尾部后面假想元素的只读迭代器<br>
const_iterator constEnd() const
//指向尾部后面假想元素的只读迭代器,Qt风格</div>
注意 *end() 返回的迭代器通常只用于做不等于判断,它指向的东西根本不存在, *end() 仅用于越界判断。<br>
虽然获取头部、尾部迭代器的函数多,其实功能类似,起了一堆名字是方便兼容 STL 风格函数命名。<br>
利用迭代器插入一个或多个元素的函数如下:<br>
<div class="code">iterator insert(iterator before, const T
& value) //在 before 指向的元素前面插入元素 value<br>
iterator insert(iterator before, int count, const T
& value) //在 before 指向的元素前面插入 count 个数的 value 元素</div>
insert() 迭代器函数返回值就会自动指向新插入的元素,如果插入多个元素,就指向新插入的第一个元素,参数里迭代器 before
不能再使用。一定要使用返回值里的迭代器进行后续遍历操作。<br>
利用迭代器删除元素的函数如下:<br>
<div class="code">iterator erase(iterator
pos) //删除 pos 指向的一个元素,返回值指向下一个元素,可能指向尾部后面假想元素<br>
iterator erase(iterator begin, iterator end) //删除从参数
begin 到参数 end 的元素,但是参数 end 元素不删除,总是返回参数 end<br>
</div>
第一个 erase() 删除参数 pos 指向的一个元素,返回下一个元素的迭代器,返回值可能是指向尾部后面假想元素。<br>
第二个 erase() 删除从参数 begin 到参数 end 的多个元素,但是参数 end 指向的元素不删除,该函数总是返回参数 end 迭代器。<br>
一般向量很少使用迭代器访问,因为使用数组下标形式更直接而且高效。<br>
<br>
(8)容器类型转换函数<br>
如果希望将向量转为列表或标准库的向量,使用下面函数:<br>
<div class="code">QList<T> toList()
const //转为 Qt 列表<br>
std::vector<T> toStdVector()
const //转为标准库的向量</div>
向量类还提供了静态成员函数,实现将参数里类型转为向量类型,返回值就是新的向量:<br>
<div class="code"> QVector<T> fromList(const
QList<T> & list) //将参数里的列表转为向量,返回值是新向量<br>
QVector<T> fromStdVector(const
std::vector<T> & vector) //将参数里的标准库向量转为 Qt 向量</div>
列表的好处是针对头部插入元素有优化,向量头部插入元素需要大量元素向后复制腾挪,向量头部元素的增删不如列表效率高。<br>
<br>
(9)其他内容<br>
向量类还附带了两个友元函数,是流操作符重载函数,支持数据流的输出、输入,<br>
<div class="code">QDataStream &
operator<<(QDataStream & out, const QVector<T> &
vector) //输出<br>
QDataStream & operator>>(QDataStream & in,
QVector<T> & vector) //输入</div>
这些流操作符函数正常运行的前提是元素类型 T 必须支持数据流的输入和输出。C++ 基本类型和 Qt 常见数据类型都支持,如果是自定义类型那么必须类似重
载 operator<<() 和 operator>>() 函数。<br>
<br>
向量与列表一样都支持排序函数:<br>
<div class="code">void qSort(Container & container) //排序 <br>
void qStableSort(Container & container) //稳定排序</div>
排序函数要求容器的元素类型 T 必须支持小于号函数 operator<(),用于比较元素大小。Qt
调用的小于号函数原型是两个参数的全局 operator<() 函数,不是成员函数,应该在类外面声明并定义下面的小于号函数:<br>
<div class="code">bool operator< ( const T &t1, const T &t2
)</div>
一般要将该函数声明为 T 类型的友元函数,方便访问私有变量。<br>
<br>
最后我们梳理一下,如果自定义类型希望能够完美地和 QVector 配合使用,那么需求如下:<br>
① 必须是可赋值类型,需要默认构造函数、复制构造函数、赋值函数 operator=() ;<br>
② 如果希望支持查询函数,需要双等号函数 operator==();<br>
③ 如果希望支持排序函数,需要全局小于号函数 operator< ( const T &t1, const T &t2
) ;<br>
④ 如果希望支持 QDataStream 数据流输入输出,那么添加友元函数 operator<<() 和
operator>>() 。 <br>
第一条是必须实现的函数,后面三条是建议实现的函数。<br>
<br>
对于自定义类型支持 QVector ,可以参考 9.1.1 小节的示例,因为 QList 和 QVector 对自定义类型的要求是一样的。<br>
本小节示例实现一个查询城市经纬度的功能,并示范嵌套容器的使用。在开始例子之前,请读者到下面网址下载一个文本文件:<br>
<a href="https://qtguide.ustclug.org/QtProjects/ch09/cityposition/position.txt">
https://qtguide.ustclug.org/QtProjects/ch09/cityposition/position.txt</a>
<br>
position.txt 保存了全国各省市的经纬度,里面的内容举例如下:<br>
<div class="code">安徽省 合肥市 31 50 117 15<br>
安徽省 安庆市 30 32 117 3<br>
安徽省 池州市 30 40 117 29<br>
安徽省 六安市 31 46 116 30</div>
每行文本分别是省名称、市名称、纬度的度和分、经度的度和分。比如合肥市就是纬度 31°50′,经度 117°15′
。所有的行都是这种格式,方便我们用程序加载。<br>
下载 position.txt 之后,我们打开 QtCreator,新建一个 Qt Widgets Application
项目,在新建项目的向导里填写:<br>
①项目名称 cityposition,创建路径 D:\QtProjects\ch09,点击下一步;<br>
②套件选择里面选择全部套件,点击下一步;<br>
③基类选择 QWidget,点击下一步;<br>
④项目管理不修改,点击完成。<br>
新建项目之后,我们把 position.txt 复制到项目文件夹 D:\QtProjects\ch09\cityposition 里面。<br>
我们点击 QtCreator 菜单“文件”-> “新建文件或项目”,进入新建对话框,<br>
在对话框左边选择“文件和类”里的“Qt”栏目,然后在对话框中间选择“Qt Resource File”:<br>
<center> <img src="images/ch09/ch09-02-01.png" alt="ui" width="600"></center>
点击下面 Choose... 按钮,进入文件名称路径设置页面,名称里填写 res.qrc :<br>
<center> <img src="images/ch09/ch09-02-02.png" alt="ui" width="600"></center>
点击下一步按钮,进入项目管理界面:<br>
<center> <img src="images/ch09/ch09-02-03.png" alt="ui" width="600"></center>
项目管理界面不需要修改,直接点击完成,这样就添加了 res.qrc 文件到项目里了。<br>
添加 res.qrc 文件之后,自动进入该文件编辑界面,我们在 QtCreator 左侧项目管理栏,右击 res.qrc 文件,<br>
在右键菜单选择“添加现有文件...”:<br>
<center> <img src="images/ch09/ch09-02-04.png" alt="ui" width="600"></center>
在弹出的添加现有文件对话框里面,选择 position.txt 添加到资源文件里面:<br>
<center> <img src="images/ch09/ch09-02-05.png" alt="ui" width="600"></center>
点击上面对话框的打开按钮,然后我们就可以看到该记事本文件成功添加到资源文件里了:<br>
<center> <img src="images/ch09/ch09-02-06.png" alt="ui" width="600"></center>
我们保存该资源文件,然后就可以关闭它了,将 position.txt 添加到资源文件里,项目编译之后就会将该文件嵌入到生成的可执行目标程序里,程序里可以
使用下面路径读取该文件:<br>
:/position.txt<br>
<br>
接下来我们编辑 widget.ui 界面文件,参考下图拖入控件:<br>
<center> <img src="images/ch09/ch09-02-07.png" alt="ui" width="800"></center>
第一行是两个标签和两个组合框,标签文本分别为“省份”、“市县”,组合框对象名分别为
comboBoxProvince、comboBoxCity,这里需要将两个组合框的 sizePolicy 的水平策略都修改为 Expanding
自动拉伸模式,方便与第二行的单行编辑器对齐。<br>
第二行是两个标签和两个单行编辑器,标签文本分别为“经度”、“纬度”,单行编辑器对象名为
lineEditLongitude、lineEditLatitude。<br>
窗口整体使用一个栅格布局,窗口大小 400*200 。<br>
这个界面用组合框存储全国所有的省份和市县,当省份改变时,自动加载该省的市县;用户选择了省份和市县之后,下面单行编辑器自动显示该市县的经纬度。
下面我们开始 编辑代码,首先是头文件 widget.h 的代码:<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>WIDGET_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGET_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QWidget></span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QVector></span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//省份变化时,自动加载该省的市县</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onProvinceIndexChange</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>index<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//市县变化时,自动显示市县的经纬度到编辑框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onCityIndexChange</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>index<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//保存省份名称</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QVector</span><span
style=" color:#000000;"><</span><span style=" color:#800080;">QString</span><span
style=" color:#000000;">></span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vProvinces</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//二维向量保存市县名称</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QVector</span><span
style=" color:#000000;"><</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QVector</span><span style=" color:#000000;"><</span><span
style=" color:#800080;">QString</span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vCities</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//二维向量保存市县的经度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QVector</span><span
style=" color:#000000;"><</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QVector</span><span style=" color:#000000;"><</span><span
style=" color:#808000;">double</span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLongitudes</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//二维向量保存市县的纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QVector</span><span
style=" color:#000000;"><</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QVector</span><span style=" color:#000000;"><</span><span
style=" color:#808000;">double</span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">></span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLatitudes</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//从</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">position.txt</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">加载各省市及其经纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">loadPositions</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGET_H</span></pre>
</div>
该文件添加了向量模板类的头文件引用。Widget 类声明里的私有槽函数都是手动添加的,onProvinceIndexChange(int) 用于关联省份组合框的序号变化信号,onCityIndexChange(int) 用于关联市县组合框的序号变化信号,当用户选择省份时自动更新该省的市县,用户选择市县时,自动显示该市县的经纬度到编辑框。<br>类的私有变量里,添加了一维字符串向量 m_vProvinces ,保存省份的名称列表;<br>添加了二维向量 m_vCities 保存市县名称, m_vLongitudes 保存市县经度,m_vLatitudes 保存市县纬度,二维向量定义时要注意在两层尖括号中间加空格,防止编译器将二维向量的尖括号识别为流操作符。这里的二维向量,第一维是省份的序号,第二维是该省市县的序号。<br>最后的私有函数 loadPositions() 在窗口构建时从资源文件加载全国所有的省份和市县信息。<br><br>下面分段编辑源文件 widget.cpp 的代码,首先是头文件包含、构造函数、析构函数:<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"widget.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widget.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QDebug></span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QFile></span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QTextStream>//文本流</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">Widget</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置编辑框为只读</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">lineEditLongitude</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setReadOnly</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">true</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">lineEditLatitude</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setReadOnly</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">true</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//从资源文件</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">position.txt</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">读取省市经纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">loadPositions</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//关联信号,省份组合框序号变化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">connect</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">ui</span><span style=" color:#000000;">-></span><span
style=" color:#800000;">comboBoxProvince</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SIGNAL</span><span
style=" color:#000000;">(</span>currentIndexChanged<span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#000000;">)),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">this</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SLOT</span><span
style=" color:#000000;">(</span>onProvinceIndexChange<span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#000000;">))</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//市县组合框序号变化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">connect</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">ui</span><span style=" color:#000000;">-></span><span
style=" color:#800000;">comboBoxCity</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SIGNAL</span><span
style=" color:#000000;">(</span>currentIndexChanged<span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#000000;">)),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">this</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SLOT</span><span
style=" color:#000000;">(</span>onCityIndexChange<span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#000000;">))</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">Widget</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
该文件添加了调试打印类、文件类和文本流的头文件包含。<br>构造函数里先将经度、纬度编辑框设置为只读,防止显示市县经纬度后被用户修改,因为市县经纬度是固定值。<br>然后调用 loadPositions() 加载全国所有省份、市县的经纬度信息。<br>加载经纬度信息之后,关联省份组合框的序号变化信号到槽函数 onProvinceIndexChange(int);<br>关联市县组合框的序号变化信号到槽函数 onCityIndexChange(int) 。<br>构造函数里先加载经纬度信息,后关联信号到槽函数,是避免添加省份或市县组合框条目时触发序号变化信号,因为数据没加载完,如果冒然触发序号变化关联的槽函数,槽函数容易出现越界访问或者读取不了经纬度。<br>析构函数是默认代码,没有修改。<br>
<br>下面手动编辑加载全国省份和市县经纬度信息的函数:<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//从资源文件</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">position.txt</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">读取省市经纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">loadPositions</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打开资源里的文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileIn</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">":/position.txt"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//资源文件打开一般不需要判断,只要文件名对就可以打开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">fileIn</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">ReadOnly</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//定义文本流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span style=" color:#000000;">(&</span><span
style=" color:#000000;">fileIn</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setCodec</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"UTF-8"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//该文件使用</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">UTF-8</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">文本编码</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//为二维向量的第一维省份添加元素空间,这样后面才能使用中括号访问</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vCities</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">resize</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">40</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#008000;">//全国省份目前只有34个,分配</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">40</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">保证够用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLongitudes</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">resize</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">40</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLatitudes</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">resize</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">40</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//定义变量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strProvBefore</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//保存前一行记录的省份,用于判断是否应该添加新省份了</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strProvCur</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//当前行加载的省份</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strCity</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//当前行加载的市县</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLonD</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//经度的度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLonM</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//经度的分</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLatD</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//纬度的度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLatM</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//纬度的分</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//记录当前省份的序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nProvIndex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">-</span><span style=" color:#000080;">1</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//开始读取,文本流不结束就一直读</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">while</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#000000;">tsIn</span><span style=" color:#000000;">.</span><span style=" color:#000000;">atEnd</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//依次读取省份、市县、纬度的度和分、经度的度和分</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">strProvCur</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">strCity</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">>></span><span
style=" color:#000000;">nLatD</span><span style=" color:#000000;">>></span><span
style=" color:#000000;">nLatM</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">>></span><span
style=" color:#000000;">nLonD</span><span style=" color:#000000;">>></span><span
style=" color:#000000;">nLonM</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//如果当前省份不等于前一个省份,需要新增省份</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strProvBefore</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">strProvCur</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nProvIndex</span><span
style=" color:#000000;">++;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//省份序号增加</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strProvBefore</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">strProvCur</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//保存省份,用于下一行记录判断</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加新的省份</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vProvinces</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">strProvCur</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//一维向量不需要提前分配,自动分配空间并追加元素</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//无论省份新旧,都要添加市县、经度、纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加市县</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vCities</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">nProvIndex</span><span
style=" color:#000000;">]</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;"><<</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strCity</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加纬度,转为浮点数的度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLatitudes</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">nProvIndex</span><span
style=" color:#000000;">]</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;"><<</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLatD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">+</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#000000;">)</span><span style=" color:#000000;">nLatM</span><span
style=" color:#000000;">/</span><span style=" color:#000080;">60.0</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加经度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vLongitudes</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">nProvIndex</span><span
style=" color:#000000;">]</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;"><<</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nLonD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">+</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#000000;">)</span><span style=" color:#000000;">nLonM</span><span
style=" color:#000000;">/</span><span style=" color:#000080;">60.0</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//从文件加载完毕</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//省份组合框的内容是固定的,直接添加</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;"><</span><span style=" color:#800000;">m_vProvinces</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">comboBoxProvince</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vProvinces</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置省份序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">comboBoxProvince</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setCurrentIndex</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//手动调用省份变化槽函数,显示第一个省份的所有市县到组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onProvinceIndexChange</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//手动调用市县变化槽函数,显示经纬度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onCityIndexChange</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打印省份计数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"加载完毕,省份计数:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_vProvinces</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">count</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
该函数首先定义文件输入对象 fileIn,文件名为资源文件 ":/position.txt" ,然后直接打开该文件,对于资源里的文件,我们不需要判断是否打开成功,因为该文件总是存在的,并且格式已知,也不需要进行输入异常判断,因为我们程序员可以控制 ":/position.txt" 文件的内容,不行可以在程序编译之前纠正该文件内容。程序运行时资源里的文件都是只读的,所以不需要考虑数据源污染问题。<br>打开文件之后,以该文件对象定义输入文本流,设置文本编码格式 UTF-8 。<br>然后提前为三个二维向量增加了第一维的 40 个元素,全国目前省份只有 34 个,添加 40 个已经很富余了,保证后面用中括号访问时不会越界。 <br>
接下来定义了三个字符串,strProvBefore 保存前一行记录的省份,strProvCur 保存当前行的省份,strCity 保存当前的市县。当上一行的省份不同于当前行的省份时,我们就知道需要为一维向量 m_vProvinces 添加新的省份名称,省份序号也就加一,然后新省份的市县、经纬度就保存到二维向量的新序号记录行里面。 <br>
然后定义了经度的度、分,纬度的度、分变量,方便从文件读取市县的经纬度。<br>我们定义省份序号 nProvIndex 从 -1 开始,然后开始用 while 循环加载 position.txt 文件:<br>我们从文件当前行里面加载省份名称、市县名称、纬度的度值和分值、经度的度值和分值;<br>然后判断 strProvBefore 是否与 strProvCur 不一样:<br> 如果不一样就将省份序号加一,保存当前行的省份给 strProvBefore 用于下轮循环判断,将新省份名称添加到向量 m_vProvinces。<br>因为 nProvIndex 总是与当前的省份序号同步,所以无论新旧省份,都将市县的名称添加到 m_vCities[nProvIndex] 记录行里面,计算纬度浮点数值保存到 m_vLatitudes[nProvIndex] 记录行,计算经度浮点数值保存到 m_vLongitudes[nProvIndex] 记录行。<br> 当文件所有内容读取完毕时,结束循环。<br>这样全国所有省份市县信息都加载到四个向量里面了。<br>我们将省份名称循环添加为省份组合框的条目,将当前省份条目序号设为 0 ;<br>然后手动调用了省份序号变化关联的槽函数和市县序号变化的槽函数,用于填充市县组合框,并显示第一个市县的经纬度到编辑框。<br>
最后打印了实际加载的省份计数。<br><br>下面我们编辑关联省份组合框序号变化信号的槽函数:<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//根据省份序号变化,自动加载该省的市县</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">onProvinceIndexChange</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">index</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">index</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;"><</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">return</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//序号不合法,不处理</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//清空市县组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">comboBoxCity</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//根据省份序号,加载该省的市县到市县组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//该省的市县计数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_vCities</span><span style=" color:#000000;">[</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">count</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;"><</span><span style=" color:#000000;">nCount</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//第一维是省序号,第二维是市县序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">comboBoxCity</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_vCities</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">index</span><span
style=" color:#000000;">][</span><span style=" color:#000000;">i</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置默认市县的序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-></span><span style=" color:#800000;">comboBoxCity</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">setCurrentIndex</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>