C第九天
2015-03-05 11:57
197 查看
第九课 指针与字符串
一、指针
1....
2....
3.指针的用法
2)指针也可以作为函数的返回值,但是不要返回指向局部变量的指针。因为函数返回以后,其局部变量所占用的内存将随函数栈一起被释放,所得到的指针为野指针。可以返回全局变量、静态局部变量、实参变量以及成员变量的指针。因为这些变量在函数返回以后依然有效。
int foo (void) {
return 10;
}
a = foo ();
int* foo (void) {
...
return p;
}
int* foo (void); // 函数声明,声明一个没有参数,返回int*的foo反函数
int (*foo) (void); // 函数指针
void foo (void) {
}
没有返回值的函数。
4.指针计算
1)一个指针型数据可以和一个整数做加减法计算,表示地址计算。所得结果与指针的类型有关。
int型指针+1:地址+4
short型指针+1:地址+2
char型指针+1:地址+1
...
X型指针+/-N:地址+/-N*sizeof(X)
2)通过指针计算可以访问数组中的元素。所谓的下标运算“[]”,其本质就是指针计算。
3)相同类型的指针之间可以做减法运算,所得为两个指针之间的距离,以指针类型为单位。
5.数组和指针
1)数组名就是数组的首地址,即首元素的地址,其本质就是一个指针,但其类型为常量。
2)以数组为参数的函数,所传递的实参是数组的首地址,而形参就是数组元素类型的指针。
6.常量、常量指针和指针常量
1)const可以修饰普通变量,该变量就会被当做常量来处理,即其值一经初始化就再不能被修改。
2)常量指针:指向常量的指针,即无法通过该指针修改其目标。
const int* p;
int const* p;
3)指针常量:指针型的常量,即无法修改其值的指针。
int* const p;
const int* const p; // 常量指针常量,p本身不能改,其目标亦不能改
二、字符串
1.在C语言中没有专门的字符串类型,通常情况下,字符串可以用三种方式表示:
1)字面值方式:"hello world"。不能修改,但是可以被赋值给变量,并在变量中修改。字面值方式的字符串后面自动追加'\0'结束符。字面值可以拼接:
"hello ""world"
" tarean" ==> "hello world tarena"
2)字符数组方式:char str[] = {...};以char型数组表示字符串,注意结尾符'\0',必须手动加入数组中。
3)字符指针方式:char* psz = ...;可以指向字面值字符串,也可以指向字符数组字符串。同样有效字符串必须以'\0'结尾。
char str[] = "abcdefg";
str[1] = '1';
*(str+2) = '2';
str[4] = 0; // = '\0';
printf ("%s\n", str);
输出:a12d
str[4] = '0';
printf ("%s\n", str);
输出:a12d0fg
-------------
char str1[] = "ABC";
char str2[] = {'A','B','C'};
sizeof (str1)>sizeof (str2)
-------------
int a;
scanf ("%d", &a);
printf ("%d", a);
char str[128];
scanf ("%s", str);
2.字符串I/O函数
char* psz;
scanf ("%s", psz); // 错误!
char* gets (char* str);
从标准输入读取字符串保存到str所指向的内存中,直到遇到\n为止,并将\n转换为\0。返回str。
int puts (char* str);
向标准输出打印str所指向的字符串,并将\0转换为\n。成功返回非0,失败返回0。
3.其它字符串常用函数
string.h
size_t strlen (char* str);
返回str的长度。
char* strcpy (char* to, const char* from);
将from所指向的字符串拷贝到to所指向的内存中。返回to。
char* strcat (char* str1, const char* str2);
将str2所指向的字符串连接到str1所指向字符串的末尾。返回str1。
使用strcpy/strcat的时候,to/str1所指向的内存空间一定要足够大,否则会导致内存溢出。
int strcmp (const char* str1, const char* str2);
str1 < str2:返回值小于0
str1 = str2:返回值等于0
str1 > str2:返回值大于0
4.字符串数组
1)二维数组
char sa[][128] = {"beijing", "tianjin", "shanghai", "chongqing"};
printf ("%s\n", sa[0]);
// beijing
2)字符指针数组
数组首地址:数组首元素的地址,数组名。
指针数组:数组中的每个元素都是指针。
int a, b, c;
int* pa[] = {&a, &b, &c};
char* ps[] = {"hello", "world", "mw"};
练习:基于命令行的简单计算器,实现两个整型操作数的+-x/%运算。
提示:atoi()将字符串转换整数。
练习:实现字符串合并函数:
void merge (const char* p1, const char* p2, char* p3);
将p1与p2合并放入p3,p1和p2以排好序,要求p3也是有序的。
p1 : agkxz
p2 : bhmp
p3 : abghkmpxz
#include <stdio.h>
void print (/*int arr[]*/int* arr, int len) {
int i;
for (i = 0; i < len; i++)
printf ("%d ", arr[i]);
printf ("\n");
}
int main (void) {
int a[] = {1,2,3,4,5};
printf ("%p\n", a);
printf ("%p\n", &a[0]);
int* p = a, i;
for (i = 0; i < 5; i++)
printf ("%d ", p[i]/* *(p+i) */);
printf ("\n");
int b[] = {10,20,30,40,50};
p = b;
for (i = 0; i < 5; i++)
printf ("%d ", p[i]);
printf ("\n");
// a = b; // 编译错误
print (a, sizeof (a) / sizeof (a[0]));
return 0;
}
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[]) {
if (argc < 4)
goto error;
if (strspn (argv[1], "0123456789") != strlen (argv[1]) || strspn (argv[3], "0123456789") != strlen (argv[3]))
goto error;
int a = atoi (argv[1]);
int b = atoi (argv[3]);
int c;
if (! strcmp (argv[2], "+"))
c = a + b;
else
if (! strcmp (argv[2], "-"))
c = a - b;
else
if (! strcmp (argv[2], "x"))
c = a * b;
else
if (! strcmp (argv[2], "/"))
c = a / b;
else
if (! strcmp (argv[2], "%"))
c = a % b;
else
goto error;
printf ("%s %s %s = %d\n", argv[1], argv[2], argv[3], c);
return 0;
error:
printf ("使用方法:%s a +|-|x|/|%% b\n", argv[0]);
return -1;
}
#include <stdio.h>
int main (int argc, char* argv[]) {
printf ("argc=%d\n", argc);
int i;
for (i = 0; i < argc; i++)
printf ("argv[%d]=%s\n", i, argv[i]);
return 0;
}
#include <stdio.h>
void show (const int* pn) {
printf ("show: %d\n", *pn);
//(*pn)++; // 编译错误
}
int main (void) {
const int a = 100;
// a = 200;
// a++;
// a -= 10;
int b = 100;
const int* cp = &b; // 常量指针
// *cp = 200; // 编译错误
int* const pc = &b; // 指针常量
int c = 300;
// pc = &c; // 编译错误
cp = &c; // ok
*pc = 400; // ok
show (&b);
printf ("after show: b=%d\n", b);
return 0;
}
#include <stdio.h>
#include <string.h>
void reverse (char* str) {
int len = strlen (str), i;
for (i = 0; i < len / 2; i++) {
char c = str[i];
str[i] = str[len-1-i];
str[len-1-i] = c;
}
}
int main (void) {
char str[1024];
for (;;) {
gets (str);
reverse (str);
puts (str);
}
return 0;
}
#include <stdio.h>
void merge (const char* p1, const char* p2, char* p3) {
int i = 0;
for (;;)
if (*p1 && *p2)
if (*p1 < *p2)
p3[i++] = *p1++;
else
p3[i++] = *p2++;
else if (*p1)
p3[i++] = *p1++;
else if (*p2)
p3[i++] = *p2++;
else
break;
p3[i] = '\0';
}
int main (void) {
const char* s1 = "adgkm";
const char* s2 = "behklop";
char s3[256];
merge (s1, s2, s3);
printf ("%s + %s = %s\n", s1, s2, s3);
return 0;
}
#include <stdio.h>
int main (void) {
char* pc = NULL;
printf ("pc=%u\n", pc);
printf ("pc+1=%u\n", pc+1);
pc += 2;
pc++;
printf ("pc=%u\n", pc); // 3
int* pn = NULL;
printf ("pn=%u\n", pn);
printf ("pn+1=%u\n", pn+1);
pn += 2;
pn++;
printf ("pn=%u\n", pn); // 12
int arr[] = {100,200};
int* p = arr;
printf ("*p=%d\n", *p); // 100
p++;
printf ("*p=%d\n", *p); // 200
printf ("%d\n", arr[1]); // 200
printf ("%d\n", *(arr+1)); // 200
printf ("%d\n", *(1+arr)); // 200
printf ("%d\n", 1[arr]); // 200
// x[y] ==> *(x+y)
int* p1 = NULL;
int* p2 = p1 + 10;
printf ("p2=%u\n", p2); // 40
printf ("p2-p1=%d\n", p2 - p1); // 10
//printf ("p2+p1=%d\n", p2 + p1); // 编译错
return 0;
}
#include <stdio.h>
int g = 100;
int* foo (/*void*/int* p) {
static int a = 100;
//return &a;
//return &g;
return p;
}
int* bar (void) {
int b = 200;
return &b;
}
int hum (void) {
int c = 300;
return c;
}
int main (void) {
int a = 100;
int* p = foo (&a);
bar ();
printf ("%d\n", *p);
printf ("%d\n", hum ());
return 0;
}
#include <stdio.h>
int main (void) {
char sa[][128] = {"beijing", "tianjin", "shanghai", "chongqing", "达内科技"};
size_t i;
for (i = 0; i < sizeof (sa) / sizeof (sa[0]); i++)
printf ("%s\n", sa[i]);
char* ps[] = {"hello", "world", "mw"};
for (i = 0; i < sizeof (ps) / sizeof (ps[0]); i++)
printf ("%s\n", ps[i]);
return 0;
}
#include <stdio.h>
#include <string.h>
int main (void) {
char str[1024] = {0};
printf ("%d\n", strlen (str));
strcpy (str, "hello");
printf ("%s\n", str);
printf ("%s\n", strcpy (str, "good"));
printf ("%d\n", strlen (strcat (str, " morning")));
printf ("%s\n", str);
printf ("%d\n", strcmp ("abc", "abc"));
printf ("%d\n", strcmp ("abc", "aBc"));
printf ("%d\n", strcmp ("abC", "abc"));
printf ("%d\n", strcmp ("abc", "abcd"));
return 0;
}
#include <stdio.h>
int main (void) {
printf ("hello "
"world\n");
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\n','\0'};
printf ("%s", str);
char str2[] = "hello world\n";
str2[0] = 'H';
printf ("%s", str2);
char* psz = "hello world\n";
//psz[0] = 'H'; //*(psz+0)='H', 段错误
printf ("%s", psz);
psz = str2;
psz[1] = 'E'; // *(psz+1)='E'
printf ("%s", psz);
return 0;
}
一、指针
1....
2....
3.指针的用法
2)指针也可以作为函数的返回值,但是不要返回指向局部变量的指针。因为函数返回以后,其局部变量所占用的内存将随函数栈一起被释放,所得到的指针为野指针。可以返回全局变量、静态局部变量、实参变量以及成员变量的指针。因为这些变量在函数返回以后依然有效。
int foo (void) {
return 10;
}
a = foo ();
int* foo (void) {
...
return p;
}
int* foo (void); // 函数声明,声明一个没有参数,返回int*的foo反函数
int (*foo) (void); // 函数指针
void foo (void) {
}
没有返回值的函数。
4.指针计算
1)一个指针型数据可以和一个整数做加减法计算,表示地址计算。所得结果与指针的类型有关。
int型指针+1:地址+4
short型指针+1:地址+2
char型指针+1:地址+1
...
X型指针+/-N:地址+/-N*sizeof(X)
2)通过指针计算可以访问数组中的元素。所谓的下标运算“[]”,其本质就是指针计算。
3)相同类型的指针之间可以做减法运算,所得为两个指针之间的距离,以指针类型为单位。
5.数组和指针
1)数组名就是数组的首地址,即首元素的地址,其本质就是一个指针,但其类型为常量。
2)以数组为参数的函数,所传递的实参是数组的首地址,而形参就是数组元素类型的指针。
6.常量、常量指针和指针常量
1)const可以修饰普通变量,该变量就会被当做常量来处理,即其值一经初始化就再不能被修改。
2)常量指针:指向常量的指针,即无法通过该指针修改其目标。
const int* p;
int const* p;
3)指针常量:指针型的常量,即无法修改其值的指针。
int* const p;
const int* const p; // 常量指针常量,p本身不能改,其目标亦不能改
二、字符串
1.在C语言中没有专门的字符串类型,通常情况下,字符串可以用三种方式表示:
1)字面值方式:"hello world"。不能修改,但是可以被赋值给变量,并在变量中修改。字面值方式的字符串后面自动追加'\0'结束符。字面值可以拼接:
"hello ""world"
" tarean" ==> "hello world tarena"
2)字符数组方式:char str[] = {...};以char型数组表示字符串,注意结尾符'\0',必须手动加入数组中。
3)字符指针方式:char* psz = ...;可以指向字面值字符串,也可以指向字符数组字符串。同样有效字符串必须以'\0'结尾。
char str[] = "abcdefg";
str[1] = '1';
*(str+2) = '2';
str[4] = 0; // = '\0';
printf ("%s\n", str);
输出:a12d
str[4] = '0';
printf ("%s\n", str);
输出:a12d0fg
-------------
char str1[] = "ABC";
char str2[] = {'A','B','C'};
sizeof (str1)>sizeof (str2)
-------------
int a;
scanf ("%d", &a);
printf ("%d", a);
char str[128];
scanf ("%s", str);
2.字符串I/O函数
char* psz;
scanf ("%s", psz); // 错误!
char* gets (char* str);
从标准输入读取字符串保存到str所指向的内存中,直到遇到\n为止,并将\n转换为\0。返回str。
int puts (char* str);
向标准输出打印str所指向的字符串,并将\0转换为\n。成功返回非0,失败返回0。
3.其它字符串常用函数
string.h
size_t strlen (char* str);
返回str的长度。
char* strcpy (char* to, const char* from);
将from所指向的字符串拷贝到to所指向的内存中。返回to。
char* strcat (char* str1, const char* str2);
将str2所指向的字符串连接到str1所指向字符串的末尾。返回str1。
使用strcpy/strcat的时候,to/str1所指向的内存空间一定要足够大,否则会导致内存溢出。
int strcmp (const char* str1, const char* str2);
str1 < str2:返回值小于0
str1 = str2:返回值等于0
str1 > str2:返回值大于0
4.字符串数组
1)二维数组
char sa[][128] = {"beijing", "tianjin", "shanghai", "chongqing"};
printf ("%s\n", sa[0]);
// beijing
2)字符指针数组
数组首地址:数组首元素的地址,数组名。
指针数组:数组中的每个元素都是指针。
int a, b, c;
int* pa[] = {&a, &b, &c};
char* ps[] = {"hello", "world", "mw"};
练习:基于命令行的简单计算器,实现两个整型操作数的+-x/%运算。
提示:atoi()将字符串转换整数。
练习:实现字符串合并函数:
void merge (const char* p1, const char* p2, char* p3);
将p1与p2合并放入p3,p1和p2以排好序,要求p3也是有序的。
p1 : agkxz
p2 : bhmp
p3 : abghkmpxz
#include <stdio.h>
void print (/*int arr[]*/int* arr, int len) {
int i;
for (i = 0; i < len; i++)
printf ("%d ", arr[i]);
printf ("\n");
}
int main (void) {
int a[] = {1,2,3,4,5};
printf ("%p\n", a);
printf ("%p\n", &a[0]);
int* p = a, i;
for (i = 0; i < 5; i++)
printf ("%d ", p[i]/* *(p+i) */);
printf ("\n");
int b[] = {10,20,30,40,50};
p = b;
for (i = 0; i < 5; i++)
printf ("%d ", p[i]);
printf ("\n");
// a = b; // 编译错误
print (a, sizeof (a) / sizeof (a[0]));
return 0;
}
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[]) {
if (argc < 4)
goto error;
if (strspn (argv[1], "0123456789") != strlen (argv[1]) || strspn (argv[3], "0123456789") != strlen (argv[3]))
goto error;
int a = atoi (argv[1]);
int b = atoi (argv[3]);
int c;
if (! strcmp (argv[2], "+"))
c = a + b;
else
if (! strcmp (argv[2], "-"))
c = a - b;
else
if (! strcmp (argv[2], "x"))
c = a * b;
else
if (! strcmp (argv[2], "/"))
c = a / b;
else
if (! strcmp (argv[2], "%"))
c = a % b;
else
goto error;
printf ("%s %s %s = %d\n", argv[1], argv[2], argv[3], c);
return 0;
error:
printf ("使用方法:%s a +|-|x|/|%% b\n", argv[0]);
return -1;
}
#include <stdio.h>
int main (int argc, char* argv[]) {
printf ("argc=%d\n", argc);
int i;
for (i = 0; i < argc; i++)
printf ("argv[%d]=%s\n", i, argv[i]);
return 0;
}
#include <stdio.h>
void show (const int* pn) {
printf ("show: %d\n", *pn);
//(*pn)++; // 编译错误
}
int main (void) {
const int a = 100;
// a = 200;
// a++;
// a -= 10;
int b = 100;
const int* cp = &b; // 常量指针
// *cp = 200; // 编译错误
int* const pc = &b; // 指针常量
int c = 300;
// pc = &c; // 编译错误
cp = &c; // ok
*pc = 400; // ok
show (&b);
printf ("after show: b=%d\n", b);
return 0;
}
#include <stdio.h>
#include <string.h>
void reverse (char* str) {
int len = strlen (str), i;
for (i = 0; i < len / 2; i++) {
char c = str[i];
str[i] = str[len-1-i];
str[len-1-i] = c;
}
}
int main (void) {
char str[1024];
for (;;) {
gets (str);
reverse (str);
puts (str);
}
return 0;
}
#include <stdio.h>
void merge (const char* p1, const char* p2, char* p3) {
int i = 0;
for (;;)
if (*p1 && *p2)
if (*p1 < *p2)
p3[i++] = *p1++;
else
p3[i++] = *p2++;
else if (*p1)
p3[i++] = *p1++;
else if (*p2)
p3[i++] = *p2++;
else
break;
p3[i] = '\0';
}
int main (void) {
const char* s1 = "adgkm";
const char* s2 = "behklop";
char s3[256];
merge (s1, s2, s3);
printf ("%s + %s = %s\n", s1, s2, s3);
return 0;
}
#include <stdio.h>
int main (void) {
char* pc = NULL;
printf ("pc=%u\n", pc);
printf ("pc+1=%u\n", pc+1);
pc += 2;
pc++;
printf ("pc=%u\n", pc); // 3
int* pn = NULL;
printf ("pn=%u\n", pn);
printf ("pn+1=%u\n", pn+1);
pn += 2;
pn++;
printf ("pn=%u\n", pn); // 12
int arr[] = {100,200};
int* p = arr;
printf ("*p=%d\n", *p); // 100
p++;
printf ("*p=%d\n", *p); // 200
printf ("%d\n", arr[1]); // 200
printf ("%d\n", *(arr+1)); // 200
printf ("%d\n", *(1+arr)); // 200
printf ("%d\n", 1[arr]); // 200
// x[y] ==> *(x+y)
int* p1 = NULL;
int* p2 = p1 + 10;
printf ("p2=%u\n", p2); // 40
printf ("p2-p1=%d\n", p2 - p1); // 10
//printf ("p2+p1=%d\n", p2 + p1); // 编译错
return 0;
}
#include <stdio.h>
int g = 100;
int* foo (/*void*/int* p) {
static int a = 100;
//return &a;
//return &g;
return p;
}
int* bar (void) {
int b = 200;
return &b;
}
int hum (void) {
int c = 300;
return c;
}
int main (void) {
int a = 100;
int* p = foo (&a);
bar ();
printf ("%d\n", *p);
printf ("%d\n", hum ());
return 0;
}
#include <stdio.h>
int main (void) {
char sa[][128] = {"beijing", "tianjin", "shanghai", "chongqing", "达内科技"};
size_t i;
for (i = 0; i < sizeof (sa) / sizeof (sa[0]); i++)
printf ("%s\n", sa[i]);
char* ps[] = {"hello", "world", "mw"};
for (i = 0; i < sizeof (ps) / sizeof (ps[0]); i++)
printf ("%s\n", ps[i]);
return 0;
}
#include <stdio.h>
#include <string.h>
int main (void) {
char str[1024] = {0};
printf ("%d\n", strlen (str));
strcpy (str, "hello");
printf ("%s\n", str);
printf ("%s\n", strcpy (str, "good"));
printf ("%d\n", strlen (strcat (str, " morning")));
printf ("%s\n", str);
printf ("%d\n", strcmp ("abc", "abc"));
printf ("%d\n", strcmp ("abc", "aBc"));
printf ("%d\n", strcmp ("abC", "abc"));
printf ("%d\n", strcmp ("abc", "abcd"));
return 0;
}
#include <stdio.h>
int main (void) {
printf ("hello "
"world\n");
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\n','\0'};
printf ("%s", str);
char str2[] = "hello world\n";
str2[0] = 'H';
printf ("%s", str2);
char* psz = "hello world\n";
//psz[0] = 'H'; //*(psz+0)='H', 段错误
printf ("%s", psz);
psz = str2;
psz[1] = 'E'; // *(psz+1)='E'
printf ("%s", psz);
return 0;
}
相关文章推荐
- 【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
- 安卓第九天笔记-Activity
- 【OpenCV】OpenCV3的第九天——imgproc组件之特征检测
- 冲刺阶段第九天
- 第九天
- 冲刺第九天
- 《校园封神榜》第二阶段个人工作总结——第九天
- 第二阶段冲刺第九天
- c/c++第九天
- Spring学习第九天:Spring表达式语言Spel
- 就第九天学习的数组和排序问题做出的总结
- C#基础第九天-作业答案-储蓄账户(SavingAccount)和信用账户(CreditAccount)
- 第九天(学生信息)
- 第九天
- JS基础第九天:逆名函数以及作用域的介绍
- python爬虫学习第九天
- OCM_第九天课程:Section4—》OCM课程环境搭建
- 六级_第九天
- Alpha冲刺——第九天
- web前端第九天