1 数组名称和指针变量的区别
数组名称和指针变量的区别:
1、数组名称不可以被赋值,指针变量可以被赋值;
2、进行sizeof计算时结果不同;
3、进行取地址操作结果不同(数组名称取地址得到的数字和原数组名称代表的数字一样,但是新数字被当成二维数组看待)。
使用循环操作数组时,可以使用指针变量作为循环变量。
#include <stdio.h>
int main() {
int num[] = {1, 2, 3}, pos = 0;
int *p_num = num;
/*for (pos = 0;pos <= 2;pos++) {
//printf("%d ", num[pos]);
printf("%d ", p_num[pos]);
}*/
for (p_num = num;p_num <= num + 2;p_num++) {
//printf("%d ", p_num[0]);
printf("%d ", *p_num);
}
printf("\n");
//num = NULL; 错误
p_num = num;
printf("sizeof(num)是%d,sizeof(p_num)是%d\n", sizeof(num), sizeof(p_num));
printf("&num是%p,&p_num是%p\n", &num, &p_num);
return 0;
}
2 const关键字
const关键字也可以用来声明变量,const变量是不可以被修改的(可以通过指针修改)。
const用来声明指针变量的时候不允许修改使用这个指针表示的普通变量的内容,这叫常量指针,例如:
const int *p_num;
const用来声明指针还有另一种用法,例如
int *const p_num;这样可以修改指针表示的普通变量的内容,但是不能修改指针,这叫指针常量。
#include <stdio.h>
int main() {
const int num = 3;
int num1 = 1;
//int *p_num = (int *)#
const int *p_num = #
int * const p_num1 = &num1;
//num = 7;
//*p_num = 7;
printf("num是%d\n", num);
*p_num1 = 9;
printf("num1是%d\n", num1);
//p_num1 = NULL;
return 0;
}
3 程序在内存中的分段
程序在内存中是分段保存的!
代码段:所有语句转化的数字都存储在代码段中,代码段中的内容在运行时不可以修改。
全局段落:存放全局变量和静态局部变量。
栈:随着程序的运行不断变化,局部变量,块变量以及形参都存储在这个段落里,每个函数在栈中有自己的私有空间,栈中的一段区域可能在不同的时候被不同的函数使用。
堆:存放所有动态分配的变量,必须使用语句创建和销毁。
4 字符串
字符串由一组连续的字符变量表示,第一个字符的地址可以用来表示字符串的整体,如果把这个地址记录在一个char*类型的指针变量中,则也可以用这个指针表示这个串,所有字符串都以‘\0’作为结尾。
字符串字面值是一种描述字符串的方式,例如: “abc”。字面值在程序运行时被保存在专门的段落中,这个段落的内容不可以被修改,同样的字符串字面值在程序中只有一份。连续的两个字面值可以合并成一个。
字符数组是另外一种表示字符串的方法,包含“\0”字符的数组都可以当成字符串使用,字符数组可以被修改。可以用字符串字面值对字符数组进行初始化。
c语言提供了一系列对字符串操作的标准函数 ,这些函数的使用需要包含文件string.h
strlen : 计算字符串中有效字符的个数
strcat : 合并两个字符串,合并后的结果字符串作为返回值,有可能溢出
strncat : 作用和strcat类型一样,用的好可以防止溢出
strcmp : 可以比较两个字符串的大小,比较的依据是ASC码
strncmp : 只比较前n个字符
strcpy : 字符串拷贝功能,拷贝完成后内存中有两份同一个字符串
strncpy : 只覆盖前n个字符
/*
字符串合并练习
*/
#include <stdio.h>
char *mystrcat(char *p_buf, char *p_buf1) {
char *p_dest = p_buf;
char *p_src = p_buf1;
while (*p_dest) {
p_dest++;
}
while (*p_src) {
*p_dest = *p_src;
p_dest++;
p_src++;
}
*p_dest = *p_src;
return p_buf;
}
int main() {
char buf[10] = "abc";
printf("合并结果是%s\n", mystrcat(buf, "xyz"));
return 0;
}
用fgets()函数读取字符串,不用scanf,因为用scanf会出问题,如溢出等。
fgets函数读取字符串时,可能会把最后的回车读入。
每次读完字符串后都需要检查是否输入缓冲区中还有垃圾数据,如果有,则需要清除。
#include <stdio.h>
int main() {
char buf[10] = {};
printf("请输入一个字符串:");
//scanf("%s", buf);
fgets(buf, 10, stdin);
if (strlen(buf) == 9 && buf[8] != '\n') {
scanf("%*[^\n]");
scanf("%*c");
}
printf("字符串是%s\n", buf);
return 0;
}
多个相关字符串的表示方式
1、使用二维数组(容易浪费空间,不灵活)
2、指针数组(不会浪费空间,更灵活)
二级指针(用来放置普通指针的地址的)
主函数的第二个参数用来表示多个字符串,类型可以是指针数组或二级指针。
#include <stdio.h>
int main() {
//char name[][10] = {"China", "America", "Russia"};
char *name[] = {"China", "America", "Russia"};
char **pp_name = name;
int pos = 0;
for (pos = 0;pos <= 2;pos++) {
//printf("%s\n", name[pos]);
printf("%s\n", pp_name[pos]);
}
return 0;
}
/*
主函数的参数
*/
#include <stdio.h>
int main(int argc, /*char *argv[]*/char **argv) {
int num = 0;
for (num = 0;num <= argc - 1;num++) {
printf("%s\n", argv[num]);
}
return 0;
}
/*模拟登陆*/
#include <stdio.h>
#include <string.h>
int main() {
char buf[10] = {};
int loop = 0;
for (loop = 1;loop <= 3;loop++) {
printf("请输入用户名:");
fgets(buf, 10, stdin);
if (strcmp(buf, "admin\n")) {
printf("用户名错误\n");
continue;
}
printf("请输入密码:");
fgets(buf, 10, stdin);
if (strcmp(buf, "123456\n")) {
printf("密码错误\n");
continue;
}
break;
}
if (loop <= 3) {
printf("登陆成功\n");
}
else {
printf("登陆失败\n");
}
return 0;
}
/*字符串查找*/
#include <stdio.h>
int indexof(const char *str, const char *str1) {
int pos = 0, pos1 = 0;
while (*(str + pos)) {
pos1 = 0;
while (*(str + pos + pos1) == *(str1 + pos1) && *(str1 + pos1)) {
pos1++;
}
if (*(str + pos + pos1) == *(str1 + pos1)) {
return pos;
}
else if (*(str + pos + pos1) != *(str1 + pos1) && !*(str1 + pos1)) {
return pos;
}
pos++;
}
return -1;
}
int main() {
printf("indexof(\"abc\", \"bc\")是%d\n", indexof("abc", "bc"));
printf("indexof(\"abcd\", \"bc\")是%d\n", indexof("abcd", "bc"));
printf("indexof(\"abcd\", \"bcf\")是%d\n", indexof("abcd", "bcf"));
return 0;
}
/*
成绩拆分练习
*/
#include <stdio.h>
int split(const char *p_rank, char rank[][4], int size) {
int row = 0, col = 0, pos = 0;
while (*(p_rank + pos)) {
if ('0' <= *(p_rank + pos) && *(p_rank + pos) <= '9') {
rank[row][col] = *(p_rank + pos);
col++;
}
else {
rank[row][col] = 0;
row++;
col = 0;
}
pos++;
}
for (pos = 0;pos <= row - 1;pos++) {
printf("%s\n", rank[pos]);
}
return row;
}
int ave(char rank[][4], int size) {
int pos = 0, pos1 = 0, sum = 0, num = 0;
for (pos = 0;pos <= size - 1;pos++) {
num = 0;
pos1 = 0;
while (rank[pos][pos1]) {
num = 10 * num + rank[pos][pos1] - '0';
pos1++;
}
sum += num;
}
return sum / size;
}
int split1(char *p_rank, char *rank[], int size) {
int pos = 0, num = 0;
rank[0] = p_rank;
num = 1;
while (*(p_rank + pos)) {
if (*(p_rank + pos) == ',') {
*(p_rank + pos) = 0;
rank[num] = p_rank + pos + 1;
num++;
}
else if (*(p_rank + pos) == '\n') {
*(p_rank + pos) = 0;
}
pos++;
}
for (pos = 0;pos <= num - 1;pos++) {
printf("%s\n", rank[pos]);
}
return num;
}
int main() {
char buf[40] = {};
char rank[10][4] = {};
char *p_rank[10] = {};
int size = 0;
printf("请输入成绩:");
fgets(buf, 40, stdin);
//size = split(buf, rank, 10);
//printf("平均成绩是%d\n", ave(rank, size));
printf("共有%d个成绩\n", split1(buf, p_rank, 10));
return 0;
}
/*
字符串拷贝练习
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//字符串合并函数,参数代表两个已经存在的字符串
//返回值表示新字符串
char *mystrcat(const char *p_str, const char *p_str1) {
char *p_ret = (char *)malloc(strlen(p_str) + strlen(p_str1) + 1);
if (p_ret) {
strcpy(p_ret, p_str);
strcat(p_ret, p_str1);
}
return p_ret;
}
void mystrcat1(char **pp_str, const char *p_str, const char *p_str1) {
*pp_str = (char *)malloc(strlen(p_str) + strlen(p_str1) + 1);
if (*pp_str) {
strcpy(*pp_str, p_str);
strcat(*pp_str, p_str1);
}
}
//字符串拷贝函数
//参数代表一个已经存在的字符串
//返回值代表拷贝生成的新字符串
char *mystrcpy(const char *p_str) {
char *p_ret = (char *)malloc(strlen(p_str) + 1);
if (p_ret) {
strcpy(p_ret, p_str);
}
return p_ret;
}
void mystrcpy1(char **pp_str, const char *p_str) {
*pp_str = (char *)malloc(strlen(p_str) + 1);
if (*pp_str) {
strcpy(*pp_str, p_str);
}
}
int main() {
//char *p_str = mystrcpy("abc");
char *p_str = NULL;
mystrcpy1(&p_str, "abc");
if (p_str) {
printf("%s\n", p_str);
free(p_str);
p_str = NULL;
}
//p_str = mystrcat("abc", "xyz");
mystrcat1(&p_str, "abc", "xyz");
if (p_str) {
printf("%s\n", p_str);
free(p_str);
p_str = NULL;
}
return 0;
}