24 / 07 / 12

「一生一芯」Learn C the hard way - Ex 14

练习 14:编写并使用函数

#include <stdio.h> #include <ctype.h> // forward declarations int can_print_it(char ch); void print_letters(char arg[]); void print_arguments(int argc, char *argv[]) { int i = 0; for(i = 0; i < argc; i++) { print_letters(argv[i]); } } void print_letters(char arg[]) { int i = 0; for(i = 0; arg[i] != '\0'; i++) { char ch = arg[i]; if(can_print_it(ch)) { printf("'%c' == %d ", ch, ch); } } printf("\n"); } int can_print_it(char ch) { return isalpha(ch) || isblank(ch); } int main(int argc, char *argv[]) { print_arguments(argc, argv); return 0; }

附加题 1

重新编写这些函数,使它们的数量减少。比如,你真的需要can_print_it吗?

#include <stdio.h> #include <ctype.h> void print_arguments(int argc, char *argv[]) { int i = 0; int j = 0; for(i = 1; i < argc; i++) { for(j = 0; argv[i][j] != '\0'; j++) { char ch = argv[i][j]; if(isalpha(ch) || isblank(ch)) { printf("'%c' == %d; ", ch, ch); } } printf("\n"); } } int main(int argc, char *argv[]) { print_arguments(argc, argv); return 0; }

附加题 2

使用strlen函数,让print_arguments知道每个字符串参数都有多长,之后将长度传入print_letters。然后重写print_letters,让它只处理固定的长度,不按照'\0'终止符。你需要#include <string.h>来实现它。

void print_arguments(int argc, char *argv[]) { int i = 0; int j = 0; for(i = 1; i < argc; i++) { printf("%lu",strlen(argv[i])); for(j = 0; j < strlen(argv[i]); j++) { char ch = argv[i][j]; if(isalpha(ch) || isblank(ch)) { printf("'%c' == %d; ", ch, ch); } } printf("\n"); } } int main(int argc, char *argv[]) { print_arguments(argc, argv); return 0; }

附加题 3

使用man来查询isalphaisblank的信息。使用其它相似的函数来只打印出数字或者其它字符。

C 标准库中还有其他一些类似的函数,用来判断字符类型。以下是一些相关的函数:

  • isdigit:检查字符是否为数字。

  • isalnum:检查字符是否为字母或数字。

  • isspace:检查字符是否为空白字符(空格、换行、制表符等)。

  • ispunct:检查字符是否为标点符号。

#include <stdio.h> #include <ctype.h> #include <string.h> void print_arguments(int argc, char *argv[]) { int i = 0; int j = 0; for(i = 1; i < argc; i++) { printf("%lu: ",strlen(argv[i])); for(j = 0; j < strlen(argv[i]); j++) { char ch = argv[i][j]; if(isalnum(ch) || isspace(ch) || ispunct(ch)) { printf("'%c' == %d;\t", ch, ch); } } printf("\n"); } } int main(int argc, char *argv[]) { print_arguments(argc, argv); return 0; }

附加题 4

上网浏览不同的人喜欢什么样的函数格式。永远不要使用“K&R”语法,因为它过时了,而且容易使人混乱,但是当你碰到一些人使用这种格式时,要理解代码做了什么。

Google

  1. 文件组织

    • 每个文件只包含一个独立的概念。

    • 使用头文件保护(#ifndef, #define, #endif)防止重复包含。

  2. 命名规范

    • 变量和函数名使用小驼峰命名法(如 myVariable)。

    • 全局变量和常量使用全大写字母和下划线(如 GLOBAL_CONSTANT)。

  3. 缩进和空白

    • 使用2个空格缩进,不使用制表符。

    • 每个函数定义和实现之间留一个空行。

  4. 注释

    • 使用双斜杠(//)注释单行,使用斜杠星号(/* ... */)注释多行。

    • 注释应简明扼要,解释代码逻辑而不是代码本身。

  5. 函数和变量

    • 函数应尽量短小,每个函数只做一件事。

    • 避免使用全局变量,使用局部变量和函数参数。

  6. 常量

    • 使用const关键字定义常量,避免使用宏定义常量。
  7. 条件语句和循环

    • 在条件语句和循环中总是使用大括号,即使只有一行代码。

Microsoft

  1. 命名约定

    • 变量名、函数名、类型名和常量名应使用驼峰命名法(CamelCase),首字母小写。

    • 宏定义使用全大写字母,并且单词之间用下划线分隔。

  2. 代码布局

    • 使用一致的缩进风格,推荐使用四个空格进行缩进。

    • 函数和控制结构的大括号应该独占一行,且大括号应该与相关语句对齐。

  3. 注释规范

    • 函数头应包含描述函数用途、参数和返回值的详细注释。

    • 代码行注释应解释代码的意图、复杂的算法或者可能引起误解的地方。

  4. 函数和参数

    • 函数应该有明确的声明和定义,包括返回类型、函数名和参数列表。

    • 参数应有描述其用途和类型的清晰命名,推荐参数顺序应该符合逻辑顺序。

  5. 错误处理

    • 建议在可能发生错误的地方进行错误检查,并采取适当的错误处理措施。

    • 错误处理应该清晰、一致,并能够提供有用的错误信息和恢复机制。

Recommended C Style and Coding Standards