目录
一.前言
这篇文章将通过一个实例对c语言里的知识点的概念及作用进行介绍简单讲解。这篇文章主要面向c语言0基础的人,看一下c语言是怎么解决和实现一个问题的。
二.实例
我将直接讲一个例子,此例子包含了大多数c语言的基础知识,后面就可以从例子中介绍c语言各个知识点的作用。此例子来自《c和指针》,我自己进行了部分修改。
问题描述:输入n个数字代表想输出的列数,如输入:3 5,就需要裁剪出第3列到第5列的字符,n不大于20,这n个数字以-1作为结尾;接着换行输入N行英文句子,最后则会将裁剪好的句子打印出来。
例子1:输入: 3 7 -1
hello world!
输出:lo wo //c语言中字符串的下标是从0开始计数的,所以h是第0列,第三列则是l
例子2:输入: 0 2 6 7 -1
Hello there, how are you?
I am fine, thank you.
输出:Helth //"Hel"是0到2列的字符,"th"是6到7列的字符
I ain //"I a"是0到2列的字符,空格也算一个字符,"in"是6到7列的字符
例子3:输入: 4 9 12 20 -1
Hello there, how are you?
I am fine, thanks .
see you !
Bye
输出:o ther how are
fine, hanks .
you !
接下来是实现的代码,可以大致浏览过后直接跳到第三部分。
代码1:
//每个输入行的后面一行是该行内容的一部分。
//输入的第1行是一串列标号,串的最后以一个负数结尾。这些列标号成对出现,说明需要打印的输入行的列的范围。
//例如,0 3 10 12 - 1表示第0列到第3列,第10列到第12列的内容将被打印。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20 //最大列数为20
#define MAX_INPUT 1000//输入的每一行句子最多有1000个字符
//函数声明
int read_col_numbers(int col_arr[]); //此函数的功能为——读取列的数,即读入例子中的0 3 10 12 -1,返回值为col_arr数组中的元素个数
void rearrange(char* output, char* const input, int n_col_arr, int const col_arr[]);
//此函数名为重新排列,即将输入的英文句子接受放入input中,再将重新排列后的结果放到要输出的output中,返回值为空
int main()
{
//定义变量
int n_col_arr;
int col_arr[MAX_COLS];
char input[MAX_INPUT] = { 0 };
char output[MAX_INPUT] = { 0 };
int a = strlen(output);
//调用read_col_numbers函数,将数据0 3 10 12 -1读取到col_arr数组中,并返回数组中的个数即4,因为-1代表结束标志所以不算
n_col_arr = read_col_numbers(col_arr);
//将一个句子放到input中,调用rearrange函数,再打印output,再利用循环语句重复这段操作直到所有句子处理完毕
while (gets(input) != NULL)
{
rearrange(output, input, n_col_arr, col_arr);
printf("output:%s\n", output);
memset(output, 0, strlen(output));
}
//执行完毕,返回
return EXIT_SUCCESS;//EXIT_SUCCESS是<stdlib.h>中定义的符号,数值上等于0,所以也可以直接return 0;
}
//函数实现
int read_col_numbers(int col_arr[])
{
int n = 0;//将要返回给n_col_arr的值
char tmp_ch;//一个临时的字符型变量
while ((scanf("%d",&col_arr[n]))!=EOF && col_arr[n]>=0 && n<=20)//当scanf读取成功并且读取的数大于0,即不为-1,并且n不大于20,循环就不会结束
{
n++;
}
if (n % 2)//如果n为奇数则进入
{
puts("the column numbers if not paired.");
exit(EXIT_FAILURE);
}
while ((tmp_ch = getchar()) != EOF&&tmp_ch != '\n')//将-1后输入的数全部舍弃直到遇到'\n'
;
return n;
}
void rearrange(char* output, char* const input, int n_col_arr, int const col_arr[])
{
int output_col = 0;
int nchars;
for (int i = 0; i < n_col_arr; i += 2)
{
nchars = col_arr[i + 1] - col_arr[i] + 1;
if (output_col + nchars>MAX_INPUT - 1)
{
nchars = MAX_INPUT - 1 - output_col;
}
if (output_col==MAX_INPUT-1||strlen(input) <= col_arr[i])
{
break;
}
strncpy(output+output_col, input + col_arr[i], nchars);
output_col += nchars;
}
}
三.讲解
1.数据类型
我们从上面的问题开始分析,这个题简单说就是要计算机接收我们输入的数字和英文,然后按照数字去裁剪英文。那么我们是不是先要让计算机记录我们输入的数字和英文,而数字和英文显然是不一样的,所以要将他们进行分类。在c语言中,整数的数据类型称为整型,记作int;字母的数据类型称为字符型记作char。c语言中有七种默认数据类型,分别是
2.变量和常量
(1).定义变量
我们知道了什么是数据类型,但还没法将数据储存在计算机中,于是就需要用到变量,变量就相当于一个容器,一个变量就可以存储一个数据。在上述代码中的19~23行,数据类型后空格,再加上一个英文单词就是在定义变量,这个英文单词就是变量名,变量名只能由字母,数字或下划线组成,数字不能作为开头且该变量名不能是关键字。如
int i_1,char _1; 正确
int 1n, char N; 错误
int char,char main; 错误
第20~22行变量名后带了[ ]符号,这是数组的符号,将在第5点数组和字符串中讲。
(2).变量的分类
1.局部变量
上述的19~23行的变量都是在main函数内定义的,因此都为局部变量。
局部变量的作用域是变量所在的局部范围。
2.全局变量
不在函数内定义的变量
代码2:
int i = 0;
int main()
{
return 0;
}
如代码2,i就是一个全局变量。全局变量的作用域是整个工程。
(3).常量
#include <stdio.h>
//举例
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
//字面常量演示
3.14;//字面常量
1000;//字面常量
//const 修饰的常变量
const float pai = 3.14f; //这里的pai是const修饰的常变量
pai = 5.14;//是不能直接修改的!
//#define的标识符常量 演示
#define MAX 100
printf("max = %d\n", MAX);
//枚举常量演示
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
return 0;
}
4.操作符
我们定义了一个变量,但此时里面是一堆垃圾数据,所以需要我们给他赋予一个值。此时就需要用赋值操作符 = ,在变量名后加上赋值操作符就可以进行赋值,在定义时顺便赋值就称为初始化。赋值时需要注意该变量的数据类型,如char型变量需赋值字符 如:'a' '&';int型需赋值整数,如1,3;float需赋值带小数的值,如1.0,2.1。
int age = 150;
float weight = 45.5f;(f说明这个数是浮点型,如果不写编译器会默认他是double型)
char ch = 'w';(单个字符都需要写在单引号内)
注:因为char型数据底层在存储时也是用整数去表示字符的,每个字符都有对应的数值,具体可以查阅ASCII码表。如'a'在ASCII码表中对应的数为97,所以char a = 'a'; 与 char a = 97; 功能上是一样的。
至此,我们就可以将输入进去的数字和句子保存在计算机中了。
除赋值操作符之外,在上述代码中可以看到许多如:= % + - & 等符号,他们都具有不同的功能。c语言中常用的操作符有以下符号。(先不做讲解)
5.数组和字符串
(1).概念
我们现在已经可以定义变量去存储数据了,但是我们要输入进去的数字和字母都非常多,如果用一个个变量去存储将非常麻烦,所以便有了一个新的概念——数组。你会发现我在第20~22行中定义的变量后带了[ ],代表他们是数组。数组可以一次定义非常多的变量,具体个数写在[ ]里面。如 int[2] 就代表两个地址相邻的int型变量组成的数组,而char[2]就是两个地址相邻的字符型变量组合在一起,它也是数组,但由于是一串字符型数据,因此称为字符串,我们就可以用它来存放一整个句子。有了数组,在我们想申请大量数据时就不需要一个个去申请,而是能直接批量申请。
(2).使用
如我们需要5个int数据 int arr[5];
要将他们初始化需要用{} int arr[5]={1,2,3,4,5};
访问其中的第一个并赋值给a int a=arr[0];
6.函数
现在我们有了能存放大量数据的容器了,就可以开始从计算机键盘上开始输入数据,那要怎么让计算机知道我们要从键盘输入数据呢?这时就需要用一个库函数scanf
(1).scanf使用
代码4:
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
printf("%d %d", num1, num2);
return 0;
}
如代码4中,我定义了两个变量num1和num2初始化为0,调用了scanf后我就能从键盘输入两个数将他们重新赋值。除了scanf,在代码4中还有两个函数,一个是运行程序必备的main函数,所以的程序都需要它才能运行,因为他就是程序的入口。另一个是printf函数,他的作用是将num1和num2打印到屏幕上。由于篇幅有限这些函数的具体使用方法这里不做展开。
在代码1的29行中可以看到一个gets函数,他的功能与scanf类似,都是将从键盘输入的数据放到变量中。gets是从键盘获取一个句子,在这段代码中它的作用是将我输入的句子放到input数组里面。
(2).自定义函数
现在我们已经将一串数字和几串句子输入到计算机中了,于是就需要开始剪切句子。如代码1的第12和13行,我在那里定义了两个函数,
int read_col_numbers(int col_arr[]);
void rearrange(char* output, char* const input, int n_col_arr, int const col_arr[]);
read_col_number和rearrange是他们的函数名,当我们要使用函数时就需要用它的名字才能调用它。int和void是他们的返回值的数据类型,void表示该函数无返回值。括号里面是该函数的传参。我们从代码中来解读更容易理解。
在代码1中,我在12行定义了read_col_numbers,从他的名字可以知道我将赋予它的功能是读取列的数字,也就是我要它将我从键盘输入的一串数字保存起来。而我要然他保存在我22行定义的名为col_arr的数组中,所以我需要将col_arr当做参数放在read_col_numbers的括号内,最后该函数会返回一个int型数据,所以我们可以用一个int型变量来接收它,可以看到我用的是n_col_arr。这个函数具体会返回什么取决于你在实现它的时候怎么写,我让他最终返回我输入的数的个数,那么我n_col_arr最终拿到的就是输入的数的个数。第40行后面就是实现的代码。
rearrange就是我用来负责剪切的函数,我将output,input,n_col_arr,col_arr传给rearrage函数,他就会从input中拿到句子,按col_arr中的数字对其进行裁剪,最后放回output数组中,我们就可以用printf将裁剪好的句子进行输出打印了。rearrange的实现代码在60行以下。
7.选择语句和循环语句
c语言的语句有三种,分别是顺序语句、选择语句和循环语句。(具体用法不做详解)顺序语句就是指代码会从main函数开始自上而下运行,而选择语句和循环语句就可以用来处理特殊情况。在刚刚的我说29行的gets是从键盘中获取一个句子放到input里,但这道题显然不止一个句子,这时就需要用到循环语句,可以看到在29行有一个关键词while,除他之外c语言还有for循环和do……while循环。选择语句也是为了处理一些特殊情况,如代码1的50行的if(),if是一个选择语句的关键词,()里面放条件语句,就可以做到满足条件就运行,不满足我给的条件就不运行。有了三个语句就可以处理生活中几乎所有问题了。
8.注释
从上面的代码中可以看到,每当我写中文时总是会加上/* */或//,这就是注释,加上它们之后编译器就不会你后面输入的内容当成代码。所以代码中有不需要的代码可以直接删除,也可以注释掉,或者代码中有些代码比较难懂,可以加一下注释文字
9.转义字符
在打印数据时的一些特殊操作