c笔记——总结几点

1、   C语言格式自由,但编写程序时遵守一些约定会使代码更加容易阅读和修改,清晰显示程序很重要,但让读者知道程序是做什么的更加重要,注释就是实现这个功能,格式优美,让人舒服。

2、   注释掉一段代码,即使这段代码在程序中不起作用,但并没有将其真正从源文件中删除,要从逻辑上删除一段代码更好的办法是使用#if指令,即:

#if  0

              statements

          #endif

在  #if和#endif之间的程序段可以有效的从程序中去除,即使这段代码之间原先存在注释也无妨,预处理指令的作用很大。

3、函数原型:每个原型以一个类型名开头,表示函数返回值的类型,跟在返回类型名后面的是函数的名字,然后跟着函数期望接受的参数。

如:void rearrange(char *output,char const *input,int n_columns,int const columns[]);//rearrange函数接受四个参数,关键字void表示函数并不返回任何值.

4、在C语言中,数组参数是以引用形式传递的,也就是传址调用,而标量和常量则是按值传递。被调用函数无法修改调用函数以传值形式传递给它的参数,然而,当被调用函数修改数组参数的其中一个元素时,调用函数所传递的数组就会被实际的修改,如下,给出关键部分:

.........

#define MAC_COLS  20

.......

int main()

{

....

int columns[MAX_COLS];

....

n_columns = read_column_numbers(columns,MAX_COLS);//调用函数read_column_numbers,数组columns和MAX_COLS                                                                                                                                            //所代表的常量20作为参数传 递给这个函数

....

}

.......

5、和绝大多数语言一样,C语言中形式参数的名字和实际参数的名字并没有什么关系,可以让两者相同,也可不同。

6、while(num < max && scanf("%d",&columns[num]) == 1 && columns[num] >= 0)

此while语句中循环的测试条件由三部分组成:num<max为了确保函数不会读取过多的值,从而导致数组溢出;scanf("%d",&columns[num]) == 1,scanf函数每次调用时都从标准输入读取一个十进制整数,如果转换失败,函数返回0,整个循环终止,若输入的字符可以合法的转换为整数,那么这个值就会转换为二进制数存储于数组元素columns[num]中,scanf函数返回1表示成功; columns[num] >= 0,这个表达式确保函数所读取的值是正数。整个语句中第二个&&操作符确保在scanf函数成功读取了一个数后才对这个数进行正负测试。&&:逻辑与,&:按位与。

Note:scanf函数实现的原理:所有标量参数的前面必须加上一个"&"符号,数组前面不需要加上"&"符号,但是数组参数中如果出现了下标引用,即实际参数是某个特定元素,前面必须加"&".

7、while ((ch = getchar()) != EOF && ch != ‘\n‘);

等价于:

ch = getchar();

while (ch != EOF && ch != ‘\n‘);

 ch = getchar();

getchar函数从标准输入读取一个字符并返回它的值,如果输入中不再存在任何字符,函数就会返回EOF(在stdio.h中定义),用于提示文件的结尾。从getchar函数返回的值被赋给变量ch,然后把它与EOF进行比较,若ch = EOF,为假,循环终止,若非如此,再把ch与换行符比较,若相等,则循环终止。即只有当输入尚未到达文件尾且输入的字符并非换行符时,表达式为真,继续读取下一个字符,达到剔除当前输入行最后的剩余字符(终止符的换行符或其他字符)。C可以把复制操作蕴含于while语句内部,可以消除冗余语句。

8、get函数从标准输入读取一行文本并把它存储于作为参数传递给它的数组中,一行输入由一串字符组成,以一个换行符(newLine)结尾。gets函数丢弃换行符,并在该行的末尾存储一个人NUL字节(一个NUL字节是指字节为全0的字节,类似‘\0‘这样的字符常量)。gets函数返回一个非NULL值,表示该行已被成功读取,当gets函数被调用但事实上不存在输入行时,它就返回NULL值,表示它达到了输入的末尾(文件尾)。

约定:字符串就是就是一串以NUL字节结尾的字符,NUL是作为字符串终止符,它本身不被看作是字符串的一部分。字符串常量(string literal)就是源程序中被双引号括起来的一串字符,例如,字符串常量:"Hello",在内存中占据6个字节的空间,按顺序分别是H、e、l、l、o和NUL.

note:NUL是ASCII字符集中‘\0‘字符的名字,它的字节模式为全0,NULL指一个其值为0的指针,他们都是整型值,其值相同,可以互换使用。

.....

int main()

{

.....

while(gets(input) != NULL)
{
printf("Original input:%s\n",input);
rearrange(output,input,n_columns,columns);//rearrange函数的三个参数是传递给函数的值
printf("Rearranged line:%s\n",output);//显示输入行重新整理后的结果
}
return EXIT_SUCCESS;//表示程序成功执行

}

.....

9、strncpy函数把选中的字符从输入行复制到输出行中可用的下一个位置。strncpy函数的前两个参数分别是目标字符串和源字符串的地址,在这个调用中,目标字符串的位置是输出数组的起始地址向后偏移output_col列的地址,源字符串的位置是输出数组的起始地址向后偏移columns[col]个位置的地址,第3个参数指定需要复制的字符数,输出列计数器随后向后移动nchars个位置。循环结束后,输出字符以一个NUL字符作为终止符。

...

int main()

{

...

}

...

void rearrange(char *output,char const *input,int n_columns,int const columns[])

{

...

strncpy(output + output_col,input + columns[col],nchars);
output_col += nchars;

output[output_col] = ‘\0‘;

...

}

补充说明:

strcpy:与strncpy相似,但没有限制需要复制的字符数量,它接受两个参数:第二个字符串参数将被复制到第一个字符串参数,第一个字符串参数将被覆盖。

stract:接受两个参数,把第二个字符串参数添加到第一个字符串参数的末尾。

注:第一个字符串参数不能是字符串常量,确保目标字符串有足够的空间。

strchr:第一个参数字符串,第二个参数一个字符,实现搜索功能:在字符串参数内搜索字符参数第1次出现的位置,成功返回指向这个位置的指针,失败返回一个NULL指针。

strstr:与strstr类似,区别第二个参数是字符串,搜索第二个字符串在第一个字符串中第1次出现的位置。

完整代码:

/*
**这个程序从标准输入中读取输入行并在标准输出中打印这些输入行
**每个输入行的后面一行是该行内容的一部分
**
**输入的第一行是一串列标号,串的最后以一个负数结尾
**这些列标号成对出现,说明需要打印的输入行的列范围
**例如:0 3 10 12 -1表示第 0 列到第 3 列,第 10 列到第 12 列的内容将被打印
*/
//预处理器指令
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20 //所能处理的最大列号
#define MAX_INPUT 1000 //每个输入行的最大长度

int read_column_numbers(int columns[],int max);
void rearrange(char *output,char const *input,int n_columns,int const columns[]);
int main()
{
int n_columns;//进行处理的列标号
int columns[MAX_COLS]; //需要处理的列数
char input[MAX_INPUT];//容纳输入行的数组
char output[MAX_INPUT];//容纳输出行的数组
/*
**读取该串列标号
*/
n_columns = read_column_numbers(columns,MAX_COLS);
/*
** rearrange函数:处理输入行,将指定列的字符连接在一起,输出行以NUL结尾
** while 当还可以读取另一行输入时
** 打印输入行
** 对输入行进行重新整理,把它存储于output数组
** 打印输出结果
*/
while(gets(input) != NULL)
{
printf("Original input:%s\n",input);
rearrange(output,input,n_columns,columns);
printf("Rearranged line:%s\n",output);
}
return EXIT_SUCCESS;//表示程序成功执行
}
/*
**读取列标号,如果超出范围则不予理会
*/
int read_column_numbers(int columns[],int max)
{
int num = 0;
int ch;
/*
**取得列标号,如果所读取的数小于0则停止
*/
while(num < max && scanf("%d",&columns[num]) == 1 && columns[num] >= 0)
num += 1;
/*
**确认已经读取的标号为偶数个,因为它们是以对的形式出现的
*/
if(num % 2 != 0)
{
puts("Last column number is not paired.");
exit(EXIT_FAILURE);
}
/*
**丢弃该行中包含最后一个数字的那部分内容
*/
while ((ch = getchar()) != EOF && ch != ‘\n‘);
return num;
}
/*
**处理输入行,将指定列的字符连接在一起,输出行以 NUL 结尾
*/
void rearrange(char *output,char const *input,int n_columns,int const columns[])
{
int col; //columns数组的下标
int output_col; //输出列计数器
int len; // 输入行的长度

len = strlen(input);
output_col = 0;
/*
**处理每对列标号
*/
for(col = 0;col < n_columns;col += 2)
{
int nchars = columns[col + 1] - columns[col] + 1;//需要复制的字符数
/*
**如果输入行结束或输出行数组已满,就结束任务
*/
if(columns[col] >= len || output_col == MAX_INPUT - 1)
break;
/*
**如果输出行数组空间不够,只复制可以容纳的数据
*/
if(output_col + nchars > MAX_INPUT - 1)
nchars = MAX_INPUT - output_col - 1;
/*
**复制相关数据
*/
strncpy(output + output_col,input + columns[col],nchars);
output_col += nchars;
}
output[output_col] = ‘\0‘;
}

时间: 2024-09-30 21:53:01

c笔记——总结几点的相关文章

【安全牛学习笔记】

弱点扫描 ╋━━━━━━━━━━━━━━━━━━━━╋ ┃发现弱点                                ┃ ┃发现漏洞                                ┃ ┃  基于端口五福扫描结果版本信息(速度慢)┃ ┃  搜索已公开的漏洞数据库(数量大)      ┃ ┃  使用弱点扫描器实现漏洞管理            ┃ ╋━━━━━━━━━━━━━━━━━━━━╋ [email protected]:~# searchsploit Usage:

51CTO持续更新《通哥的运维笔记》

<通哥的运维笔记>将持续在51CTO网站更新,希望大家多多关注.互相学习,后期,我将会退出<通哥的运维笔记>系列视频教程,希望带给大家最大的收获,帮助大家更好的学习.进步.<通哥的运维笔记>主要从linux系统管理.虚拟化.cloudstack云平台以及网络管理之CCNA.CCNP.CCIE,等等方面深入讲解.

WPF笔记整理 - Bitmap和BitmapImage

项目中有图片处理的逻辑,因此要用到Bitmap.而WPF加载的一般都是BitmapImage.这里就需要将BitmapImage转成Bitmap 1. 图片的路径要用这样的,假设图片在project下的Images目录,文件名XXImage.png. pack://application:,,,/xxx;component/Images/XXImage.png 2. 代码: Bitmap bmp = null; var image = new BitmapImage(new Uri(this.X

java String 类 基础笔记

字符串是一个特殊的对象. 字符串一旦初始化就不可以被改变. String s = "abc";//存放于字符串常量池,产生1个对象 String s1=new String("abc");//堆内存中new创建了一个String对象,产生2个对象 String类中的equals比较字符串中的内容. 常用方法: 一:获取 1.获取字符串中字符的个数(长度):length();方法. 2.根据位置获取字符:charAt(int index); 3.根据字符获取在字符串中

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

学习笔记之邮件发送篇

用脚本语言发送邮件是系统管理员必备技能 对系统定期检查或者当服务器受到攻击时生成文档和报表. 发布这些文档最快速有效的方法就是发送邮件. python中email模块使得处理邮件变得比较简单 发送邮件主要用到了smtplib和email两个模块,这里首先就两个模块进行一下简单的介绍: 本段摘录于    http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.html 1.smtplib模块 smtplib.SMTP([host[, p

15.1-全栈Java笔记:Java事件模型是什么?事件控制的过程有哪几步??

应用前边两节上一章节的内容,大家可以完成一个简单的界面,但是没有任何的功能,界面完全是静态的,如果要实现具体功能的话,必须要学习事件模型. 事件模型简介及常见事件模型 对于采用了图形用户界面的程序来说,事件控制是非常重要的. 一个源(事件源)产生一个事件并把它(事件对象)送到一个或多个监听器那里,监听器只是简单地等待,直到它收到一个事件,一旦事件被接收,监听器将处理这些事件. 一个事件源必须注册监听器以便监听器可以接收关于一个特定事件的通知. 每种类型的事件都有其自己的注册方法,一般形式为: v

Java设计模式学习笔记,一:单例模式

开始学习Java的设计模式,因为做了很多年C语言,所以语言基础的学习很快,但是面向过程向面向对象的编程思想的转变还是需要耗费很多的代码量的.所有希望通过设计模式的学习,能更深入的学习. 把学习过程中的笔记,记录下来,只记干货. 第一部分:单例模式的内容 单例模式:类只能有一个实例. 类的特点:1.私有构造器:2.内部构造实例对象:3.对外提供获取唯一实例的public方法. 常见的单例模式实现有五种形式: 1.饿汉式. 2.懒汉式. 3.双重检查锁式. 4.静态内部类式. 5.枚举式. 以下分别

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

机器学习笔记_PRML_Adaboost 算法的原理与推导

转自:http://blog.csdn.net/v_july_v/article/details/40718799 Adaboost 算法的原理与推导 1 Adaboost的原理 1.1 Adaboost是什么 AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出.它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器.同时,在每一轮中加