C第九天

第九课  指针与字符串
一、指针
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值