Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830327
  • 博文数量: 85
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 952
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-19 22:52
文章分类

全部博文(85)

文章存档

2011年(1)

2008年(1)

2007年(60)

2006年(23)

我的朋友

分类: C/C++

2007-10-20 14:48:46

[旧blog文章搬移]

Ø        C语言的注释

注释(Comment)在/*……*/之间,可以换行。

有时在调试程序时,或者某段代码留作后备和扩展使用时,往往需要将其注释掉,但在C语言中,如果用/*……*/来这样做,可能会发生问题。例如:

int count;

/*count=count+origin; /*add original number to total count*/

**if (count>=MAX)

**    count=MAX;

**end

*/

原意是要注释掉第二行开始的所有代码,但是,由于该段代码中存在注释,实际注释掉的部分是蓝色注释符中间的部分。因为C编译器会将离第一个起始符/*最近的结束符*/与其匹配。即注释不可嵌套。

另:单行注释也可采用//….                                                                                

 

       从逻辑上删除一段代码的更好更安全的办法是使用# if 指令。如下:

       # if 0

              statement

       # endif

                                                                                                                               

Ø        预处理命令include和头文件

若有一些声明(函数、变量或常量等)需要用于多个源文件,可以单独编辑为一个头文件,然后用# include指令把它包含到需要使用这些声明的源文件中。这样就只需要在一个地方声明,便于维护。

 

Ø        main函数的形式

可移植的main定义方式:http://genial.yculblog.com/post.164716.html

1 int main(void)
2)   int main(int argc, char ** argv)
3)   int main(int argc, char *argv[ ])
4)  
等价于以上定义的定义。


除了可移植性的上述定义之外,如下方式并不非法,但是并不是所有编译器都支持:

1
int mainint argc

2
int mainint argcchar**argvchar**env

 

int main ( int argc, char* argv[]),这是一个典型的main函数的声明。这是为了在执行程序时需要向程序传递参数,参数argc代表了输入参数的个数,char *argv[]表示传入的参数的字符串,是一个字符串数组;或说是一个指针数组,其中每个指针指向一个字符串,即一个参数。

argc为主程序的参数个数(包括程序名  
argv[0]
为程序名
 
argv[1]
为第一个参数

argv[n]为第n个参数

例如:

#include
main (int argc,char *argv[])
{
    int I = 0;
    printf("\n
命令行中可执行文件名为:
%s \n", argv[0]);
    printf("\n
总共有%d个参数:
\n", argc);
    while((argc--)>0)
    printf("%s \n", argv[I++]);
}

若文件名为test.c,编译为test.exe,在命令行下输入:test.exe abc efg ok 则运行结果为:

命令行中可执行文件名为:test.exe

总共有4个参数:test.exe abc efg ok

 

Ø        C函数的参数传递

所有传递给函数的参数都是按值传递

Int   n_columns;

Int   columns[MAX_COLS];

n_columns=read_column_numbers(columns, MAX_COLS);

     传址调用:数组参数以引用(reference)形式进行传递;实际上,传递的还是数组的首地址值,在函数中对相关地址进行操作,也就影响了相应存储器的内容,因此,数组名作为参数时,就会产生引用传递的效果。

     传值调用:标量和常量按值(value)传递,函数只是把参数传过来的值拷贝一份暂时存储在一个变量(通常为局部变量,也可以是全局变量)中,因而在使用参数值时实际上是对临时变量的操作,而不影响原来的实参。

注意:函数声明时并不指定数组的长度。因为传递时只传数组首地址,因而函数并不检查数组长度是否溢出,因而如果需要知道数组的长度,其值必须作为一个单独的参数传递给函数。

 

Ø        字符串操作函数简介

     getcharputchargetchar()函数从标准输入读取一个字符(以整型接受)并返回它的值,若无输入则返回EOFpuchar()则接受一个整型参数并在标准输出中打印该字符。

     getsputsgets ( )函数从标准输入读取一行文本并将其存入作为参数传递给它的数组中。一行输入由一串字符组成,以一个换行符结尾,gets()函数丢弃换行符,并在末尾存储一个NUL作为结束符。puts()函数是gets()函数的输出版本,将指定的字符串写到标准输出并在末尾添加一个换行符。如puts(“I am an excellent software engineer.”)。可否为字符串名(首地址)?可以。

注意:若输入行过长可能导致gets函数溢出,应换用fgets

     strncpy(target, source, n):前个参数分别表示目标字符串和源字符串的地址,第3个参数指定需要复制的字符数,把source字符串复制到target指定的起始地址段。strcpy(target, source)功能一样,但不指定复制个数。

     strcat(a ,b) :把b字符串添加到a末尾,注意溢出处理。

     strlen(str):返回字符串长度。包括结束符NUL在内吗?不包括。

     strchr(str, char)在字符串中搜索某字符第一次出现的位置,若成功则返回指向该位置的指针,否则返回NULL指针。strstr(str , substr)则在字符串str中搜索字符串substr

 

Ø      其他

l         stdlib.h定义了EXIT_SUCCESSEXIT_FAILURE符号。跳出函数时可用exit函数,例如exit(EXIT_FAILURE)或者exit(EXIT_SUCCESS);也可直接return EXIT_SUCCESS.

l         函数声明中,被声明为const的参数,表明函数不会修改函数调用者所传递的这类参数。例如:void reaarange (char *output, char const *input, int n_columns, int const columns[] );

l        NULNULLNULASCⅡ字符集中’\0’字符的名字,字节模式为全0NULL指一个其值为0的指针。它们都是整型值,其值也相同。不过最好在相应场合使用相应符号。需要提醒的是,NULLstdio.h中定义,而在C语言中并没有对NUL进行预定义。因此若要使用NUL来代替字符常量’\0’,必须自行定义。

l        C语言不存在字符串“string”数据类型,只约定:字符串就是一串以NUL字节结尾的字符。即NUL是字符串终止符,但它本身并不被看作是字符串的一部分。

l        函数调用失败:例如调用gets()函数时不存在输入行,返回NULL值,否则返回非NULL值或1,表示该行被成功读取。调用getchar()函数时若输入中不存在任何字符,返回常量EOF(在stdio.h中定义),用于提示文件的结尾。不过这应该不算是函数调用失败。

l       函数形参和实参名不必相同。

l       scanf(“%d”, &columns[num]),该函数读入一个由格式码标志的数据类型值,并存入地址为&columns[num]的存储空间,也即columns[num]=输入值。注意scanf函数不认空格、制表符和换行符等,输入之前的空白被跳过,而有输入之后的空白表示该次输入结束。

l       C语言允许将赋值操作、函数调用等包含在whileif等语句的条件判断中,这样可以消除冗余语句,例如:while((ch=getchar())!=0&&ch!=’\0’).

 

Ø      练习

1.7.5 关于scanf( ),读入字符串到字符指针department时,应该定义一个字符数组,即:   char department[20];若定义为字符指针即char *department,使用gcc 3.4.4cygwin环境下测试时,编译可以通过,运行时则报错:Segmentation fault (core dumped ),若事先用malloc分配内存,则可;而使用gcc 3.4.2 MinGui下测试时,则运行正确。

读入字符串时应写为:scanf(“%s”,department ),前面不用&,因为department已经代表了字符串数组的首地址。

     另外,涉及到字符串操作时,在string.h中定义了专门的字符串操作函数,使用专用函数会更加方便(实际操作时,发现不必包含这个头文件)。例如这里从标准输入读入一个字符串,可以使用函数gets( ),与scanf( )不同的是,gets()不需要指明输入格式,它只接受字符串,而且参数可以是定义为字符串指针类型的变量,即定义char *department;调用gets(department)也可(但是实际操作时,不论是gcc还是VC++,这样都会出错,编译时则有warning: local variable 'department' used without having been initialized);要在gets()之前为department分配内存:department=(char *)malloc(20),这样就没有问题了。

1.8.2

#include

#include

#include

 

int main(void)

{

      unsigned int row_num;

      unsigned int row_count;

      unsigned int row_length;

      char **row_content;

     

      puts("Please enter the number of rows to be input:");

      scanf("%d",&row_num);

      puts("Please enter the maximum number of characters for each row:");

      scanf("%d",&row_length);

      puts("Now please type what you want to input:");

      for (row_count=0;row_count

       row_content[row_count]=(char *)malloc(row_length);

       scanf("%s",row_content[row_count]);/*这里使用gets(row_content[row_count]在运行时有问题,不知道为什么?*/

      }

      for (row_count=0;row_count

       printf("%d:%s\n",(row_count+1),row_content[row_count]);

      }

}


阅读(1865) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~