Ada 语言学习(3)复合类型数据——Array

article/2025/9/24 11:36:34

文章目录

  • Array
    • 数据类型声明
    • 数组索引
    • 数组范围
    • 数组复制
    • 数组初始化
      • 直接赋值
      • 通过拷贝赋值
        • 不同索引范围但长度相等
        • 非指定类型边界收缩
    • 多维数组
    • 数组遍历
    • 数组切片
    • 访问和动态检查
      • 直接访问
      • 动态检查
    • 数组字面量 Array literal
    • 数组拼接
      • 两个数组拼接
      • 数组和单个值拼接
    • Array Equality(数组相等判定)
    • 数组遍历
      • 通过索引遍历(循环变量I不可更改)
      • 直接遍历所有的对象 object(对象可以被更改)
    • 二维数组
    • 高维数组
  • Definite / indefinite types (定义类型和非定义类型)
    • String 字符串
    • 数组的默认值
    • Definite type (定义类型)
    • Indefinite type(非定义类型)
      • unconstrained type(未指定类型)
      • Generic type(泛型类型)
  • 练习

Array

数据类型声明

  • 在 Ada 中,可以使用 type 关键字声明数组类型,指定元素类型和维度 。例如:
    在这里插入图片描述
type IntArray is array(1 .. 10) of Integer;

数组索引

  • 数组中的索引是从 1 开始,默认情况下不支持从 0 开始,可以使用索引来访问数组的特定元素:IntArray(3) 表示 IntArray 数组的第 3 个元素。

数组范围

  • 数组的范围由其类型的索引范围定义。例如,IntArray 的索引范围是从 110

数组复制

在这里插入图片描述

  • 这里将 A2 的值复制给了 A1 但是, A1, A2 仍然是独立的两个数组, 在其他的编程语言中(有的是指向引用,但是 ada 不会这样,所有的 ada 复制都是 deep copy 操作)
  • 但是要求这两个数组的类型长度 必须是一致的。
    在这里插入图片描述
  • 在上面的复制中, A2 的内容复制给了 A1 ,因为虽然他们的索引范围不同,但是会对应复制,例如 A2(11) = A1(1) 以此类推
  • 但是 A3 的长度和 A1 不同,因此无法复制

数组初始化

  • 可以使用 := 运算符在声明数组时对其进行初始化,或者可以使用赋值语句逐个赋值。例如:

直接赋值

```ada
IntArray: IntArray := (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
```

通过拷贝赋值

不同索引范围但长度相等

在这里插入图片描述

  • 在上面的例子中,我们使用 非定义类型 的方式声明了一个类型 T,这是一个数组类型,但是 T 的范围我们并不知道,只知道 T 中的元素都是整数而已。
  • 同时 A1 数组是 T 类型,并且包含了 10 个元素,索引范围是 1-10
  • A2 数组也是 T 类型,并且包含了 10 个元素,索引范围是 11-20, 但是她复制了 A1 的值,虽然现在我们并不知道 A1 的值是什么。
  • 如果后面我们对 A1 的值进行修改,那么 A2 的值实际上并不会改变,因为 ada 的赋值是深拷贝
type T is array (Integer range <>) of Integer;
A1: T (1 .. 10);
A2: T (1 .. 10);-- Fill A1 with some data.
for I in A1'Range loopA1(I) := I;
end loop;-- Copy A1 to A2.
A2 := A1;-- Change the value of A1(1)
A1(1) := 99;-- Now, A1(1) is 99, but A2(1) is still 1.

非指定类型边界收缩

在这里插入图片描述

  • 如上图,如果 A1 是一个 T,并且 A1 数组的元素索引就是从 1-10,而这时,A2 复制了 A1 的值,虽然 A2 仍然是 T 类型(非定义类型),但是她也会复制 A1 的索引范围。

多维数组

  • Ada 支持多维数组的声明和操作。可以通过指定多个维度来声明多维数组,例如:
type Matrix is array(1 .. 3, 1 .. 3) of Integer;

数组遍历

可以使用 for 循环结构遍历数组中的元素。例如:

for i in IntArray'Range loopPut_Line(Integer'Image(IntArray(i)));
end loop;

数组切片

  • 可以使用数组切片(array slice)来访问数组的子集。切片允许通过指定范围来提取数组的一部分。例如:

    SubArray: IntArray := IntArray(3 .. 6);
    
    • SubArray 将包含 IntArray 数组索引为 3 到 6 的元素。
      在这里插入图片描述
  • 虽然在 copy 的时候,不同长度的 array 不能进行 copy 行为,但是我们可以 copy 其中的一部分。

  • 上图中 A2 的前 10 个元素复制给了 A1,然后 A12-4 索引的元素又获得了 A25-7 索引元素的值。

访问和动态检查

直接访问

  • ada 中的数组中的元素可以被直接访问:
    在这里插入图片描述
    • 这里定义了一个数组 V,他的索引范围是 1..10, 因此可以直接取 V(1)

动态检查

  • 数组会被进行动态检查:
    在这里插入图片描述
    • 因为这里的 V(0) 中的 0 并没有被覆盖在定义的索引范围中,因此这样是一种越界行为

数组字面量 Array literal

  • 可以使用 array literals(数组字面量) 来初始化数组或者赋值给数组。数组字面量是由一系列逗号分隔的值,这些值被括在括号内。

  • 例如,可以使用数组字面量来初始化一个数组:

    type T is array (1 .. 5) of Integer;
    A : T := (1, 2, 3, 4, 5); -- array literal
    
  • 在这个例子中,(1, 2, 3, 4, 5) 是一个数组字面量,用来初始化数组 A。

  • 也可以使用数组字面量来给数组赋值:

    A := (6, 7, 8, 9, 10); -- array literal
    
  • 此外,Ada 语言还提供了 others 关键字来初始化或赋值数组中剩余的所有元素:

    A := (1, 2, others => 3); -- array literal with 'others'
    

在这里插入图片描述

  • 需要特别注意的是:在使用数组字面量进行初始化的时候,要注意分清楚下面的情况:
    在这里插入图片描述
    • V1 虽然是一个 非指定类型 的数组,但是由于其索引就只有 3 个,因此我们可以使用 others 来为 V1 中的所有的元素赋值
    • 但是 V2 没有指定元素的个数,而直接使用 others 这种情况在 ada 中是不被允许的

数组拼接

两个数组拼接

在这里插入图片描述

  • 通过 & 符号,可以直接拼接两个一维的数组

那现在就有疑问了,假设 A1 的索引范围是 (1..10)A2
的索引范围是 (8..12),那么 A3 作为 A1 & A2 的结果,索引范围应该会是什么样子?

  • 其实是这个完全不需要担心,因为再给 A3 赋值之前,我们需要先定义 A3 的索引,例如下面的代码:
type T is array (Integer range <>) of Integer;
A1: T (1 .. 10);
A2: T (8 .. 12);
A3: T (1 .. 15);  -- The range of A3 should be the total length of A1 and A2.-- Fill A1 and A2 with some data.
for I in A1'Range loopA1(I) := I;
end loop;for I in A2'Range loopA2(I) := I;
end loop;-- Concatenate A1 and A2.
A3 := A1 & A2;
  • 可以看到,其实我们只需要关注 A3 的元素个数即可,而不用担心元素的索引。

数组和单个值拼接

在这里插入图片描述

Array Equality(数组相等判定)

在这里插入图片描述

  • 数组的 size 需要相等
  • 数组中的每个元素都必须相等
  • 数组的类型必须相等
  • 数组的索引范围不影响数组的相等判定
    type T is array (Integer range <>) of Integer;A1 : T (1 .. 3) := (1, 2, 3);
    A2 : T (2 .. 4) := (1, 2, 3);-- This will print "Equal"
    if A1 = A2 thenPut_Line("Equal");
    elsePut_Line("Not Equal");
    end if;
    

数组遍历

通过索引遍历(循环变量I不可更改)

在这里插入图片描述

  • 使用 A 数组的 Range 属性来得到所有的索引,并进行遍历
  • 但是使用的循环变量 I 是不可以被修改的

直接遍历所有的对象 object(对象可以被更改)

在这里插入图片描述

  • 使用 of 关键字
  • 如果我在循环中更改了 V (如上图)那么这个 V 就会切实地被更改成 0

二维数组

在这里插入图片描述

高维数组

type T1 is array (Integer range <>) of Integer;
type T2 is array (Integer range <>) of T1 (0 .. 2); -- specify the range of T1 hereV: T2 (1 .. 10);
beginV (1)(0) := 0; -- Now this is OK.
end;
  • 在这段代码中,V 是一个 T2 类型的数组,其中每个元素都是一个 T1 类型的数组。T1 类型的数组的范围是 0 .. 2,因此 V (1)(0) := 0; 这行代码现在是正确的,它将 V 的第1个元素(一个 T1 类型的数组)的第0个元素设置为 0
  • 在定义一个多维数组的后面的维度的时候,需要将前面的维度都定义好

所以这是一个几行几列的数组?

  • 类型 T2 定义为 type T2 is array (Integer range <>) of T1 (0 .. 2);,其中每个元素都是一个 T1 类型的数组(这里,T1 的范围是 0 .. 2,因此 T1 类型的数组有3个元素)。

因此,当你声明 V: T2 (1 .. 10); 时,你正在创建一个有10行、每行3列的二维数组。具体来说,这是一个10行3列的数组。

对于一个 ada 中的 2维数组 V, 那么 V(0)(1) 和 V(0,1) 是相等的么

  • 是的,V(0)(1)V(0,1) 在 Ada 中是等价的。它们都是用来访问二维数组 V 中的特定元素。具体来说,它们都访问的是 V 的第 0 行第 1 列的元素。V(0,1) 的写法可能在阅读和理解代码时更清晰,因为它明确表示了这是一个二维索引,而 V(0)(1) 则可能需要更多的解析才能理解。

Definite / indefinite types (定义类型和非定义类型)

在这里插入图片描述

String 字符串

  • 在 Ada 语言中,字符串被视为一种特殊类型的数组,其索引是 Positive 范围的整数(也就是从 1 开始的整数),而元素类型是 Character。这意味着可以像处理其他数组一样来处理字符串,比如用下标来访问特定字符,或者用 'Length 属性来获取字符串的长度。
S : String := "Hello, world!";
Put_Line("The first character is: " & S(1));
Put_Line("The length of the string is: " & Integer'Image(S'Length));
  • 此外,还要注意的是 Ada 中的字符串是不可变的。也就是说,一旦一个字符串被创建,就不能修改它的内容。不过,可以通过字符串拼接操作(用 & 运算符)来创建新的字符串。比如:
S1 : String := "Hello";
S2 : String := ", world!";
S3 : String := S1 & S2;  -- S3 is now "Hello, world!"
  • 但如果你需要一个可变的字符串,你可以使用 Unbounded_String 类型,这是 Ada 的标准库 Ada.Strings.Unbounded 中提供的一种类型。Unbounded_String 类型的对象可以通过 To_Unbounded_String 函数从普通字符串创建,可以用 To_String 函数转回普通字符串,也可以用 &= 运算符来修改内容。
    在这里插入图片描述

数组的默认值

  • 在 Ada 语言中,当你声明一个数组但不给它赋初始值时,数组的元素将不会被自动初始化为默认值。相反,数组元素的初始值是不确定的。这与许多其他编程语言有所不同,这些语言可能会给新的数组元素自动赋予默认值。

  • 如果你想给数组的所有元素赋予相同的初始值,你可以使用 (others => value) 语法,其中 value 是你想要赋予的初始值。例如,以下代码将创建一个浮点数数组 A,并将其所有元素初始化为 0.0

    type T is array (Integer range <>) of Float;
    A : T (1 .. 10) := (others => 0.0);
    
  • 请注意,(others => value) 只能用于初始化数组。如果你在后续的代码中想要修改数组的所有元素,你需要使用一个循环来遍历数组并为每个元素赋值。

  • 当然也可以强迫数组拥有默认值:
    在这里插入图片描述

  • 为了性能考虑,上述代码一般不会使用

Definite type (定义类型)

  • 定义类型是通过使用 type 关键字显式定义的类型。它们是具体的类型,具有明确定义的结构和语义。定义类型可以是基本类型(如 Integer、Float、Boolean)或派生类型(通过限定范围、枚举、数组等方式创建的类型)。例如:

    type MyInteger is range 1 .. 10;
    

Indefinite type(非定义类型)

  • 非定义类型是一种未具体定义的类型,它们是一种抽象概念,没有具体的结构和语义。它们通常用作模板或占位符,在需要时可以被实例化为具体的类型

  • Ada 中的非定义类型包括未指定类型(unconstrained type)和泛型类型(generic type)。

unconstrained type(未指定类型)

  • 未指定类型:未指定类型是一种可以通过参数传递进行实例化的占位符类型。它们在声明时不指定范围或大小,需要在使用时提供具体的值或范围。

      ```adatype MyUnconstrainedArray is array (Positive range <>) of Integer;```
    
    • 在上述示例中,MyUnconstrainedArray 是一个未指定类型的数组类型,可以根据实际需要传递不同的范围进行实例化。
    • Positive 被用作 array 的索引范围。通过使用 Positive range <>,表示数组的索引可以是任意的正整数范围。
    • 例如,可以将 MyUnconstrainedArray 实例化为索引范围为 1 到 100 的数组:
      MyArray : MyUnconstrainedArray(1 .. 100);
      
    • 使用 Positive 子类型作为数组索引范围的好处是,它可以确保索引始终是正整数,符合实际需求,并提供了类型安全性。

Generic type(泛型类型)

  • 泛型类型是一种可以根据参数化的类型或值来创建通用代码模板的类型。它们在定义时可以指定一个或多个参数,然后在使用时提供具体的参数值来实例化
    例如:

    generictype ElementType is private;
    package Stack istype Stack_Type is private;procedure Push(Item : in ElementType);function Pop return ElementType;...
    end Stack;
    
  • 在上述示例中,Stack 是一个泛型包(generic package),使用了一个参数 ElementType。这个参数 ElementType 可以是任意类型,它在使用时可以通过传递具体的类型来实例化。也就是说,可以使用不同的类型来创建不同类型的堆栈。

  • 例如,可以使用 Stack 泛型包创建一个整数类型的堆栈:

    package Integer_Stack is new Stack(ElementType => Integer);
    

非定义类型 (indefinite types) 的灵活性和可扩展性使得它们在处理通用数据结构和算法时非常有用。通过使用非定义类型,可以编写更通用和可复用的代码,适应不同的数据类型和需求。

练习

在这里插入图片描述
在这里插入图片描述

  • 这种情况的类型定义没问题,但是没有限定数组的大小,因此会报错

在这里插入图片描述

  • 从结构上来说,他们都是长度为 3 的数组,
  • 但是他们不是同一个 type,虽然他们的 type 定义看起来完全一样的,但是却并不符合数组复制的要求

在这里插入图片描述

  • 在 Ada 中,数组的默认索引起始值是 1,而不是像一些其他语言(如 C 或 Python)那样是 0。因此,V (0) 是无效的,会导致范围错误。

  • 在代码中创建了一个名为 V 的数组,类型为 T,并将其初始化为 (1, 2, 3)。这将创建一个包含三个元素的数组,这些元素的索引是 1、23

在这里插入图片描述
在这里插入图片描述

  • 开始 X=10 ,即,V1 创建出来的时候具备 10 个元素
  • 虽然后来 X 的值修改为 100,但是 V1 已经固定了,
  • 因此可以直接将 V2 复制给 V1

在这里插入图片描述

  • 从定义中我们只知道 V1 的索引范围是 1-3 并且给定了 3 个值
  • 同时我们知道 V2 的值也是 (10, 20, 30)
  • 但是定义中并没有明确指定 V2 的 boundary,也就是索引范围,因此我们并不能够盲目推测
  • 也就是当 I=1 时,我们无法确定 V2 的值,对 V2来说,因为没有给定 boundary,所以 V2 的第一个索引其实是 -2^16(也就是 integer 类型中最小的数)

在这里插入图片描述

  • 这里是通过 definite 的方式来定义数组, Tboundary 固定为 1-10,因此不能被随意改变,如果这里使用的是 indefinite 的形式,例如 type T is array(Integer range<>) of Integer 那么在定义 V 的时候是可以更改 boundary

在这里插入图片描述

  • 在 Ada 中,String 是一种预定义的数组类型,其元素类型为 Character。在 Ada 中,没有直接创建字符串数组的方式。通常,你会创建一个数组,它的元素类型是固定长度的字符串,或者是 Unbounded_String
  • 同时,如果创建一个字符串,那么对于索引类型 Integer range <> 也要更改为 Positive range <> 因为在 Ada 中,String 是一种特定类型的数组,其索引类型是 Positive

如果你想创建一个可以存储任意长度字符串的数组,你可以使用 Ada.Strings.Unbounded.Unbounded_String 类型。这个类型可以存储任意长度的字符串,并提供了一些实用的操作。以下是一个示例:

	with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;type String_Array is array (Integer range <>) of Unbounded_String;
  • 如果你只需要处理固定长度的字符串,你可以这样定义:
	type String_Array is array (Integer range <>) of String (1 .. Max_Length);
  • 在这个例子中,Max_Length 是一个你预先定义的常量,表示字符串的最大长度。这种方式的限制是所有的字符串都必须有相同的长度,而且这个长度是在编译时决定的。

在这里插入图片描述

  • 在 Ada 中,Default_Component_Value 属性应用于类型标签,并将默认值分配给类型的每个实例的组件。但是,此默认值必须是编译时可以确定的值,不能是变量。以上代码中,尝试将变量 X 作为默认组件值,这是不允许的。

  • 如果希望每个数组元素的默认值为 0,那么应该直接使用数值 0,而不是变量 X。下面是修改后的代码:

    type T is array (Integer range <>) of Integer with Default Component Value => 0;
    V: T(1 .. 10);
    
  • 如果 X 的值在编译时可以确定,那么也可以使用常量来替代变量,如下:

    X: constant Integer := 0;
    type T is array (Integer range <>) of Integer with Default Component Value => X;
    V: T(1 .. 10);
    

http://chatgpt.dhexx.cn/article/WKQCuxr9.shtml

相关文章

【历史上的今天】12 月 10 日:世界上第一位程序员诞生;Ada 语言发布;第一人称射击游戏的开拓者

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2021 年 12 月 10 日&#xff0c;在 120 年前的今天&#xff0c;瑞典国王和挪威诺贝尔基金会首次颁发了诺贝尔奖。根据诺贝尔的遗嘱&#xff1a;“诺贝尔奖每年发给那些…

Ada 程序设计语言(The Ada Programming Language)[第一集]

Ada 程序设计语言(The Ada Programming Language)[第一集]- - 版权&#xff08;Copyright) 《Ada 程序设计语言》的版权隶属于网站 VenusIC&#xff0c;允许任何用户翻阅、传播、批评等等&#xff0c;只要读者想的出的行为&#xff0c;都…

Ada语言学习(1)Basic Knowledge

文章目录 说在前头命名注释数字变量变量类型signed integersEnumerationsFloating Points 类型重用&#xff08;继承&#xff09;类型转换 运算符属性&#xff08;Attributes&#xff09;练习 说在前头 本系列教程将会通过提问的方式来完成整个学习过程&#xff0c;因为当你能…

Ada程序设计语言初识

Ada曾是美国国防部指定的唯一一款可用于军用系统开发的语言&#xff0c;旨在整合美军事系统中运行着450多种不同的程序设计语言&#xff0c;她是迄今为止最复杂、最完备的软件工具。开发始于1975年&#xff0c;最早是针对嵌入式和实时系统设计的&#xff0c;1983年发布。其命名…

Ada语言-标识符和注释

标识符 1,ada标识符是不区分大小写的&#xff0c;如下所示它们指向的都是同一个标识符&#xff1a; 2, 全以字母开头&#xff0c;如下&#xff1a; 3,以字母或数字结尾,如下&#xff1a; 4,可以‘包含’不连续的下划线&#xff0c;如下&#xff1a; 注释 注意&#xff1a;在Ad…

ada语言第一步从Hello World开始

打开GNAT软件&#xff0c;在界面中选择“Greate new project” > “Basic” > “simple Ada Project”&#xff0c;再“NEXT”&#xff0c;填写创建工程文件路径、工程名称和main文件名称信息之后&#xff0c;就创建一个新的“控制台”工程文件。 之后&#xff0c;你会看…

Ada 编程语言

以下内容摘自wiki&#xff0c;http://zh.wikipedia.org/wiki/Ada Ada&#xff0c;是一种程序设计语言。源于美国军方的一个计划&#xff0c;旨在整合美军系统中运行着上百种不同的程序设计语言编写的程序&#xff0c;命名是为了纪念爱达勒芙蕾丝而使用Ada。 目录 [隐藏] 1 重要…

Xshell6、xftp资源,舒服!!(自行下载)

还饱受xhell产品各种到期侵害的同志们&#xff0c;可以下载使用这版&#xff0c;本人已经用了将近两年半&#xff0c;不存在到期的问题。当然&#xff0c;如果你的机子之前就用了Xshell6且已经过期了。那就不用试了&#xff0c;基本也是没戏o_O&#xff0c;换别的版本的可用版吧…

xftp的免费下载和安装教程

下载 下载地址https://www.netsarang.com/en/all-downloads/ 2. 安装 按默认配置选项 下一步&#xff0c;下一步即可&#xff0c;文件路径根据自己需要修改

Xftp的下载和安装教程

在Windows系统下&#xff0c;如果想和Linux系统进行文件传输&#xff0c;可以使用Xftp 工具&#xff0c;本篇将介绍Xftp 6下载与安装的过程 软件下载地址:http://www.netsarang.com/download/software.html 点击免费授权页面 随便输入名字 但是邮箱地址一定要正确。可以根据需…

Xftp6下载

前面介绍了Xshell的下载&#xff0c;Xshell是一款能够直接操作linux的终端命令的软件&#xff0c;但是无法进行不同系统间文件的传输&#xff0c;而Xftp是一个功能强大的SFTP、FTP 文件传输软件&#xff0c;它能够快速的进行不同系统之间文件的传输。 懒的看下面的可以直接去我…

xftp7评估版安装使用

xftp7评估版安装使用 1、安装xftp72、配置xftp73、安装包xftp74、其他文件传输软件 之前文章介绍过 xshell7 评估版的安装过程&#xff0c;详见 xshell7评估版安装使用。 本文将介绍 xftp7 文件传输软件的安装使用过程&#xff08;常与xshell7 配套使用&#xff09;。 1、安装x…

Xshell|Xftp正版免费使用,再也不用辛辛苦苦破解了

Xshell正版免费&#xff0c;再也不用找破解版了&#xff01; 话不多说&#xff0c;先贴链接(直接点击)各位按需下载就可以了&#xff0c;亲测有效&#xff0c;感觉有用点个赞呗&#xff01; 当然也可以直接点击下方名字直接下载压缩包哦 【特别声明】此为教育版正版免费&#x…

xftp下载安装及简单使用

一、xftp简介 Xftp是一个功能强大的SFTP、FTP 文件传输软件。使用了 Xftp 以后&#xff0c;MS Windows 用户能安全地在 UNIX/Linux 和 Windows PC 之间传输文件。Xftp 能同时适应初级用户和高级用户的需要。它采用了标准的 Windows 风格的向导&#xff0c;它简单的界面能与其他…

2021年了!!Xftp新手的下载和安装教程(超详细),以及演示了远程登录和远程文件传输

超级快的&#xff0c;一会就下好了 官网链接&#xff1a;https://www.netsarang.com/zh/xshell/ 1、点下载 出现这个&#xff0c;点进去 填写下面的信息&#xff0c;下载的链接就会发到邮箱里&#xff0c; 点这个邮箱里的链接就会帮你下载了 一、Xftp的安装以及远程登录进行远…

Xshell/Xftp个人完全免费版

很多人在找 Xshell 或 Xftp 的破解版&#xff0c;完全没必要 因为官方已经针对个人用户&#xff0c;提供了完全免费版本 官方免费版下载步骤如下&#xff1a; 1、进入官网活动页面&#xff1a;Xshell Xftp官网 2.填写邮箱、姓名&#xff08;随便填&#xff09;&#xff0c;需要…

xftp的简单使用

xftp的简单使用 1.下载并安装Xftp工具。打开Xftp工具&#xff0c;点击“新建”。 2.在“新建会话属性”中选择“名称”为主机命名&#xff0c;在“主机”栏输入主机IP&#xff0c;“协议”和“端口号”使用sftp和22【注意默认协议是ftp&#xff0c;此处要改为sftp】&#x…

Xshell/Xftp个人完全免费版(功能与收费版完全相同)

如果你还在找 Xshell 或 Xftp 的破解版&#xff0c;完全没必要&#xff0c;因为官方已经针对个人用户&#xff0c;提供了完全免费版本&#xff0c;功能和商业收费版 完全一样&#xff01; 官方免费版下载步骤如下&#xff1a; 此版本和收费版唯一的不同就是一个窗口最多只能同时…

Xftp的下载和安装(超详细)

Xftp的下载和安装&#xff08;超详细&#xff09;

Xftp的介绍及下载安装教程

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。转载请注明出处&#xff1a;https://blog.csdn.net/weixin_44222492/article/details/98309601 。 1. Xftp介绍 能和电脑传输的软件&#xff08;文件传输工具&#xff09;&#xff1a;Xftp &#x…