函数和关键字

本篇主要介绍:自定义函数宏函数字符串处理函数关键字

自定义函数

基本用法

实现一个 add() 函数。请看示例:

#include <stdio.h>

// 自定义函数,用于计算两个整数的和
int add(int a, int b) { // a, b 叫形参
int sum = a + b;
return sum;
} int main() {
int num1 = 3;
int num2 = 5; // 调用自定义函数计算两个整数的和
int result = add(num1, num2); // num1, num2 叫实参 printf("两个整数的和为:%d\n", result); return 0;
}

其中a, b 叫形参,num1, num2 叫实参

Tip:形参和实参的个数不同,笔者编译器报错如下(一个说给函数的参数少,一个说给函数的参数多了):

// 3个形参,2个实参
int add(int a, int b, int c) {} // error: too few arguments to function call, expected 3, have 2
int result = add(num1, num2);
// 2个形参,3个实参
int add(int a, int b) {} // error: too many arguments to function call, expected 2, have 3
int result = add(num1, num2, num1);

函数调用过程

函数调用过程:

  1. 通过函数名找到函数的入口地址
  2. 给形参分配内存空间
  3. 传参。包含值传递地址传递(比如js中的对象)
  4. 执行函数体
  5. 返回数据
  6. 释放空间。例如栈空间

请看示例:

#include <stdio.h>

// 2. 给形参分配内存空间
// 3. 传参:值传递和地址传递(比如js中的对象)
// 4. 执行函数体
// 5. 返回数据
// 6. 释放空间。例如栈空间:局部变量 a,b,sum
int add(int a, int b) {
int sum = a + b;
return sum;
} int main() {
int num1 = 3;
int num2 = 5; // 1. 通过函数名找到函数的入口地址
int result = add(num1, num2); printf("add() 的地址:%p\n", add);
printf("%d\n", result); return 0;
}

输出:

add() 的地址:0x401130
8

练习-sizeof

题目:以下两次 sizeof 输出的值相同吗?

#include <stdio.h>

void printSize(int arr[]) {
printf("Size of arr: %zu\n", sizeof(arr));
} int main() {
int nums[] = {1, 2, 3, 4, 5}; printf("Size of nums: %zu\n", sizeof(nums));
printSize(nums); return 0;
}

运行:

开始运行...
// sizeof(arr) 获取的是指针类型 int * 的大小(在此例中是8字节)
/workspace/CProject-test/main.c:4:40: warning: sizeof on array function parameter will return size of 'int *' instead of 'int[]' [-Wsizeof-array-argument]
printf("Size of arr: %zu\n", sizeof(arr));
^
/workspace/CProject-test/main.c:3:20: note: declared here
void printSize(int arr[]) {
^
1 warning generated.
Size of nums: 20
Size of arr: 8 运行结束。

结果:输出不相同,一个是数组的大小,一个却是指针类型的大小。

结果分析:将一个数组作为函数的参数传递时,它会被隐式地转换为指向数组首元素的指针,然后在函数中使用 sizeof 运算符获取数组大小时,实际上返回的是指针类型的大小((通常为4或8字节,取决于系统架构)),而不是整个数组的大小。

宏函数

宏函数是C语言中的一种预处理指令,用于在编译之前将代码片段进行替换

之前我们用 #define 定义了常量:#define MAX_NUM 100。定义宏函数就是将常量改为函数。就像这样

#include <stdio.h>
// 无参
#define PRINT printf("hello\n") // 有参
#define PRINT2(n) printf("%d\n", n) int main() { // 无参调用
PRINT;
// 有参调用
PRINT2(10);
return 0;
}

输出:hello 10

编译流程

宏函数发生在编译的第一步。

编译可以分为以下几个步骤:

  • 预处理(Preprocessing):在这一步中,预处理器将对源代码进行处理。它会展开宏定义、处理条件编译指令(如 #if、#ifdef 等)、包含头文件等操作。处理后的代码会生成一个被称为预处理文件(通常以 .i 或 .ii 为扩展名)。
  • 编译(Compilation):在这一步中,编译器将预处理后的代码翻译成汇编语言。它会进行词法分析、语法分析、语义分析和优化等操作,将高级语言的代码转化为低级机器可以理解的形式。输出的文件通常以 .s 为扩展名,是一个汇编语言文件。
  • 汇编(Assembly):汇编器将汇编语言代码转换为机器语言指令。它将每条汇编语句映射到对应的机器语言指令,并生成一个目标文件(通常以 .o 或 .obj 为扩展名),其中包含已汇编的机器指令和符号表信息。
  • 链接(Linking):如果程序涉及多个源文件,以及使用了外部库函数或共享的代码模块,链接器将合并和解析这些文件和模块。它会将目标文件与库文件进行链接,解析符号引用、处理重定位等。最终生成可执行文件(或共享库),其中包含了完整的机器指令。

这些步骤并非一成不变,具体的编译过程可能因为编译器工具链和目标平台的不同而有所差异。但是大致上,这是一个常见的编译流程。

宏函数 vs 普通函数

用普通函数和宏函数实现平方的功能,代码分别如下:

int square(int x) {
return x * x;
}
#define SQUARE(x) ((x)*(x))

宏函数在编译过程中被简单地替换为相应的代码片段。它没有函数调用的开销,可以直接插入到调用的位置,这样可以提高代码执行效率

这发生在预处理阶段,不会进行类型检查错误检查,可能导致意外的行为或结果。例如:宏函数中需打印字符串,而参数传递数字1:

#include <stdio.h>

#define PRINT2(n) printf("%s\n", n)

int main() {

    PRINT2(1);
return 0;
}

编译有告警,执行文件还是生成了:

pjl@pjl-pc:~/ph$ gcc demo-3.c -o demo-3
demo-3.c: In function ‘main’:
demo-3.c:3:26: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
3 | #define PRINT2(n) printf("%s\n", n)
| ^~~~~~
......
7 | PRINT2(1);
| ~
| |
| int
demo-3.c:7:5: note: in expansion of macro ‘PRINT2’
7 | PRINT2(1);
| ^~~~~~
demo-3.c:3:28: note: format string is defined here
3 | #define PRINT2(n) printf("%s\n", n)
| ~^
| |
| char *
| %d

但运行还是报错:

pjl@pjl-pc:~/ph$ ./demo-3
段错误 (核心已转储)

普通函数具备了类型检查作用域错误检查等功能,可以更加安全可靠地使用。但是函数调用需要一定的开销,涉及保存现场、跳转等操作。例如:

#define ADD(a, b) (a + b)

int result = ADD(3, 5);

编译器会将宏函数展开为 (3 + 5),并直接插入到 ADD(3, 5) 的位置,避免了函数调用的开销。

练习

题目:请问以下输出什么?

#include <stdio.h>

#define SQUARE(x) x * x

int main() {
int result = SQUARE(1 + 2);
printf("%d\n", result); return 0;
}

输出:5。

分析:

// 1 + 2 * 1 + 2
#define SQUARE(x) x * x

如果希望输出 9 可以用括号,就像这样:

//(1 + 2) * (1 + 2)
#define SQUARE(x) (x) * (x)

字符串处理函数

以下几个字符串处理函数都来自 <string.h> 库函数。

strlen()

strlen() - 用于获取字符串的长度,即字符串中字符的个数(不包括结尾的空字符'\0')

语法:

#include <string.h>

size_t strlen(const char *str);

示例:

#include <stdio.h>
#include <string.h> int main() {
char str[] = "Hello, world!";
size_t length = strlen(str);
// Length of the string: 13
printf("Length of the string: %zu\n", length); return 0;
}

Tip: %zu只用于格式化输出 size_t 类型的格式控制符

size_t

size_t是无符号整数类型。unsigned int 也是无符号整数,两者还是有区别的。

size_t 被定义为足够大以容纳系统中最大可能的对象大小的无符号整数类型,可以处理比 unsigned int更大的值。

在涉及到内存分配、数组索引、循环迭代等需要表示大小的场景中,建议使用size_t类型,以保证代码的可移植性和兼容性。尽管许多编译器将size_t 定义为 unsigned int,但不依赖于它与unsigned int之间的精确关系是一个好的编程实践。

strcpy()

strcpy - 将源字符串(src)复制到目标字符串(dest)中,包括字符串的结束符\0。语法:

char *strcpy(char *dest, const char *src);

示例:

#include <stdio.h>
#include <string.h> int main() {
char source[] = "Hello, world!";
char destination[20];
strcpy(destination, source);
// Destination: Hello, world!
printf("Destination: %s\n", destination); return 0;
}

比如destination之前有字符串,而且比source要长,你说最后输出什么?

char source[] = "Hello, world!";
char destination[20] = "world, Hello!XXXXXXX";
strcpy(destination, source);

输出不变。source 拷贝的时候会将结束符\0也复制到目标,destination 最后是Hello, world!\0XXXXXX。如果不需要拷贝结束符,可以使用 strncpy()

strncpy()

strncpy - 将源字符串的指定长度复制到目标字符串中。比如不拷贝源字符的结束符:

示例:

#include <stdio.h>
#include <string.h> int main() {
char source[] = "Hello, world!";
char destination[20] = "world, Hello!XXXXXXX"; // 将源字符串的指定长度复制到目标字符串中,不要source的结束符
strncpy(destination, source, sizeof(source)-1);
// Destination: Hello, world!XXXXXXX
printf("Destination: %s\n", destination); return 0;
}

最后输出:Destination: Hello, world!XXXXXXX

strcat()

strcat - 将源字符串(src)连接到目标字符串(dest)的末尾,形成一个新的字符串。语法:

char *strcat(char *dest, const char *src);

示例:

#include <stdio.h>
#include <string.h> int main() {
char destination[20] = "Hello";
char source[] = ", world!"; strcat(destination, source);
// Destination: Hello, world!
printf("Destination: %s\n", destination); return 0;
}
strncat()

strncat - 将源字符串连接到目标字符串的末尾,并限制连接的字符数量。

示例:

#include <stdio.h>
#include <string.h> int main() {
char destination[20] = "Hello";
char source[] = ", world!"; strncat(destination, source, 3);
// Destination: Hello, w
printf("Destination: %s\n", destination); return 0;
}

strcmp()

strcmp - 用于比较两个字符串的大小。

  • 字符串的比较是按照字典顺序进行的,根据每个字符的 ASCII 值进行比较。
  • 比如 apple 和 applea比较,第一次是 a 等于 a,继续比较,直到第六次 \0 和 a 比较,\0 的 ASCII 是0,而a 是97(可打印字符的ASCII值通常位于32-126之间),所以 applea 更大
  • 大小写敏感。例如 A 的 ASCII 是 65。

例如:比较字符串 str1 和字符串 str2 的大小

  • 如果 str1 小于 str2,则返回一个负整数(通常是 -1)。
  • 如果 str1 大于 str2,则返回一个正整数(通常是 1)。
  • 如果 str1 等于 str2,则返回 0。

示例:

#include <stdio.h>
#include <string.h> int main() {
char str1[] = "apple";
char str2[] = "applea"; int result = strcmp(str1, str2); if (result < 0) {
printf("str1 is less than str2\n");
} else if (result > 0) {
printf("str1 is greater than str2\n");
} else {
printf("str1 is equal to str2\n");
} return 0;
}

输出:str1 is less than str2

strncmp()

strncmp - 比较两个字符串的前n个字符是否相等

示例:

#include <stdio.h>
#include <string.h> int main() {
char str1[] = "apple";
char str2[] = "applea"; // int result = strcmp(str1, str2);
int result = strncmp(str1, str2, strlen(str1)); if (result < 0) {
printf("str1 is less than str2\n");
} else if (result > 0) {
printf("str1 is greater than str2\n");
} else {
printf("str1 is equal to str2\n");
} return 0;
}

输出:str1 is equal to str2

strchr()

strchr - 在一个字符串中查找指定字符第一次出现的位置。语法:

// str是要搜索的字符串;
// c是要查找的字符。
char* strchr(const char* str, int c);

函数返回值:

  • 如果找到指定字符,则返回该字符在字符串中的地址(指针)。
  • 如果未找到指定字符,则返回NULL。

Tip:可以通过地址相减返回字符在字符串中出现的索引值。请看示例:

#include <stdio.h>
#include <string.h> int main() {
char str[] = "Hello, world!";
char* result = strchr(str, 'o'); if (result != NULL) {
// 返回字符'o'的位置,并输出字符 'o' 到结尾的字符串
printf("找到了字符'o',位置为:%s\n", result);
// 地址相减,返回字符第一次出现的索引
printf("找到了字符'o',位置为:%ld\n", result - str);
}
else {
printf("未找到字符'o'\n");
} return 0;
}

输出:

开始运行...

找到了字符'o',位置为:o, world!
找到了字符'o',位置为:4 运行结束。
strrchr

strrchr - 相对strchr()逆序查找。

修改上述示例(strchr)一行代码:

- char* result = strchr(str, 'o');
+ char* result = strrchr(str, 'o');

运行:

开始运行...

找到了字符'o',位置为:orld!
找到了字符'o',位置为:8 运行结束。

strstr

strstr - 用于在一个字符串中查找指定子字符串的第一次出现位置。语法:

char* strstr(const char* str1, const char* str2);

示例:

#include <stdio.h>
#include <string.h> int main() {
char str[] = "Hello, World!";
char *subStr = "World";
char *result = strstr(str, subStr); if (result != NULL) {
printf("找到子字符串:%s\n", result);
} else {
printf("未找到子字符串。\n");
} return 0;
}

关键字

C 语言有如下关键字:

关键字 描述 关键字 描述
auto 声明自动变量 enum 声明枚举类型
break 跳出当前循环或开关语句 extern 声明外部变量或函数
case 开关语句分支标签 float 声明单精度浮点型变量或函数返回值类型
char 声明字符型变量或函数返回值类型 for 循环语句
const 声明只读变量 goto 无条件跳转语句
continue 结束当前循环的迭代,并开始下一次迭代 if 条件语句
default 开关语句的默认分支 int 声明整型变量或函数返回值类型
do 循环语句的循环体 long 声明长整型变量或函数返回值类型
double 声明双精度浮点型变量或函数返回值类型 register 声明寄存器变量
else 条件语句中否定条件的执行体 return 从函数返回值
short 声明短整型变量或函数返回值类型 signed 声明有符号数类型
sizeof 获取某个数据类型或变量的大小 static 声明静态变量
struct 声明结构体类型 switch 开关语句
typedef 声明类型别名 union 声明联合体类型
unsigned 声明无符号数类型 void 声明无类型
volatile 说明变量可以被意外修改,应立即从内存中读取或写入而不进行优化 while 循环语句

重点说一下:static、const(已讲过)、extern。

auto

在C语言中,auto 关键字并不是必需的,因为所有在函数内部声明的变量默认都是自动变量。所以在实际编码中,很少使用 auto 关键字进行变量声明

#include <stdio.h>

int main() {
auto int x = 10; // 等于 int x = 10; printf("The value of x is: %d\n", x); // 输出:The value of x is: 10 return 0;
}

在现代的C语言标准中(C99及以上),auto 关键字的使用已经不常见,并且很少被推荐使用,因为它已经成为了默认行为

register

比如 for(int i = 0; i< 1000; i++),每次i都会自增1,如果编译器没有任何优化,有可能会导致寄存器内存之间的数据交互发生一千次。如果将 i 声明成寄存器变量(register int count;),可能就无需交互这么多次。但这也只是给编译器提供一个建议,指示它将变量存储在寄存器中。实际上,编译器可以选择忽略这个建议,根据自身的优化策略和限制来决定是否将变量存储在寄存器中。

Tip: 寄存器是不能被直接取地址。C 语言标准已经从 C99 开始将 register 关键字标记为过时(deprecated)

extern

extern - 用于声明变量或函数的外部链接性。

通俗点说,比如我在b.c中定义了一个方法,在另一个文件中想使用,无需重复编写,通过 extern 声明后可直接使用。编译时需要将多个文件一起编译成可执行文件。

定义b.c和main.c两个文件:

  • b.c 中通过 extern int number 声明 number 变量在外部已定义,不会分配内存空间
  • main.c 先声明 show() 函数已在外部定义,然后使用
  • 最后通过 gcc 将这两个文件编译成 main 可执行函数

完整代码如下:

b.c:

#include <stdio.h>
extern int number; // 声明外部变量 number 已存在。不会分配内存空间 void show() {
printf("x = %d\n", number); // 使用外部变量 number
}

main.c:

#include <stdio.h>

extern void show();  // 声明函数 show 的存在

// 全局变量
int number = 101;
int main() {
show(); // 调用 b.c 中的函数,打印外部变量 number
return 0;
}

两两个文件一起编译,运行输出 x = 101

pjl@pjl-pc:~/$ gcc main.c b.c -o main && ./main
x = 101

static

static 有3个作用:

  • static int number = 101;, 指明 number 只能在本文件中使用,其他文件即使使用了 extern 也不能访问
  • static void show(), 指明 show 只能在本文件中使用,其他文件即使使用了 extern 也不能访问
  • static 修饰局部变量,会改变变量的声明周期,直到程序结束才释放

通过三个示例一一说明。

:在 extern 示例基础上进行。

示例1:修改 main.c:

- int number = 101;
+ static int number = 101;

编译报错如下:

pjl@pjl-pc:~/$ gcc main.c b.c -o main
/usr/bin/ld: /tmp/ccEOKXoI.o: in function `show':
b.c:(.text+0xa): undefined reference to `number'
collect2: error: ld returned 1 exit status

示例2:修改 b.c:

- void show() {
+ static void show() {

编译报错:

pjl@pjl-pc:~/$ gcc main.c b.c -o main
/usr/bin/ld: /tmp/cc8XfhVS.o: in function `main':
main.c:(.text+0xe): undefined reference to `show'
collect2: error: ld returned 1 exit status

示例3:请问下面这段代码输出什么?

#include <stdio.h>
void show(); void fn1(){
int i = 1;
printf("%d\n", ++i);
} int main() {
for(int i = 0; i < 3; i++){
fn1();
}
return 0;
}

输出三个2。因为 fn1() 每次执行完,存放在栈中的变量 i 就被释放。

如果给 i 增加 static 会输出什么:

- int i = 1;
+ static int i = 1;

输出2 3 4

Tip:在C语言中,全局变量静态变量都属于静态存储类别,默认情况下会被分配到静态数据区。静态数据区在程序启动时被分配,在程序结束时释放。

练习

Tip:以下4个都是字符串相关的编程练习

练习1

题目:查找字符数组中字符的位置,例如 hello e,输出1。

实现:

#include <stdio.h>
#include <string.h> int findIndex(char array[], char target) {
int length = strlen(array);
for (int i = 0; i < length; i++) {
if (array[i] == target) {
return i;
}
}
return -1; // 字符不在数组中
} int main() {
char array[] = "hello";
char target = 'e';
int index = findIndex(array, target); if (index != -1) {
printf("字符 %c 的位置是:%d\n", target, index);
} else {
printf("字符 %c 不在数组中\n", target);
} return 0;
}

输出:字符 e 的位置是:1

练习2

题目:查找字符数组中字符的位置,例如 hello ll,输出2。

实现:

#include <stdio.h>
#include <string.h> int findIndex(char array[], char substring[]) {
char *result = strstr(array, substring);
if (result != NULL) {
return result - array;
}
return -1; // 字符串不在数组中
} int main() {
char array[] = "hello";
char substring[] = "ll";
int index = findIndex(array, substring); if (index != -1) {
printf("字符串 \"%s\" 的位置是:%d\n", substring, index);
} else {
printf("字符串 \"%s\" 不在数组中\n", substring);
} return 0;
}

输出:字符串 "ll" 的位置是:2

练习3

题目:在字符串指定位置插入字符串

实现

#include <stdio.h>
#include <string.h> void insertString(char str[], int pos, const char insert_str[]) {
int len1 = strlen(str);
int len2 = strlen(insert_str); if (pos < 0 || pos > len1)
return; // 无效的插入位置 // 创建临时数组,用于存储插入后的新字符串
char temp[len1 + len2 + 1]; // 将原字符串中插入位置之前的部分复制到临时数组
strncpy(temp, str, pos); // 将要插入的字符串复制到临时数组的合适位置
strcpy(&temp[pos], insert_str); // 追加原字符串中插入位置之后的部分
strcat(temp, &str[pos]); // 将新字符串复制回原字符串
strcpy(str, temp);
} int main() {
char original_str[100] = "Hello, world!";
int pos = 7;
char insert_str[100] = "beautiful "; insertString(original_str, pos, insert_str);
printf("%s\n", original_str); return 0;
}

输出:Hello, beautiful world!

练习4

题目:计算字符串中子串的次数,例如 "helloworldhelloworldhelloworld hello" 中 hello 出现4次

#include <stdio.h>
#include <string.h> int countSubstringOccurrences(const char* str, const char* substring) {
int count = 0;
int substring_length = strlen(substring);
const char* ptr = strstr(str, substring); while (ptr != NULL) {
count++;
ptr += substring_length;
ptr = strstr(ptr, substring);
} return count;
} int main() {
const char* str = "helloworldhelloworldhelloworld hello";
const char* substring = "hello"; int count = countSubstringOccurrences(str, substring);
// 4
printf("%d\n", count); return 0;
}

前端学习C语言 - 函数和关键字的更多相关文章

  1. iOS学习05C语言函数

    本次主要是学习和理解函数,函数树状图如下: 1.函数的声明和定义 函数定义的四要素分别为: 返回值类型 :函数的结果值类型,函数不能返回数组. 指定返回类型是void类型说明函数没有返回值. 函数名 ...

  2. iOS学习09C语言函数指针

    本次主要学习和理解函数指针 1.函数指针 void printValue(int number) { printf("number = %d\n", number); } int ...

  3. 前端学习之回调函数、call方法、apply方法

    今天学习的内容比较少,大部分时间是自己在写qq音乐和京东移动端的页面.现在说说今天学到的内容: 首先,回调函数,就是在函数内部中调用另外一个函数, 将一个函数当作参数传给另一个函数,被传的函数叫做回调 ...

  4. 菜鸟学习-C语言函数参数传递详解-结构体与数组 分类: C/C++ Nginx 2015-07-14 10:24 89人阅读 评论(0) 收藏

    C语言中结构体作为函数参数,有两种方式:传值和传址. 1.传值时结构体参数会被拷贝一份,在函数体内修改结构体参数成员的值实际上是修改调用参数的一个临时拷贝的成员的值,这不会影响到调用参数.在这种情况下 ...

  5. 【前端学习笔记】函数定义、函数调用、this

    函数定义的三种方式与特点: 1.函数声明:(特点:会被前置:重复定义函数时,最后一次定义有效.) 2.函数表达式: 3.函数实例化:(特点:只能访问本地作用域与全局作用域!!!) /* 对象实例化定义 ...

  6. C语言函数申明关键字inline

    内联inline是给编译器的优化提示,如果一个函数被编译成inline的话,那么就会把函数里面的代码直接插入到调用这个函数的地方,而不是用调用函数的形式.如果函数体代码很短的话,这样会比较有效率,因为 ...

  7. C语言函数声明什么时候可以省略,什么时候不能省?

    在学习C语言函数的时候,老师总会告诉我们函数要写声明,然后再定义.这是个稳健的做法.等我自己学习了其他高级语言以后,回头再来写C,突然就觉得函数要写声明有点麻烦.无意间发现有一次函数没写声明居然编译( ...

  8. 大前端学习笔记整理【五】关于JavaScript中的关键字——this

    写在前面 工作有那么一段时间了,但是在工作中,发现自己的理论知识还是有所欠缺.特别是在javascript上,很多东西其实自己属于知道要用这个,但是不知道为什么要这么用...这种情况很是尴尬了,所以写 ...

  9. 前端学习 第三弹: JavaScript语言的特性与发展

    前端学习 第三弹: JavaScript语言的特性与发展 javascript的缺点 1.没有命名空间,没有多文件的规范,同名函数相互覆盖 导致js的模块化很差 2.标准库很小 3.null和unde ...

  10. 【C语言学习笔记】C语言函数执行成功时,返回1和返回0,究竟哪个好?

    基本上,没有人会将大段的C语言代码全部塞入 main() 函数,更好的做法是按照复用率高,耦合性低的原则,尽可能的将代码拆分不同的功能模块,并封装成函数.C语言代码的组合千变万化,因此函数的功能可能会 ...

随机推荐

  1. Flutter 异步编程指南

    作者:京东物流 王志明 1 Dart 中的事件循环模型 在 App 开发中,经常会遇到处理异步任务的场景,如网络请求.读写文件等.Android.iOS 使用的是多线程,而在 Flutter 中为单线 ...

  2. 系统评价——数据包络分析DEA的R语言实现(七)

    数据包络分析(Data envelopment analysis,DEA)是运筹学中用于测量决策部门生产效率的一种方法,它是基于相对效率发展的崭新的效率评估方法. 详细来说,通过使用数学规划模型,计算 ...

  3. 自定义SpringMVC实现

    首先要知道springmvc主要流程: 当用户,也是就是请求送达过来的时候, 1.前端控制器会获取, 2.请求处理映射器,返回执行链接 3.获取执行适配器适配,交给执行器 4.返回modelandvi ...

  4. Windows注册表中修改UAC(用户账号控制)及批处理脚

    我在windows电脑上安装软件时,或者设置开机启动软件时,会先弹出提示框: 用户账户控制 你要允许此应用对你的设备进行更改吗? 很烦人,我不想每次都提醒.需要关闭"用户账户控制" ...

  5. [Linux]常用命令之【diff】

    1 概述 2 diff命令 diff 命令是 Linux 上比较重要的命令行工具,用于比较文本内容,并找到不相同的地方,diff 在命令行中打印每一行的改动之处. diff 程序的输出被称为补丁(pa ...

  6. Django笔记十九之manager用法介绍

    本文首发于微信公众号:Hunter后端 原文链接:Django笔记十九之manager用法介绍 首先介绍一下 manager 的使用场景,比如我们有一些表级别的,需要重复使用的功能,都可以使用 man ...

  7. day07 字符串和列表

    day07字符串与列表 字符串的内置方法 lower upper startswitch endwhich 格式化输出 format join的用法 replace替换字符串 isdigit判断 字符 ...

  8. DG:重启之后主备数据重新同步

    问题描述:本来配置好的DG第二天重启之后,发现主备库数据不能同步,在主库上执行日志切换以及创建表操作都传不到备库上,造成这种错误的原因是主库实例断掉后造成备库日志与主库无法实时接收 主库:orcl  ...

  9. 【Java SE】枚举类和注解

    1.枚举类的使用 当类的对象由有限个,确定的时候,我们称这种类为枚举类.当需要定义一组常量时,建议使用枚举类.而当枚举类中只有一个对象时,可以使用单例模式. 1.1 enmu关键字 省略private ...

  10. jquery实现一个网页同时调用多个倒计时

    <div class="time countdown_1" data-time="1449429731"> <span class=" ...