C库函数

C标准库链接:

https://www.runoob.com/cprogramming/c-standard-library-stdio-h.html

15、int main(int argc, char *argv[], char *envp[]) 的用法

其实: int main(int argc,char *argv[]) 是 UNIX 和 Linux 中的标准写法,而 int main() 只是 UNIX 及 Linux 默许的用法.

那究竟 argc,argv[] 有何之用呢?下面看个例子 edit.c 就会明白它们的用法了:

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(int argc,char *argv[]){
  4. if(argc==1 || argc>2) {
  5. printf("请输入想要编辑的文件名如:./edit fillen");
  6. }
  7. if(argc==2) {
  8. printf("编辑 %sn",argv[1]);
  9. }
  10. exit(0)
  11. }
  12. 编译该程序:gcc -o edit edit.c
  13. 运行:./edit
  14. 结果:请输入想要编辑的文件名如:./edit fille
  15. 运行:./edit edit.txt
  16. 结果:编辑 edit.txt
  17. 看到这里 argc,argv[] 如何用就很明白了,argc 是外部命令参数的个数,argv[] 存放各参数的内容,如上例:执行 ./edit 时,argc 为1, argv[0] 为 ./edit .
  18. 而执行 ./edit edit.txt 时,argc 的值为 2,argv[0] 为./edit, argv[1] 为 edit.txt .
  19. 网友回复:简单的说,就是命令行参数!
  20. argc 是外部命令参数的个数,argv[] 存放各参数的内容,如上例:执行 ./edit 时,argc 为1, argv[0] 为 ./edit .
  21. 而执行 ./edit edit.txt 时,argc 的值为 2,argv[0] 为 ./edit,argv[1] 为 edit.txt .
  22. 网友回复:int argc 参数个数
  23. char** argv 参数数组,,数组大小就是前面那个参数,通过数组下标访问里面存放的内容,例如argv[0],argv[1]
  24. 网友回复:int main(int argc,char** argv)
  25. {
  26. FILE *fp;
  27. fp = fopen("E:/works/ee/debug/1.txt","r");
  28. 为什么这个fp指针还是为空了???
  29. 网友回复:指针使用之前应该进行初始化

11、int main(int argc, char *argv[], char *envp[])

这个赋值过程是编译器完成的,我们只需要读出数据就可以了。

int main(int argc, char *argv[], char *envp[])
main()函数一般用int或者void形的。我比较喜欢用int型定义main。因为在结束的时候可以返回给操作系统一个值以表示执行情况。

参数:

int argc
这个东东用来表示你在命令行下输入命令的时候,一共有多少个参数。比方说你的程序编译后,可执行文件是test.exe
D:\tc2>test
这个时候,argc的值是1
但是
D:\tc2>test.exe myarg1 myarg2
的话,argc的值是3。也就是 命令名 加上两个参数,一共三个参数
char *argv[]
这个东东用来取得你所输入的参数
D:\tc2>test
这个时候,argc的值是1,argv[0]的值是 "test"
D:\tc2>test myarg1 myarg2
这个时候,argc的值是3,argc[0]的值是"test",argc[1]的值是"myarg1",argc[2]的值是"myarg2"。
这个东东一般用来为程序提供非常重要的信息,如:数据文件名,等等。
如:copy a.c b.txt
这个时候,a.c和b.txt就是所谓的“非常重要的信息”。不指定这两个文件,你没法进行拷贝。
当你的程序用到argc和argv这两个参数的时候,可以简单地通过判断argc的值,来看看程序的参数是否符合要求

argv数组中的第一个单元,指向的字符串总是可执行程序的名字,以后的单元指向的字符串依次是程序调用时的参数。
这个赋值过程是编译器完成的,我们只需要读出数据就可以了。

char *envp[]
这个东东相对来说用得比较少。它是用来取得系统的环境变量的。
如:在DOS下,有一个PATH变量。当你在DOS提示符下输入一个命令(当然,这个命令不是dir一类的内部命令)的时候,DOS会首先在当前目录下找这个命令的执行文件。

如果找不到,则到PATH定义的路径下去找,找到则执行,找不到返回Bad command or file name

在DOS命令提示符下键入set可查看系统的环境变量
同样,在UNIX或者LINUX下,也有系统环境变量,而且用得比DOS要多。如常用的$PATH,$USER,$HOME等等。
envp保存所有的环境变量。其格式为(UNIX下)
PATH=/usr/bin;/local/bin;
HOME=/home/shuui
即:
环境变量名=值
DOS下大概也一样。

exit()是程序退出时的返回码,可以用其他程序接收,判断是否正常退出。如exit(-1)认为异常退出。

Examples:

https://www.cnblogs.com/avril/archive/2010/03/22/1691477.html

C语言库- <getopt.h>

1、int getopt_long(argc, argv, short_options, long_options, NULL ) 解析命令行参数

  1. int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

    使用GNU C提供的函数getopt、getopt_long、getopt_long_only函数来解析命令行参数。命令行参数可以分为两类,一类是短选项,一类是长选项,

    如(ls 命令参数)所示,

    -a,-A,-b都表示短选项,

    --all,--almost-all, --author都表示长选项。

    他们两者后面都可选择性添加额外参数。比如--block-size=SIZE,SIZE便是额外的参数。原文链接:https://blog.csdn.net/qq_33850438/article/details/80172275

(1)argc和argv和main函数的两个参数一致

(2)optstring: 表示短选项字符串

短选项在参数前加一杠"-",

  1. 形式如“a🅱️💿“,分别表示程序支持的命令行短选项有-a、-b、-c、-d,冒号含义如下:
    1. (1)只有一个字符,不带冒号——只表示选项, 如-c
    2. (2)一个字符,后接一个冒号——表示选项后面带一个参数,如-a 100
    3. (3)一个字符,后接两个冒号——表示选项后面带一个可选参数,即参数可有可无, 如果带参数,则选项与参数直接不能有空格
    4. 形式应该如-b200
  2. static const char *short_options = "f:vy:l:r:c:dapⓂ️ut:eg:";

(3)longopts:表示长选项结构体。

结构如下:

长选项在参数前连续加两杠"--",

  1. (1)name:表示选项的名称,比如daemon,dir,out等。
  2. (2)has_arg:表示选项后面是否携带参数。该参数有三个不同值,如下:
    1. a: no_argument(或者是0)时 ——参数后面不跟参数值,eg: --version,--help
    2. b: required_argument(或者是1)时 ——参数输入格式为:--参数 值 或者 --参数=值。eg:--dir=/home
    3. c: optional_argument(或者是2)时 ——参数输入格式只能为:--参数=值
  3. (3)flag:这个参数有两个意思,空或者非空。
    1. a:如果参数为空NULL,那么当选中某个长选项的时候,getopt_long将返回val值。 eg,可执行程序 --help,getopt_long的返回值为h.
    2. b:如果参数不为空,那么当选中某个长选项的时候,getopt_long将返回0,并且将flag指针参数指向val值。 eg: 可执行程序 --http-proxy=127.0.0.1:80 那么getopt_long返回值为0,并且lopt值为1。
  4. (4)val:表示指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值val。
    1.
    2. struct option
    3. {
    4. const char *name; // name:表示选项的名称,比如daemon,dir,out等
    5. int has_arg; //表示选项后面是否携带参数 ,0\1\2
    6. int *flag;
    7. int val; //表示指定函数找到该选项时的返回值
    8. };
    9. eg:
    10. static struct option long_options[] = {
    11. {"filename_base", HAS_ARG, 0, 'f'},
    12. {"video", NO_ARG, 0, DUMP_VIDEO},
    13. {"yuv", HAS_ARG, 0, DUMP_YUV},
    14. {"luma", HAS_ARG, 0, DUMP_LUMA},
    15. {"raw", HAS_ARG, 0, DUMP_RAW},
    16. {"buf_dump", NO_ARG, 0, DUMP_BUF},
    17. {"vca_dump", NO_ARG, 0, DUMP_VCA},
    18. {"count", HAS_ARG, 0, COUNT},
    19. {"yuv_pre", HAS_ARG, 0, DUMP_YUV_PRE},
    20. {"pyramid", HAS_ARG, 0, DUMP_PYRAMID},
    21. {"use-dma-buf", NO_ARG, 0, USE_DMA_BUF},
    22. {"show-pts", HAS_ARG, 0, SHOW_PTS},
    23. {"cap-extra-raw", NO_ARG, 0, DUMP_EXTRA_RAW},
    24. {"multiple-yuv", HAS_ARG, 0, DUMP_MULTI_YUV},
    25. {0, 0, 0, 0}
    26. }; // longopts的最后一个元素必须是全0填充,否则会报段错误
    27.

(4)longindex:

longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。

(5)返回值:

(1)如果短选项找到,那么将返回短选项对应的字符。

(2)如果长选项找到,如果flag(长选项中的第三个值)为NULL,返回val。如果flag不为空,返回0

(3)如果遇到一个选项没有在短字符、长字符里面。或者在长字符里面存在二义性的,返回“?”

(4)如果解析完所有字符没有找到(一般是输入命令参数格式错误,eg: 连斜杠都没有加的选项),返回“-1”

(5)如果选项需要参数,忘了添加参数。返回值取决于optstring,如果其第一个字符是“:”,则返回“:”,否则返回“?”。

(6)全局变量:optarg\optind\opteer\optopt

这些全局变量的使用,

int ch;

ch = getopt_long(argc, argv, short_options, long_options, &option_index)

snprintf(filename, sizeof(filename), "%s", optarg);

//使用了getopt_long()后,在 test_stream –f /mnt 命令执行时,-f 是当前选项,optarg是参数值即指向 /mnt,

  1. (1)optarg:表示当前选项对应的参数值。
    1. (2)optind:表示的是下一个将被处理到的参数在argv中的下标值。
    2. (3)opterr:如果opterr = 0,在getopt、getopt_long、getopt_long_only遇到错误将不会输出错误信息到标准输出流。opterr在非0时,向屏幕输出错误。
    3. (4)optopt:表示没有被未标识的选项。

注意:

  1. (1)longopts的最后一个元素必须是全0填充,否则会报段错误
    1. (2)短选项中每个选项都是唯一的。而长选项如果简写,也需要保持唯一

C 标准库 - <stdlib.h>

1、malloc()

  1. C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。
  2. C 库函数 void *calloc(size_t nitems, size_t size) 分配所需的内存空间,并返回一个指向它的指针。malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。
  3. C 库函数 void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。
  4. C 库函数 void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。
Example 1

这个例子,区别了 malloc 与 calloc ,可以判断malloc分配内存是否成功。
  1. f_socket_data = (float *)malloc(total_vpout_length);

  2. if (!f_socket_data) { //如果有分配了内存,就不执行此函数。

  3. printf("ERROR: Out of memory for f_socket_data!\n");

  4. ret = -1;

  5. break;

  6. }

    Example 2

    这个例子使用了 malloc realloc free

  7. #include <stdio.h>

  8. #include <string.h>

  9. #include <stdlib.h>

  10. int main()

  11. {

  12. char *str;

  13. /* 最初的内存分配 */

  14. str = (char *) malloc(15); //使用malloc 需要进行强制类型转换

  15. strcpy(str, "runoob");

  16. printf("String = %s, Address = %u\n", str, str);

  17. /* 重新分配内存 */

  18. str = (char *) realloc(str, 25);

  19. strcat(str, ".com");

  20. printf("String = %s, Address = %u\n", str, str);

  21. free(str);

  22. return(0);

  23. }

  24. 让我们编译并运行上面的程序,这将产生以下结果:

  25. String = runoob, Address = 3662685808

  26. String = runoob.com, Address = 3662685808

new和malloc的区别可以从以下几方面进行阐述:

属性上:new/delete是C++关键字需要编译器支持,maollc是库函数,需要添加头文件

最大的区别:new在申请空间的时候会调用构造函数,malloc不会调用

成功返回类型:new操作符申请内存成功时,返回的是对象类型的指针,类型严格与对象匹配,无需进行类型转换,因此new是类型安全性操作符。malloc申请内存成功则返回void*,需要强制类型转换为我们所需的类型

申请失败返回:new在申请空间失败后返回的是错误码bad_alloc,malloc在申请空间失败后会返回NULL

参数:new在申请内存分配时不需要指定内存块大小,编译器会更具类型计算出大小,malloc需要显示的指定所需内存的大小

自定义类型:new会先调operator new函数,申请足够的内存(底层也是malloc实现),然后调用类的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数来释放内存(底层是通过free实现)。malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构函数

重载:C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回地址。malloc不允许重载。

New 与 delete

如果动态分配了一个数组,但是却用delete p的方式释放,没有用[],则编译时没有问题,运行时也一般不会发生错误,但实际上会导致动态分配的数组没有被完全释放。

牢记,用 new 运算符动态分配的内存空间,一定要用 delete 运算符释放。否则,即便程序运行结束,这部分内存空间仍然不会被操作系统收回,从而成为被白白浪费掉的内存垃圾。这种现象也称为“内存泄露”。

2、atof()、atoi()、atol()

  1. : double atof(const char *str) //把参数 str 所指向的字符串转换为一个浮点数
  2. : int atoi(const char *str) //把参数 str 所指向的字符串转换为一个整数
  3. : long int atol(const char *str)// 把参数 str 所指向的字符串转换为一个长整数

3、rand()、srand()

  1. : int rand(void)
  2. : void srand(unsigned int seed)
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <time.h>
  6. int main(){
  7. int i, n;
  8. time_t t;
  9. n = 5;
  10. /* 初始化随机数发生器 */
  11. srand((unsigned) time(&t));
  12. /* 输出 0 到 50 之间的 5 个随机数 */
  13. for( i = 0 ; i < n ; i++ ) {
  14. printf("%d\n", rand() % 50);
  15. }
  16. return(0);
  17. }

4、abort()、atexit()、exit()

4.1 void abort(void) // 使一个异常程序终止

switch(next_option){

case 'h':

print_usage(stdout , 0);

case '?':

print_usage(stderr , 1);

case -1:

break;

default:

abort();

}

4.2 int atexit(void (*func)(void)) // 当程序正常终止时,调用指定的函数 func,调用成功返回 0,否则返回一个非零值

4.3 void exit(int status) //使程序正常终止。

(1)exit(1)表示异常退出,在退出前可以给出一些提示信息,或在调试程序中察看出错原因。

(2)exit(0)表示正常退出。

5、getenv()

https://www.runoob.com/cprogramming/c-function-getenv.html

C 库函数 char *getenv(const char *name) 搜索 name 所指向的环境字符串,并返回相关的值给字符串。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main ()
  4. {
  5. printf("PATH : %s\n", getenv("PATH"));
  6. printf("HOME : %s\n", getenv("HOME"));
  7. printf("ROOT : %s\n", getenv("ROOT"));
  8. return(0);
  9. }
  10. 让我们编译并运行上面的程序,这将产生以下结果:
  11. PATH : /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
  12. HOME : /
  13. ROOT : (null)

6、system()

  1. // int system(const char *string)
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include<stdlib.h>
  5. int main (){
  6. char command[50];
  7. strcpy( command, "ls -l" );
  8. system(command);
  9. return(0);
  10. }
  11. drwxr-xr-x 2 apache apache 4096 Aug 22 07:25 hsperfdata_apache
  12. drwxr-xr-x 2 railo railo 4096 Aug 21 18:48 hsperfdata_railo
  13. rw------ 1 apache apache 8 Aug 21 18:48 mod_mono_dashboard_XXGLOBAL_1
  14. rw------ 1 apache apache 8 Aug 21 18:48 mod_mono_dashboard_asp_2
  15. srwx---- 1 apache apache 0 Aug 22 05:28 mod_mono_server_asp
  16. rw------ 1 apache apache 0 Aug 22 05:28 mod_mono_server_asp_1280495620
  17. srwx---- 1 apache apache 0 Aug 21 18:48 mod_mono_server_global

C 标准库 - <string.h>

https://www.runoob.com/cprogramming/c-standard-library-string-h.html

库变量

下面是头文件 string.h 中定义的变量类型:

size_t 这是无符号整数类型,它是 sizeof 关键字的结果。

下面是头文件 string.h 中定义的宏:

NULL 这个宏是一个空指针常量的值。

1、搜索,返回位置 “ * ”

*memchr(const void *str, int c, size_t n)

在参数 str 所指向的字符串的前 n 个字节中搜索第一次出现字符 c(一个无符号字符)的位置。

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main ()
  4. {
  5. const char str[] = "http://www.runoob.com";
  6. const char ch = '.';
  7. char *ret;
  8. ret = (char*)memchr(str, ch, strlen(str)); //这里返回 . 后面的一串字符,可用于截取字符
  9. printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);
  10. return(0);
  11. }
  12. 让我们编译并运行上面的程序,这将产生以下结果:
  13. |.| 之后的字符串是 - |.runoob.com|

*strchr( str , c )

  1. char *strchr(const char *str,int c) //在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置,该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。结果是指向找到的 位置。
  2. #include <stdio.h>
  3. #include <string.h>
  4. int main (){
  5. const char str[] = "http://www.runoob.com";
  6. const char ch = '.';
  7. char *ret;
  8. ret = strchr(str, ch);
  9. printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);
  10. return(0);
  11. }
  12. 让我们编译并运行上面的程序,这将产生以下结果:
  13. |.| 之后的字符串是 - |.runoob.com|

*strrchr(str , c)

在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置

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

在字符串 str1中查找第一次出现字符串 str2 的位置,不包含终止符 '\0'

该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(){
  4. const char haystack[20] = "RUNOOB";
  5. const char needle[10] = "NOOB";
  6. char *ret;
  7. ret = strstr(haystack, needle);
  8. printf("子字符串是: %s\n", ret);
  9. return(0);
  10. }
  11. 让我们编译并运行上面的程序,这将产生以下结果:
  12. 子字符串是: NOOB

2、比较,返回int

memcmp() 与 strncmp() 一毛一样

  1. :int memcmp(const void *str1,const void *str2,size_t n) //把 str1str2 的前 n 个字节进行比较

  2. int strncmp(const char *str1, const char *str2, size_t n)

    如果返回值 < 0,则表示 str1 小于 str2。

    如果返回值 > 0,则表示 str1 大于 str2。

    如果返回值 = 0,则表示 str1 等于 str2。

strcmp()

int strcmp(const char *str1, const char *str2)

返回值和 memcmp() 相同

strcoll()

int strcoll(const char *str1, const char *str2) //如果只比较字符串,和strcmp()一毛一样

函数说明:strcoll() 会依环境变量 LC_COLLATE 所指定的文字排列次序来比较 s1 和 s2 字符串。

默认情况下,LC_COLLATE 为"POSIX"或"C",strcoll() 和 strcmp() 一样根据ASCII比较字符串大小。

对于设置了 LC_COLLATE 语言环境的情况下,则根据 LC_COLLATE 设置的语言排序方式进行比较。例如,汉字会根据拼音进行比较。

3、复制,返回位置 “ * ”

*memcpy() 与 *memmove() 一毛一样

  1. : void *memcpy(void *dest,const void *src,size_t n) //从 src 复制 n 个字符到 dest

  2. : void *memmove(void *str1,const void *str2,size_t n)//

    str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。

    如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。

    如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

    str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

    str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。

    n -- 要被复制的字节数。

  3. 第一种用法

  4. memcpy(dest, src, strlen(src)+1); // 将字符串复制到数组 dest 中

  5. 第二种用法

  6. memcpy(d, s+11, 6);// 从第 11 个字符(r)开始复制,连续复制 6 个字符(runoob) // 或者 memcpy(d, s+11*sizeof(char), 6*sizeof(char));

*strcpy()

char *strcpy(char *dest, const char *src) //把 src 所指向的字符串复制到 dest

需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char src[40];
  6. char dest[100];
  7. memset(dest, '\0', sizeof(dest));
  8. strcpy(src, "This is runoob.com");
  9. strcpy(dest, src);
  10. printf("最终的目标字符串: %s\n", dest);
  11. return(0);
  12. }
  13. 让我们编译并运行上面的程序,这将产生以下结果:
  14. 最终的目标字符串: This is runoob.com

*strncpy()

char *strncpy(char *dest, const char *src, size_t n)

src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

4、memset()

复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。

char buf_ch[CLASSNAME_LENGTH] = {0};

memset(buf_ch, 0, CLASSNAME_LENGTH);//把 buf_ch[] 全部置 0.

5、strcat(str1 , str2) 、strncat(str1, str2, n)

src 所指向的字符串追加到 dest 所指向的字符串的结尾

  1. //char *strcat(char *dest, const char *src)
  2. //char *strncat(char *dest, const char *src, size_t n) // n -- 要追加的最大字符数
  3. #include <stdio.h>
  4. #include <string.h>
  5. int main () {
  6. char src[50], dest[50];
  7. strcpy(src, "This is source");
  8. strcpy(dest, "This is destination");
  9. strcat(dest, src); //连接两个字符串
  10. printf("最终的目标字符串: |%s|", dest);
  11. return(0);
  12. }
  13. 让我们编译并运行上面的程序,这将产生以下结果:
  14. 最终的目标字符串: |This is destinationThis is source|

6、strtok()

char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。

该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。

  1. #include <string.h>
  2. #include <stdio.h>
  3. int main () {
  4. char str[80] = "This is - www.runoob.com - website";
  5. const char s[2] = "-";
  6. char *token;
  7. /* 获取第一个子字符串 */
  8. token = strtok(str, s);
  9. /* 继续获取其他的子字符串 */
  10. while( token != NULL ) {
  11. printf( "%s\n", token );
  12. token = strtok(NULL, s); //这步有点特殊要注意
  13. }
  14. return(0);
  15. }
  16. 让我们编译并运行上面的程序,这将产生以下结果:
  17. This is
  18. www.runoob.com
  19. website

7、strlen(str)

size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。测出的长度不是 str[50] 的50长,是str中具体有多少字符。

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main ()
  4. {
  5. char str[50];
  6. int len;
  7. strcpy(str, "This is runoob.com");
  8. len = strlen(str);
  9. printf("|%s| 的长度是 |%d|\n", str, len);
  10. return(0);
  11. }
  12. 让我们编译并运行上面的程序,这将产生以下结果:
  13. |This is runoob.com| 的长度是 |18|

C 标准库 -<stdio.h>

打开关闭删除,重命名文件

fopen() 、fclose()

(1)C 库函数 FILE *fopen(const char *filename, const char *mode) 使用给定的模式 mode 打开 filename 所指向的文件。

filename -- 这是 C 字符串,包含了要打开的文件名称。

mode -- 这是 C 字符串,包含了文件访问模式,模式如下:

模式 描述
"r" 打开一个用于读取的文件。该文件必须存在。
"w" 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。
"a" 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
"r+" 打开一个用于更新的文件,可读取也可写入。该文件必须存在。
"w+" 创建一个用于读写的空文件。
"a+" 打开一个用于读取和追加的文件。

返回值

该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。

  1. fp = fopen("file.txt","r");
  2. if(fp == NULL) { //判断打开文件是否正常。
  3. perror("打开文件时发生错误");
  4. return(-1);
  5. }
  6. #include <stdio.h>
  7. int main(){
  8. FILE *fp;
  9. char c;
  10. fp = fopen("file.txt", "w");
  11. c = fgetc(fp);
  12. if( ferror(fp) ) { //测试给定流 stream 的错误标识符
  13. printf("读取文件:file.txt 时发生错误\n");
  14. }
  15. clearerr(fp); //清除给定流 stream 的文件结束和错误标识符
  16. if( ferror(fp) ) {
  17. printf("读取文件:file.txt 时发生错误\n");
  18. }
  19. fclose(fp);
  20. return(0);
  21. }
  22. 假设我们有一个文本文件 file.txt,它是一个空文件。让我们编译并运行上面的程序,因为我们试图读取一个以只写模式打开的文件,这将产生以下结果。
  23. 读取文件:file.txt 时发生错误

remove()

C 库函数 int remove(const char *filename) 删除给定的文件名 filename,以便它不再被访问。如果成功,则返回零。如果错误,则返回 -1,并设置 errno。

char filename[] = "file.txt";

ret = remove(filename);

if(ret == 0) {

printf("文件删除成功");

}

else {

printf("错误:不能删除该文件");

}

rename()

int rename(const char *old_filename, const char *new_filename)old_filename 所指向的文件名改为 new_filename。如果成功,则返回零。如果错误,则返回 -1,并设置 errno。

char oldname[] = "file.txt";

char newname[] = "newfile.txt";

ret = rename(oldname, newname);

测定 stream 文件结束、错误标识

feof(FILE *stream)

速记:!feof(file) 没到结尾;feof(file) 到结尾

C 库函数 int feof(FILE *stream) 测试给定流 stream 的文件结束标识符。

参数stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值当设置了与流关联的文件结束标识符时,检测到文件结束标识返回1,否则返回0。

int ferror(FILE *stream)

测试给定流 stream 的错误标识符

clearerr()

  1. clearerr(fp); //清除给定流 stream 的文件结束和错误标识符

给定流 stream 读写文件

(写入到流 stream)fwrite()

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)ptr 所指向的数组中的数据写入到给定流 stream 中

  1. #include<stdio.h>
  2. int main (){
  3. FILE *fp;
  4. char str[] = "This is runoob.com";
  5. fp = fopen( "file.txt" , "w" );
  6. fwrite(str, sizeof(str) , 1, fp ); //fwrite(str, strlen(str) + 1, 1, fp);
  7. fclose(fp);
  8. return(0);
  9. }
  10. 让我们编译并运行上面的程序,这将创建一个文件 file.txt,它的内容如下:
  11. This is runoob.com

(写入到流 stream)fprintf()

int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中。

参数stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。

format -- 这是 C 字符串,包含了要被写入到流 stream 中的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. int main(){

  4. FILE * fp;

  5. fp = fopen ("file.txt", "w+");

  6. fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014);

  7. fclose(fp);

  8. return(0);

  9. }

  10. 让我们编译并运行上面的程序,这将创建文件 file.txt,它的内容如下:

  11. We are in 2014

    与区别printf sprintf ,输出到的位置不同

    int printf(const char *format, ...)
    发送格式化输出到标准输出 stdout。

    int sprintf(char *str, const char *format, ...)
    发送格式化输出到字符串。

    printf sprintf fprintf

    vprintf vsprintf vfprintf

(写入到流 stream)vfprintf()

int vfprintf(FILE *stream, const char *format, va_list arg) 使用参数列表发送格式化输出到流 stream 中。

  1. #include <stdio.h>

  2. #include <stdarg.h>

  3. void WriteFormatted (FILE * stream, const char * format, ...) {

  4. va_list args;

  5. va_start (args, format);

  6. vfprintf (stream, format, args);

  7. va_end (args);

  8. }

  9. int main ()

  10. {

  11. FILE * pFile;

  12. pFile = fopen ("myfile.txt","w");

  13. WriteFormatted (pFile,"Call with %d variable argument.\n",1);

  14. WriteFormatted (pFile,"Call with %d variable %s.\n",2,"arguments");

  15. fclose (pFile);

  16. return 0;

  17. }

    与区别vprintf vsprintf

    int vprintf(const char *format, va_list arg)
    使用参数列表发送格式化输出到标准输出 stdout。

    int vsprintf(char *str, const char *format, va_list arg)
    使用参数列表发送格式化输出到字符串。

    printf sprintf fprintf

    vprintf vsprintf vfprintf

(写入到流 stream) fputc() 与 putc() 一毛一样

int fputc(int char, FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。

如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。

  1. #include <stdio.h>
  2. int main () {
  3. FILE *fp;
  4. int ch;
  5. fp = fopen("file.txt", "w+");
  6. for( ch = 33 ; ch <= 100; ch++ ) {
  7. fputc(ch, fp); //虽然是int ,但是会转换成字符进行输入
  8. }
  9. fclose(fp);
  10. return(0);
  11. }
  12. 让我们编译并运行上面的程序,这将在当前目录中创建文件 file.txt,它的内容如下:
  13. !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd

(写入到流 stream) fputs()

int fputs(const char *str, FILE *stream) 把字符串写入到指定的流 stream 中,但不包括空字符 ‘\0’。该函数返回一个非负值,如果发生错误则返回 EOF。

  1. #include <stdio.h>
  2. int main (){
  3. FILE *fp;
  4. fp = fopen("file.txt", "w+");
  5. fputs("这是 C 语言。", fp);
  6. fputs("这是一种系统程序设计语言。", fp);
  7. fputs("这是 C 语言。: \0 dsgf ", fp); // \0 就是空字符
  8. fclose(fp);
  9. return(0);
  10. }
  11. 让我们编译并运行上面的程序,这将创建文件 file.txt,它的内容如下:
  12. 这是 C 语言。这是一种系统程序设计语言。

(读取流 stream)fread()

size_t fread(void *ptr, size_t size, size_t count, FILE *stream) 从给定流 stream 读取数据ptr 所指向的数组中。

size 是每次读取的字节数
count 是读取次数

  1. 例如 从文件fp里读取100个字节 可用以下语句

  2. fread(buffer,100,1,fp)

  3. fread(buffer,50,2,fp)

  4. fread(buffer,1,100,fp)

    成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。

(读取流 stream) fscanf()

int fscanf(FILE *stream, const char *format, ...) 从流 stream 读取格式化输入

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4. char str1[10], str2[10], str3[10];
  5. int year;
  6. FILE * fp;
  7. fp = fopen ("file.txt", "w+");
  8. fputs("We are in 2014", fp);
  9. rewind(fp);
  10. fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);
  11. printf("Read String1 |%s|\n", str1 );
  12. printf("Read String2 |%s|\n", str2 );
  13. printf("Read String3 |%s|\n", str3 );
  14. printf("Read Integer |%d|\n", year );
  15. fclose(fp);
  16. return(0);
  17. }
  18. 让我们编译并运行上面的程序,这将产生以下结果:
  19. Read String1 |We|
  20. Read String2 |are|
  21. Read String3 |in|
  22. Read Integer |2014|

(读取流 stream)fgetc()

int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。

该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。

  1. #include <stdio.h>
  2. int main (){
  3. FILE *fp;
  4. int c;
  5. int n = 0;
  6. fp = fopen("file.txt","r");
  7. if(fp == NULL) {
  8. perror("打开文件时发生错误");
  9. return(-1);
  10. }
  11. do {
  12. c = fgetc(fp);
  13. if( feof(fp) ){ //速记:!feof(file) 没到结尾;feof(file) 到结尾
  14. break ;
  15. }
  16. printf("%c", c);
  17. }while(1);
  18. fclose(fp);
  19. return(0);
  20. }
  21. 假设我们有一个文本文件 file.txt,它的内容如下。文件将作为实例中的输入:
  22. We are in 2014
  23. 让我们编译并运行上面的程序,这将产生以下结果:
  24. We are in 2014

(读取流 stream)*fgets

char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

  • n -- 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。

    如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。如果发生错误,返回一个空指针。

  1. #include <stdio.h>
  2. int main(){
  3. FILE *fp;
  4. char str[60];
  5. /* 打开用于读取的文件 */
  6. fp = fopen("file.txt" , "r");
  7. if(fp == NULL) {
  8. perror("打开文件时发生错误");
  9. return(-1);
  10. }
  11. if( fgets (str, 60, fp)!=NULL ) {
  12. /* 向标准输出 stdout 写入内容 */
  13. puts(str);
  14. }
  15. fclose(fp);
  16. return(0);
  17. }
  18. 假设我们有一个文本文件 file.txt,它的内容如下。文件将作为实例中的输入:
  19. We are in 2014
  20. 让我们编译并运行上面的程序,这将产生以下结果:
  21. We are in 2014

(读取流 stream)ungetc()

int ungetc(int char, FILE *stream) 把字符 char(一个无符号字符)推入到指定的流 stream 中,以便它是下一个被读取到的字符。

  1. #include <stdio.h>
  2. int main (){
  3. FILE *fp;
  4. int c;
  5. char buffer [256];
  6. fp = fopen("file.txt", "r");//这里是read,若用fputc ,需要用 ‘r+’,一边读一边写
  7. if( fp == NULL ){
  8. perror("打开文件时发生错误");
  9. return(-1);
  10. }
  11. while(!feof(fp)) {
  12. c = getc (fp);
  13. /* 把 ! 替换为 + */
  14. if( c == '!' ){
  15. ungetc ('+', fp); //决不可换成 putc(),fputc能改变文件,ungetc不改变源文件。
  16. }
  17. else {
  18. ungetc(c, fp);
  19. }
  20. fgets(buffer, 255, fp);
  21. fputs(buffer, stdout);
  22. }
  23. return(0);
  24. }
  25. 假设我们有一个文本文件 file.txt,它的内容如下。文件将作为实例中的输入:
  26. this is runoob
  27. !c standard library
  28. !library functions and macros
  29. 让我们编译并运行上面的程序,这将产生以下结果:
  30. this is runoob
  31. +c standard library
  32. +library functions and macros

输出到字符串

(输出到字符串) sprintf()

int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串。

  1. #include <stdio.h>

  2. #include <math.h>

  3. int main()

  4. {

  5. char str[80];

  6. sprintf(str, "Pi 的值 = %f", M_PI);

  7. puts(str);

  8. return(0);

  9. }

  10. 让我们编译并运行上面的程序,这将产生以下结果:

  11. Pi 的值 = 3.141593

    sprintf() 和 snprintf() 的区别在于 snprintf() 多了一个size参数,可控制要写入的字符的最大数目

(输出到字符串) snprintf(char *str, size_t size, const char *format, ...)

C 库函数 int snprintf(char *str, size_t size, const char *format, ...) 设将可变参数(...)按照 format 格式化成字符串,并将字符串复制到 str 中,size 为要写入的字符的最大数目,超过 size 会被截断。

下面是 snprintf() 函数的声明。

int snprintf ( char * str, size_t size, const char * format, ... );

char buf_ch[CLASSNAME_LENGTH] = {0};

snprintf(array[i], CLASSNAME_LENGTH, "%s", buf_ch);//格式化buf_ch为字符串,并复制到array[i]中。(buf_ch中正好有CLASSNAME_LENGTH个字符)

参数

str -- 目标字符串。

size -- 拷贝字节数(Bytes)。

format -- 格式化成字符串。

... -- 可变参数。

返回值

(1) 如果格式化后的字符串长度小于等于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;如果格式化后的字符串长度大于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0

(2) int j = snprintf(buffer, 6, "%s\n", s);返回值为欲写入的字符串 s的长度,与参数size 没关系。

(输出到字符串) vsprintf()

int vsprintf(char *str, const char *format, va_list arg) 使用参数列表发送格式化输出到字符串。

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. char buffer[80];
  4. int vspfunc(char *format, ...){
  5. va_list aptr;
  6. int ret;
  7. va_start(aptr, format);
  8. ret = vsprintf(buffer, format, aptr);
  9. va_end(aptr);
  10. return(ret);
  11. }
  12. int main(){
  13. int i = 5;
  14. float f = 27.0;
  15. char str[50] = "runoob.com";
  16. vspfunc("%d %f %s", i, f, str);
  17. printf("%s\n", buffer);
  18. return(0);
  19. }
  20. 让我们编译并运行上面的程序,这将产生以下结果:
  21. 5 27.000000 runoob.com

(从字符串读取) sscanf()

int sscanf(const char *str, const char *format, ...) 从字符串读取,格式化输入到给定的字符串数组中。

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main() {
  5. int day, year;
  6. char weekday[20], month[20], dtm[100];
  7. strcpy( dtm, "Saturday March 25 1989" );
  8. sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year );//如果是int 加&
  9. printf("%s %d, %d = %s\n", month, day, year, weekday );
  10. return(0);
  11. }
  12. 让我们编译并运行上面的程序,这将产生以下结果:
  13. March 25, 1989 = Saturday

标准输出 输入

(stdout) printf

printf("ASCII 值 = %d, 字符 = %c\n", ch , ch );

(stdout)vprintf

int vprintf(const char *format, va_list arg) 使用参数列表发送格式化输出到标准输出 stdout。

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. void WriteFrmtd(char *format, ...) {
  4. va_list args;
  5. va_start(args, format);
  6. vprintf(format, args);
  7. va_end(args);
  8. }
  9. int main () {
  10. WriteFrmtd("%d variable argument\n", 1);
  11. WriteFrmtd("%d variable %s\n", 2, "arguments");
  12. return(0);
  13. }
  14. 让我们编译并运行上面的程序,这将产生以下结果:
  15. 1 variable argument
  16. 2 variable arguments

(stdout)putchar()

getchar() 和 getc()用法相同,

但putchar()和 putc()用法不同。putchar(ch);//putc(ch, stdout); 这样的效果相等。

fputc() 与 putc() 一毛一样

int putchar(int char) 把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中。

该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。

  1. #include <stdio.h>
  2. int main ()
  3. {
  4. char ch;
  5. for(ch = 'A' ; ch <= 'Z' ; ch++) {
  6. putchar(ch); //putc(ch, stdout); 这样的效果相等
  7. }
  8. return(0);
  9. }
  10. 让我们编译并运行上面的程序,这将产生以下结果:
  11. ABCDEFGHIJKLMNOPQRSTUVWXYZ

(stdout)puts()

int puts(const char *str) 把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。

如果成功,该函数返回一个非负值为字符串长度(包括末尾的 \0),如果发生错误则返回 EOF。

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char str1[15];
  6. char str2[15];
  7. strcpy(str1, "RUNOOB1");
  8. strcpy(str2, "RUNOOB2");
  9. puts(str1);
  10. puts(str2);
  11. return(0);
  12. }
  13. 让我们编译并运行上面的程序,这将产生以下结果:
  14. RUNOOB1
  15. RUNOOB2

(stdin) scanf()

int scanf(const char *format, ...) 从标准输入 stdin 读取格式化输入。

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

  1. #include<stdio.h>

  2. int main(void)

  3. {

  4. int a,b,c;

  5. printf("请输入三个数字:");

  6. scanf("%d%d%d",&a,&b,&c);

  7. printf("%d,%d,%d\n",a,b,c);

  8. return 0;

  9. }

    使用一个scanf函数提供的“%[]”格式来输入,这个格式可以让我们进行多字符的输入,同时决定输入结束的字符,只需要使用 ”%[^+我们需要停止的字符]” 下面为大家实际操作一波:

    scanf("%[^\n]", str);

(stdin) getchar() 与 getc()

getchar() 和 getc()都可用于接收 stdin ,参数不一样,

但putchar()和 putc()用法不同。putchar(ch);//putc(ch, stdout); 这样的效果相等。

fputc() 与 putc() 一毛一样

int getchar(void) 从标准输入 stdin 获取一个字符(一个无符号字符)。这等同于 getc 带有 stdin 作为参数。

int getc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。

  1. #include <stdio.h>
  2. int main (){
  3. char c;
  4. printf("请输入字符:");
  5. c = getchar();
  6. printf("输入的字符:");
  7. putchar(c);
  8. return(0);
  9. }
  10. 让我们编译并运行上面的程序,这将产生以下结果:
  11. 请输入字符:a
  12. 输入的字符:a
  13. char c;
  14. printf("请输入字符:");
  15. c = getc(stdin);
  16. printf("输入的字符:");
  17. putc(c, stdout);

(stdin) *gets()

char *gets(char *str) 从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

如果成功,该函数返回 str。如果发生错误或者到达文件末尾时还未读取任何字符,则返回 NULL。

  1. #include <stdio.h>
  2. int main(){
  3. char str[50];
  4. printf("请输入一个字符串:");
  5. gets(str);
  6. printf("您输入的字符串是:%s", str);
  7. return(0);
  8. }
  9. 让我们编译并运行上面的程序,这将产生以下结果:
  10. 请输入一个字符串:runoob
  11. 您输入的字符串是:runoob

tt

int fflush(FILE *stream)
刷新流 stream 的输出缓冲区。

int fgetpos(FILE *stream, fpos_t *pos)
获取流 stream 的当前文件位置,并把它写入到 pos。

FILE *freopen(const char *filename, const char *mode, FILE *stream)
把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。

int fseek(FILE *stream, long int offset, int whence)
设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。

void perror(const char *str)
把一个描述性错误消息输出到标准错误 stderr。首先输出字符串 str,后跟一个冒号,然后是一个空格。

C标准库-<ctype.h>

()、isalpha() 判断一个字符是否是字母

#include<ctype.h>

C语言函数大全:http://c.biancheng.net/ref/isalpha.html

posted @ 2022-12-20 15:36  bruce_lp  阅读(94)  评论(0)    收藏  举报