你好, 欢迎回来｡
在这节课中, 我想谈谈一些你在用c语言编程时会犯的常见错误｡
其中一些错误您可能在之前的挑战中已经熟悉,
并且您实际上已经遇到过这些错误, 但这些是最常见的错误类型｡
第一个非常非常明显｡ 少了一个分号｡
记住c中的所有语句都将以分号结束｡
如果没有, 编译器就会抱怨｡
因此, 无论是放错分号还是完全遗漏分号都是一个非常常见的错误｡
在本例中, 我们将分号放错了位置｡
我们有一个if语句｡ 我们在if语句的末尾加了一个分号｡
而这实际上会导致程序的行为完全不同｡
这将实际编译｡
如果您遗漏了一个分号, 甚至没有包含它, 它将无法编译｡
但是在这个例子中, j的值总是被设置为零,
因为if语句上的分号被放置了｡
所以分号放在if语句之后是完全有效的｡
它实际上表示空语句｡
因此,
编译器不会出错, 但这会引起问题, 因为j永远不会被置为零｡
这种类型的错误在循环中也很常见｡
当你有一个循环,
你把分号放在for循环的末尾, 然后你可能有一个括号, 你没有括号,
因为如果你有括号, 你会有一个错误, 很常见｡
另一个问题是混淆了等于运算符和等于等于运算符｡
特别提到了equals等于运算符不是比较字符串｡
所以如果你在比较字符串的时候使用了equals, equals, 这是无效的｡ 它只会比较参考文献｡
但是如果你真的想给变量赋值, 而不是用equals, equals,
你就需要一个编译器.
现在如果你试图比较两个项, 比如if语句中的两个整数, 而不是使用赋值运算符,
你实际上不会有编译器错误, 但是表达式的结果总是为真｡
所以当你使用equals而不使用equals的时候, 这通常是在if
while do语句中, 在布尔表达式中｡
这是有效的,
除非它有赋值的效果, 而不是执行的效果｡
所以在这个例子中, 如果我们有, 如果a等于2, 它就把2赋给a｡
它总是被设置为true, 因为这是一个true语句, 因为当它赋值时,
你永远不会失败｡ 所以printf总是要运行的｡
这里你真正想做的是, 如果a等于.
所以使用equals, 而不是equals,
这样就不会出现编译器错误了｡
如果在错误的情况下使用equals, 也可能会出现意外的行为, 但如果在赋值时使用它不正确,
则会出现编译器错误｡
但要小心这与平等, 而不是平等的平等｡
省略原型声明｡
我提到在使用函数之前, 一定要在文件的顶部声明函数,
这非常重要｡
然而, 这种情况并不总是发生, 这是非常常见的错误｡
通常情况下, 你会在编译器中得到一个隐式声明错误｡
在这个例子中,
如果你在程序中定义了平方根, 而不是在你调用它的地方,
或者在另一个文件中定义了平方根, 并且你没有显式地声明它, 你会收到一些警告｡
编译器将假定函数返回一个int｡
无论是显式还是隐式地在程序中包含正确的头文件, 在调用的所有函数的顶部包含原型声明总是最安全的｡
但是如果不包含这些, 那些原型声明, 就可能会出错.
未能包含头文件, 该头文件包含程序中正在使用的c编程库函数的定义｡
因此, 在本例中, 您希望重用一些代码｡
也许你有printf函数想要显示一些输出, 但是你没有包括标准的lib头文件｡
那是个错误 编译器通常会告诉你｡
该函数将出现链接问题｡
所以在这个例子中, 我们有两个答案等于1的平方根｡
如果这个程序不包括数学｡
头文件, 这将生成未定义平方根的错误｡
它将尝试链接目标文件｡ 它不会有数学｡ 不可以｡
它会说, 嘿, 你在求平方根, 但是没有实现｡
因此, 请确保为所有函数调用（尤其是从标准库调用）包含正确的头文件｡
混淆字符串中的字符常量｡
如果我们在单引号内有一个文本等于a, 这是一个分配给文本的字符｡
如果我们有一个名为text的变量, 我们用双引号赋值,
这是一个指向字符串的指针｡
对于单个字符无效｡
实际上我们已经讨论过字符串常量, 并把它们赋值给字符数组.
你怎么不能用对等的来做, 你必须用星星的来做｡
在这个例子中,
当我们说text等于a时, 它是赋值一个指针, 这实际上也是无效的,
你要做的是, 如果你不想直接赋值, 你要做的是, 星星文本等于a或者星号副本｡
但你明白要点了｡
使用单引号内的a与双引号内的字符完全不同, 字符与字符串｡
在第一种情况下, 文本通常被声明为char变量｡
而在第二种情况下, 它应该声明为指向char的类型指针｡
如果你想给指针赋值而不是给指针本身赋值,
你就必须解引用它.
这实际上是不正确的,
因为如果它是一个指针而不是一个地址, 你就给它赋值了一个字符串, 所以这没有意义｡
使用错误的数组边界, 数组越界异常｡
在这里, 我们声明了一个100大小的整数数组, 然后声明了一对变量I和sum,
其中只有一些变量被初始化｡
我们循环一遍, 我们说对于I等于1, I小于等于100｡
这是不正确的, 因为100的大小意味着数组中有100个元素｡
但是数组是以零为基础的｡
所以第一个元素是零｡
在数组中可以分配或访问的最大索引为99｡
这将小于等于｡
所以你会犯一个出界错误｡
这不是一个有效的下标, 因为这个循环将一直进行到100｡
它也可能是不正确的, 因为你从1开始｡
如果你真的想要这个数组的第一个元素, 你应该从0开始｡
忘记在数组中为字符串的终止空字符保留一个额外的位置也是一个常见的问题｡
声明字符数组时, 它们需要足够大, 以包含单独终止字符｡
这就是为什么我建议你,
在初始化数组的时候, 不要在数组中加入大小｡
只有在不初始化的情况下, 才需要在其中输入大小｡
如果你在同一行创建initializing,
让c为你做这个工作, 它会自动放置正确的大小, 并且它会包含那个空终止符｡
例如, 如果你有一个字符串,
叫做hello, 这超过了五个内存位置, 它是六个, 因为结尾处有一个空终止符｡
不要忘记数组的大小｡
这是指针的一个常见问题, 我们还没有详细讨论过, 但我确实想提一下,
因为这是非常常见的｡
在指针中, 当你想访问, 甚至是指示, 当你想通过指针访问某个东西时,
你必须使用破折号大于号｡
在访问指针元素时使用｡
所以如果你有一个指向一个结构的指针, 这就是你访问它的方式｡
如果你有一个结构,
它不是指针, 那么你可以用点操作符来访问它｡
很多时候, 这个点运算符和这个破折号, 然后大于被错误地使用｡
点表示非指针, 指针破折号大于,
这在我们更多的例子中会变得很清楚｡
在scanf调用中省略非指针变量前的&符号｡
所以记住我们的scanf调用需要一个指针作为第二个参数, 这意味着一个地址｡
当我们声明一个数据类型为int类型的变量时, 它不是指针｡
所以为了让scanf把数据存储到int变量中, 我们必须给它传递一个&符号,
表示它是一个地址｡
因此这是不正确的, 在number和scan f之前没有&符号作为第二个参数是无效的｡
只有在使用指针（如字符数组）时才没有&符号｡
出现在格式字符串和scanf之后的所有参数都必须是指针｡
在初始化之前使用指针变量｡
这是一个创建指针, 然后给它赋值的例子｡
这是一个正确的赋值语句, 你赋值的时候, 要取消引用它｡
但是我们这里没有做的是,
我们已经初始化了指针, 实际上已经为它分配了内存, 在c中你不能这样做｡
您只能在设定变数指向某个位置之后, 才能将间接取值运算子（即前面的星号）套用至点或变数｡
所以它必须指向某个地方, 现在它是空的它没有指向任何地方因为你没有分配任何内存｡
因此, 字符指针从未设置为指向任何对象, 因此赋值没有意义｡
这实际上会导致分段错误｡
另一个常见的错误是在switch语句中省略case结尾的break语句｡
如果在用例结束时不包括break, 则继续执行下一个用例｡
这就是我提到的, 你有一个案例, 它被评估｡
如果你在那里没有中断,
它会直接进入下一个case, 并执行下一个case中的代码｡
因此, 您总是希望在case语句中有中断｡
有时候, 你想让一个case跟到另一个case,
而它们做的是完全一样的事情,
在这种情况下, 你在case语句中就没有任何东西了｡
在预处理程序定义的末尾插入分号｡
预处理器定义记住以数字开始, 即磅｡
预处理器通常在编译器之前运行以进行优化｡
预处理程序定义的正确语法是不包括分号｡
但是, 在c you中, 养成总是在所有内容之后放分号的习惯｡
但是你要记住, 如果你定义了一些常量数据, 你不需要分号,
这是不正确的｡
如果在这样的表达式中使用它, 这将导致语法错误｡
就像那样｡
所以如果你真的要用它来求最后加个分号是没问题的.
但是当预处理器运行的时候, 它会插入定义的内容.
所以它将作为数据结尾999冒号｡
这是编译器看到的结果, 它会导致一个错误, 那就是语法错误.
在任何语句中省略右括号或右引号, 这很常见｡
所以这也和括号直接相关, 有一个开始的花括号, 然后没有结束的花括号,
和括号一样｡
在这种情况下, 我们有两个或三个起始左括号,
但我们只有两个结束括号｡ 我们少了一个结尾右括号｡
这将是编译器会发现的语法错误｡
因此, 当您使用括号中的嵌入来分隔公式的每个部分时, 它会使代码行更具可读性｡
您需要使用括号｡
然而, 你想确保它们都匹配你开始一个括号你必须有一个结束的右括号, 与花括号相同｡
花括号开头必须有花括号结尾｡
所以要么你有太多, 要么你有太少,
编译器会抱怨, 这是非常, 非常常见的｡
第二行也缺少一个右引号, 这个print语句｡
我们还没有结束语｡
编译器会对此提出抱怨｡
这两种情况都将生成编译错误｡
有时候编译器会产生很大的误导, 因为它实际上并不知道错误发生在哪里｡
它认为错误可能发生在后续行上｡
所以它告诉你错误的那一行可能会误导你｡
因此, 根据编译器在下一行使用括号还是引号, 它实际上将完成该表达式｡
因此它会将错误下移到另一行｡
这就是它会抱怨的地方, 并说这就是错误所在｡
但实际的误差比你想放置的要高｡
这些是我看到很多c程序员犯的一些常见错误｡
他们很容易修复｡ 如果你了解它们并研究这个, 你就会知道不要制造它们｡
作为初学者编写这些代码是可以的,
但是当你编写的代码越来越多, 得到更多的练习时,
你会意识到, 嘿, 我忘了一个括号, 我忘了一个方括号,
我没有正确地使用等号和等号, 我没有正确地使用指针, 我没有分配任何内存｡
所有这些事情都将成为更多的第二天性｡ -谢谢—谢谢