Swift函数函数声明、函数参数和类型

函数是执行特定任务的代码自包含块。给定一个函数名称标识,当执行其任务时就可以用这个标识来进行"调用"。

Swift的统一的功能语法足够灵活来表达任何东西,无论是甚至没有参数名称的简单的C风格的函数表达式,还是需要为每个本地参数和外部参数设置复杂名称的Objective-C语言风格的函数。参数提供默认值,以简化函数调用,并通过设置在输入输出参数,在函数执行完成时修改传递的变量。

Swift中的每个函数都有一个类型,包括函数的参数类型和返回类型。您可以方便的使用此类型像任何其他类型一样,这使得它很容易将函数作为参数传递给其他函数,甚至从函数中返回函数类型。函数也可以写在其他函数中来封装一个嵌套函数用以范围内有用的功能。

函数的声明与调用

当你定义一个函数时,你可以为其定义一个或多个命名,定义类型值作为函数的输入(称为参数),当该函数完成时将传回输出定义的类型(称为作为它的返回类型)。

每一个函数都有一个函数名,用来描述了函数执行的任务。要使用一个函数的功能时,你通过使用它的名称进行“调用”,并通过它的输入值(称为参数)来匹配函数的参数类型。一个函数的提供的参数必须始终以相同的顺序来作为函数参数列表。

例如在下面的例子中被调用的函数greetingForPerson,像它描述的那样 -- 它需要一个人的名字作为输入并返回一句问候给那个人。
   
   
  1. func sayHello(personName: String) -> String {
  2. let greeting = "Hello," + personName + "!"
  3. return greeting
  4. }
所有这些信息都汇总到函数的定义中,并以func关键字为前缀。您指定的函数的返回类型是以箭头->(一个连字符后跟一个右尖括号)以及随后类型的名称作为返回的。

该定义描述了函数的作用是什么,它期望接收什么,以及当它完成返回的结果是什么。该定义很容易让该函数可以让你在代码的其他地方以清晰、明确的方式来调用:
   
   
  1. println(sayHello("Anna"))
  2. // prints "Hello,Anna!"
  3. println(sayHello("Brian"))
  4. // prints "Hello,Brian!"
通过括号内String类型参数值调用sayHello的函数,如的sayHello("Anna")。由于该函数返回一个字符串值,sayHello的可以被包裹在一个println函数调用中来打印字符串,看看它的返回值,如上图所示。

在sayHello的函数体开始定义了一个新的名为greeting的String常量,并将其设置加上personName个人姓名组成一句简单的问候消息。然后这个问候函数以关键字return来传回。只要问候函数被调用时,函数执行完毕是就会返回问候语的当前值。

你可以通过不同的输入值多次调用sayHello的函数。上面的例子显示了如果它以"Anna"为输入值,以"Brian"为输入值会发生什么。函数的返回在每种情况下都是量身定制的问候。

为了简化这个函数的主体,结合消息创建和return语句用一行来表示:
   
   
  1. func sayHello(personName: String) -> String {
  2. return "Hello again," + personName + "!"
  3. }
  4. println(sayHello("Anna"))
  5. // prints "Hello again,Anna!"

函数的参数和返回值

在swift中函数的参数和返回值是非常具有灵活性的。你可以定义任何东西无论是一个简单的仅仅有一个未命名的参数的函数还是那种具有丰富的参数名称和不同的参数选项的复杂函数。

多输入参数

函数可以有多个输入参数,把他们写到函数的括号内,并用逗号加以分隔。下面这个函数设置了一个开始和结束索引的一个半开区间,用来计算在范围内有多少元素包含:
   
   
  1. func halfOpenRangeLength(start: Int,end: Int) -> Int {
  2. return end - start
  3. }
  4. println(halfOpenRangeLength(1,10))
  5. // prints "9"

无参函数

函数并没有要求一定要定义的输入参数。下面就一个没有输入参数的函数,任何时候调用时它总是返回相同的字符串消息:
   
   
  1. func sayHelloWorld() -> String {
  2. return "hello,world"
  3. }
  4. println(sayHelloWorld())
  5. // prints "hello,world"
该函数的定义在函数的名称后还需要括号,即使它不带任何参数。当函数被调用时函数名称也要跟着一对空括号。

没有返回值的函数

函数也不需要定义一个返回类型。这里有一个版本的sayHello的函数,称为waveGoodbye,它会输出自己的字符串值而不是函数返回:
   
   
  1. func sayGoodbye(personName: String) {
  2. println("Goodbye,\(personName)!")
  3. }
  4. sayGoodbye("Dave")
  5. // prints "Goodbye,Dave!"
因为它并不需要返回一个值,该函数的定义不包括返回箭头( - >)和返回类型。
提示:严格地说,sayGoodbye功能确实还返回一个值,即使没有返回值定义。函数没有定义返回类型但返 回了一个void返回类型的特殊值。它是一个简直是空的元组,实际上零个元素的元组,可以写为()。
当一个函数调用时它的返回值可以忽略不计:
   
   
  1. func printAndCount(stringToPrint: String) -> Int {
  2. println(stringToPrint)
  3. return countElements(stringToPrint)
  4. }
  5. func printWithoutCounting(stringToPrint: String) {
  6. printAndCount(stringToPrint)
  7. }
  8. printAndCount("hello,world")
  9. // prints "hello,world" and returns a value of 12
  10. printWithoutCounting("hello,world" but does not return a value
第一个函数printAndCount,打印了一个字符串,然后并以Int类型返回它的字符数。第二个函数printWithoutCounting,调用的第一个函数,但忽略它的返回值。当第二函数被调用时,字符串消息由第一函数打印了回来,去没有使用其返回值。
提示:返回值可以忽略不计,但对一个函数来说,它的返回值即便不使用还是一定会返回的。在函数体底部 返回时与定义的返回类型的函数不能相容时,如果试图这样做将导致一个编译时错误。

多返回值函数

你可以使用一个元组类型作为函数的返回类型返回一个有多个值组成的一个复合作为返回值。

下面的例子定义了一个名为count函数,用它计来算字符串中基于标准的美式英语中设定使用的元音、辅音以及字符的数量:
   
   
  1. func count(string: String) -> (vowels: Int,consonants: Int,others: Int) {
  2. var vowels = 0,consonants = 0,others = 0
  3. for character in string {
  4. switch String(character).lowercaseString {
  5. case "a","e","i","o","u":
  6. ++vowels
  7. case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
  8. ++consonants
  9. default:
  10. ++others
  11. }
  12. }
  13. return (vowels,consonants,others)
  14. }
您可以使用此计数函数来对任意字符串进行字符计数,并检索统计总数的元组三个指定Int值:
   
   
  1. let total = count("some arbitrary string!")
  2. println("\(total.vowels) vowels and \(total.consonants) consonants")
  3. // prints "6 vowels and 13 consonants"
需要注意的是在这一点上元组的成员不需要被命名在该该函数返回的元组中,因为他们的名字已经被指定为函数的返回类型的一部分。

函数参数名

所有上面的函数都为参数定义了参数名称:
   
   
  1. func someFunction(parameterName: Int) {
  2. // function body goes here,and can use parameterName
  3. // to refer to the argument value for that parameter
  4. }
然而,这些参数名的仅能在函数本身的主体内使用,在调用函数时,不能使用。这些类型的参数名称被称为本地的参数,因为它们只适用于函数体中使用。

外部参数名

有时当你调用一个函数将每个参数进行命名是非常有用的,以表明你传递给函数的每个参数的目的。

如果你希望用户函数调用你的函数时提供参数名称,除了设置本地地的参数名称,也要为每个参数定义外部参数名称。你写一个外部参数名称在它所支持的本地参数名称之前,之间用一个空格来分隔:
   
   
  1. func someFunction(externalParameterName localParameterName: Int) {
  2. // function body goes here,and can use localParameterName
  3. // to refer to the argument value for that parameter
  4. }
提示:如果您为参数提供一个外部参数名称,调用该函数时外部名称必须始终被使用。
作为一个例子,考虑下面的函数,它通过插入他们之间的第三个"joiner"字符串来连接两个字符串:
   
   
  1. func join(s1: String,s2: String,joiner: String) -> String {
  2. return s1 + joiner + s2
  3. }
当你调用这个函数,你传递给函数的三个字符串的目的就不是很清楚了:
   
   
  1. join("hello","world",",")
  2. // returns "hello,world"
为了使这些字符串值的目的更为清晰,为每个join函数参数定义外部参数名称:
   
   
  1. func join(string s1: String,toString s2: String,withJoiner joiner: String) -> String {
  2. return s1 + joiner + s2
  3. }
在这个版本的join函数中,第一个参数有一个外部名称string和一个本地名称s1;第二个参数有一个外部名称toString和一个本地名称s2;第三个参数有一个外部名称withJoiner和一个本地名称joiner。

现在,您可以使用这些外部参数名称调用清楚明确的调用该函数:
   
   
  1. join(string: "hello",toString: "world",withJoiner: ",world"
使用外部参数名称使join函数的第二个版本功能更富有表现力,用户习惯使用sentence-like的方式,同时还提供了一个可读的、意图明确的函数体。
提示:考虑到使用外部参数名称的初衷就是为了在别人第一次阅读你的代码时并不知道你函数参数的目的是什么。 但当函数调用时如果每个参数的目的是明确的和毫不含糊的,你并不需要指定外部参数名称。

外部参数名称速记

如果你想为一个函数参数提供一个外部参数名,然而本地参数名已经使用了一个合适的名称了,你不需要为该参数写相同的两次名称。取而代之的是,写一次名字,并用一个hash符号(#)作为名称的前缀。这告诉Swift使用该名称同时作为本地参数名称和外部参数名称。

这个例子定义了一个名为containsCharacter的函数,定义了两个参数的外部参数名称并通过放置一个散列标志在他们本地参数名称之前:
   
   
  1. func containsCharacter(#string: String,#characterToFind: Character) -> Bool {
  2. for character in string {
  3. if character == characterToFind { return true }
  4. }
  5. return false
  6. }
这个函数选择的参数名称清晰的、函数体极具可读性,使的该函数被调用时没有歧义:
   
   
  1. let containsAVee = containsCharacter(string: "aardvark",characterToFind: "v")
  2. // containsAVee equals true,because "aardvark" contains a "v"

参数的默认值

可以为任何参数设定默认值来作为函数的定义的一部分。如果默认值已经定义,调用函数时就可以省略该参数的传值。
提示:将使用默认值的参数放在函数的参数列表的末尾。这确保了所有调用函数的非默认参数使用相同的顺 序,并明确地表示在每种情况下相同的函数调用。
这里有一个版本,是早期的join函数,并为参数joiner设置了默认值:
   
   
  1. func join(string s1: String,withJoiner joiner: String = " ") -> String {
  2. return s1 + joiner + s2
  3. }
如果在join函数被调用时提供给joiner一个字符串值,该字符串是用来连接两个字符串,就跟以前一样:
   
   
  1. join(string: "hello",withJoiner: "-")
  2. // returns "hello-world"
但是,如果当函数被调用时提供了joiner的没有值,就会使用单个空格(" ")的默认值:
   
   
  1. join(string: "hello",toString: "world")
  2. // returns "hello world"

有默认值的外部名称参数

在大多数情况下,为所有参数提供一个外部带有默认值的参数的名称是非常有用的(因此要求)。这将确如果当函数被调用时提供的值时参数必须具有明确的目的。

为了使这个过程更容易,当你自己没有提供外部名称时,Swift自动为所有参数定义了缺省的参数外部名称。自动外部名称与本地名称相同,就好像你在你的代码中的本地名称之前写了一个hash符号。

这里有一个早期join函数版本,它不为任何参数提供的外部名称,但仍然提供了joiner参数的默认值:
   
   
  1. func join(s1: String,joiner: String = " ") -> String {
  2. return s1 + joiner + s2
  3. }
在这种情况下,Swift自动为一个具有默认值的参数提供了外部参数名称。调用函数时,为使得参数的目的明确、毫不含糊,因此必须提供外部名称:
   
   
  1. join("hello",joiner: "-")
  2. // returns "hello-world"
提示:你可以通过编写一个下划线(_)有选择进行这种行为,而不是一个明确的定义外部参数名称。然 而,在适当情况下有默认值的外部名称参数总是优先被使用。

可变参数

一个可变参数的参数接受零个或多个指定类型的值。当函数被调用时,您可以使用一个可变参数的参数来指定该参数可以传递不同数量的输入值。写可变参数的参数时,需要参数的类型名称后加上点字符(...)。

传递一个可变参数的参数的值时,函数体中是以提供适当类型的数组的形式存在。例如,一个可变参数的名称为numbers和类型为Double...在函数体内就作为名为numbers类型为Double[]的常量数组。

下面的示例计算任意长度的数字的算术平均值(也称为平均):
   
   
  1. func arithmeticMean(numbers: Double...) -> Double {
  2. var total: Double = 0
  3. for number in numbers {
  4. total += number
  5. }
  6. return total / Double(numbers.count)
  7. }
  8. arithmeticMean(1,2,3,4,5)
  9. // returns 3.0,which is the arithmetic mean of these five numbers
  10. arithmeticMean(3,8,19)
  11. // returns 10.0,which is the arithmetic mean of these three numbers
提示:函数可以最多有一个可变参数的参数,而且它必须出现在参数列表的最后以避免多参数函 数调用时出现歧义。如果函数有一个或多个参数使用默认值,并且还具有可变参数,将可变参数放在列表的 最末尾的所有默认值的参数之后。

常量参数和变量参数

函数参数的默认值都是常量。试图改变一个函数参数的值会让这个函数体内部产生一个编译时错误。这意味着您不能错误地改变参数的值。

但是,有时函数有一个参数的值的变量副本是非常有用的。您可以通过指定一个或多个参数作为变量参数,而不是避免在函数内部为自己定义一个新的变量。变量参数可以是变量而不是常量,并给函数中新修改的参数的值的提供一个副本。

在参数名称前用关键字var定义变量参数:
   
   
  1. func alignRight(var string: String,count: Int,pad: Character) -> String {
  2. let amountToPad = count - countElements(string)
  3. for _ in 1...amountToPad {
  4. string = pad + string
  5. }
  6. return string
  7. }
  8. let originalString = "hello"
  9. let paddedString = alignRight(originalString,10,"-")
  10. // paddedString is equal to "-----hello"
  11. // originalString is still equal to "hello"
这个例子定义了一个新函数叫做alignRight,它对准一个输入字符串,以一个较长的输出字符串。在左侧的空间中填充规定的字符。在该示例中,字符串"hello"被转换为字符串"-----hello"。

该alignRight函数把输入参数的字符串定义成了一个变量参数。这意味着字符串现在可以作为一个局部变量,用传入的字符串值初始化,并且可以在函数体中进行相应操作。

函数首先找出有多少字符需要被添加到左边让字符串以右对齐在整个字符串中。这个值存储在本地常量amountToPad中。该函数然后将填充字符的amountToPad个字符拷贝到现有的字符串的左边,并返回结果。整个过程使用字符串变量参数进行字符串操作。
提示:一个变量参数的变化没有超出了每个调用函数,所以对外部函数体是不可见的。变量参数只能存在于函数调用 的生命周期里。

输入-输出参数

可变参数,如上所述,只能在函数本身内改变。如果你想有一个函数来修改参数的值,并且想让这些变化要坚持在函数调用结束后,你就可以定义输入-输出参数来代替。

通过在其参数定义的开始添加inout关键字写用来标明输入-输出参数。一个在输入-输出参数都有一个传递给函数的值,由函数修改后,并从函数返回来替换原来的值。

参数列表中只可以传递一个变量作为一个in-out参数。不能传递一个常数或常值作为参数,因为常量和文字不能修改。你直接在变量名前放置一个连字符(&),当你把它作为一个参数传递给一个in-out参数,表明它可以通过该功能进行修改。
提示:in-out参数不能有默认值,可变参数的参数也不能被标记为inout。如果您标记参数为inout,它不能同时被标记为var或let。
这里的一个叫做swapTwoInts函数,它有两个称为a和b的输入-输出整数参数:
   
   
  1. func swapTwoInts(inout a: Int,inout b: Int) {
  2. let temporaryA = a
  3. a = b
  4. b = temporaryA
  5. }
swapTwoInts函数只是简单地交换a、b的值。该功能通过存储在一个临时常数称为temporaryA的值,指定b的值到a,然后分配temporaryA到b执行该交换。

您可以调用交换函数swapTwoInts来交换任何int类型的变量以交换它们的值。需要注意的是他们传递给swapTwoInts执行功能时,someInt和anotherInt名称前需要加上的前缀符号:
   
   
  1. var someInt = 3
  2. var anotherInt = 107
  3. swapTwoInts(&someInt,&anotherInt)
  4. println("someInt is now \(someInt),and anotherInt is now \(anotherInt)")
  5. // prints "someInt is now 107,and anotherInt is now 3"
上面的例子表明,someInt和anotherInt的原始值由swapTwoInts函数进行了修改,即使它们定义在函数定义之外。
提示:输入输出参数与从函数返回的值是不一样的。上述swapTwoInts例子没有定义返回类型或返回一个值,但它仍然会修改someInt和anotherInt的值。输入输出参数是一个函数的另一个影响函数体范围之外的方式。

函数类型

每一个函数都有特定的函数类型,可以充当参数类型和函数的返回类型。例如:
   
   
  1. func addTwoInts(a: Int,b: Int) -> Int {
  2. return a + b
  3. }
  4. func multiplyTwoInts(a: Int,b: Int) -> Int {
  5. return a * b
  6. }
这个例子中定义了两个简单的数学函数addTwoInts和multiplyTwoInts。每个函数接受两个int值,并返回一个int值,执行适当的数学运算并返回结果。

这两个函数的类型是(Int,Int)->Int。可以解读为:"这个函数类型,它有两个int型的参数,并返回一个int类型的值。"

下面是另一个例子,不带任何参数或返回值的函数:
   
   
  1. func printHelloWorld() {
  2. println("hello,world")
  3. }
这个函数的类型是()->(),或者"函数没有参数,并返回void。"函数不显式的指出一个返回值类型是void,在swift中相当于一个空元组,显示为()。

使用函数类型

在swift中您可以像任何其他类型一样的使用函数类型。例如,你可以定义一个常量或变量为一个函数类型,并指定适当的函数给该变量:
   
   
  1. var mathFunction: (Int,Int) -> Int = addTwoInts
可以解读为:"定义一个名为mathFunction变量,该变量的类型为'一个函数,它接受两个int值,并返回一个int值。'设置这个新的变量来引用名为addTwoInts功能。"

该addTwoInts函数具有与mathFunction相同类型的变量,所以这个赋值在能通过swift的类型检查。

现在你可以调用指定的函数名称为mathFunction:
   
   
  1. println("Result: \(mathFunction(2,3))")
  2. // prints "Result: 5"
不同的函数相同的匹配类型可以分配给相同的变量,也同样的适用于非函数性类型:
   
   
  1. mathFunction = multiplyTwoInts
  2. println("Result: \(mathFunction(2,3))")
  3. // prints "Result: 6"
与其他类型一样,你可以把它迅速推断成函数类型当你为常量或变量分配一个函数时:
   
   
  1. let anotherMathFunction = addTwoInts
  2. // anotherMathFunction is inferred to be of type (Int,Int) -> Int

函数类型的参数

您可以使用一个函数类型,如(Int,Int)->Int作为另一个函数的参数类型。这使你预留了一个函数的某些方面的函数实现,让调用者提供的函数时被调用。

下面就以打印上面的数学函数的结果为例:
   
   
  1. func printMathResult(mathFunction: (Int,Int) -> Int,a: Int,b: Int) {
  2. println("Result: \(mathFunction(a,b))")
  3. }
  4. printMathResult(addTwoInts,5)
  5. // prints "Result: 8"
这个例子中定义了一个名为printMathResult函数,它有三个参数。第一个参数名为mathFunction,类型为(Int,Int)->Int。您可以传入符合的任何函数类型作为此函数的第一个参数。第二和第三个参数a、b都是int类型。被用作用于提供数学函数的两个输入值。

当printMathResult被调用时,它传递addTwoInt函数,以及整数值3和5。它调用的值3和5所提供的功能,并打印8的结果。

printMathResult的作用是调用一个适当类型的数学函数并打印相应结果。那是什么功能的实现其实并不重要,你只要给以正确的类型匹配就行。这使printMathResult以调用者类型安全的方式转换了函数的功能。

函数类型的返回值

您可以使用一个函数类型作为另一个函数的返回类型。返回的函数-(>)即你的返回箭头后,立即写一个完整的函数类型就做到这一点。

下面的例子定义了两个简单的函数调用stepForward和stepBackward。该stepForward函数返回一个值高于其输入值,而stepBackward函数返回一个值低于其输入值。这两个函数都有一个相同的类型(Int) -> Int:
   
   
  1. func stepForward(input: Int) -> Int {
  2. return input + 1
  3. }
  4. func stepBackward(input: Int) -> Int {
  5. return input - 1
  6. }
这里有一个chooseStepFunction函数,它的返回类型是"函数类型(Int) -> Int"。chooseStepFunction返回一个基于布尔参数的stepBackward或stepForward函数类型:
   
   
  1. func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
  2. return backwards ? stepBackward : stepForward
  3. }
您现在可以使用chooseStepFunction获取一个函数,可能是加一函数或另一个:
   
   
  1. var currentValue = 3
  2. let moveNearerToZero = chooseStepFunction(currentValue > 0)
  3. // moveNearerToZero now refers to the stepBackward() function
前面的例子可以判断正负的步骤决定是否需要移动一个名为使得currentValue变量逐步接近零。currentValue初始值是3,这意味着当前值>0,则返回true,chooseStepFunction返回stepBackward函数。返回函数的引用存储在一个称为moveNearerToZero常量里。
如今moveNearerToZero执行了正确的功能,就可以用来计数到零:
   
   
  1. println("Counting to zero:")
  2. // Counting to zero:
  3. while currentValue != 0 {
  4. println("\(currentValue)... ")
  5. currentValue = moveNearerToZero(currentValue)
  6. }
  7. println("zero!")
  8. // 3...
  9. // 2...
  10. // 1...
  11. // zero!

嵌套函数

迄今为止所有你在本章中遇到函数都是全局函数,在全局范围内定义。其实你还可以在其他函数中定义函数,被称为嵌套函数。

嵌套函数默认对外界是隐藏的,但仍然可以调用和使用其内部的函数。内部函数也可以返回一个嵌套函数,允许在嵌套函数内的另一个范围内使用。

你可以重写上面的chooseStepFunction例子使用并返回嵌套函数:
 
 
  1. func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
  2. func stepForward(input: Int) -> Int {
  3. return input + 1
  4. }
  5. func stepBackward(input: Int) -> Int {
  6. return input - 1
  7. }
  8. return backwards ? stepBackward : stepForward
  9. }
  10. var currentValue = -4
  11. let moveNearerToZero = chooseStepFunction(currentValue > 0)
  12. // moveNearerToZero now refers to the nested stepForward() function
  13. while currentValue != 0 {
  14. println("\(currentValue)... ")
  15. currentValue = moveNearerToZero(currentValue)
  16. }
  17. println("zero!")
  18. // -4...
  19. // -3...
  20. // -2...
  21. // -1...
  22. // zero!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。