C第十二天

五、二维数组与指针
int a[2][3] = {1,2,3,4,5,6};
    a[0] a[0]+1 a[0]+2
     |    |      |
     v    v      v
  a->1    2      3
a+1->4    5      6
a的类型:int (*)[3]
a[0]的类型:int*
对于以上二维数组以下表达式的值是相等的:
a+i
*(a+i)
a[i]
&a[i]
&a[i][0]
-------------
x[y] = *(x+y)
a[i][j]
= *(a[i]+j)
= *(*(a+i)+j)
六、多级指针
二级指针:指向一级指针的指针,其中存放一个一级指针的地址。
int a, b, c;
int* pa[] = {&a, &b, &c};
char* pc[] = {"hello", "world", "tarena"};
int** ppa = pa;
七、空指针(void*)
1.代表任意类型的指针。
2.一切类型的指针都可以隐式转换为空指针。
3.对空指针不能解引用。
4.空指针支持计算,但是统一按单字节处理。
八、动态内存分配与释放
#include <stdlib.h>
void* malloc (
  size_t size // 预分配字节数
);
成功返回所分配内存的起始地址,失败返回NULL。不初始化。
void* calloc (
  size_t nmemb, // 元素数
  size_t size // 元素字节数
);
成功返回所分配内存的起始地址,失败返回NULL。初始化为0。
所有通过动态内存分配所得到内存都要通过free()函数释放。
void free (
  void* ptr // 内存地址
);
void* realloc (
  void* ptr, // 原地址
  size_t size // 新字节数
);
成功返回调整后的内存地址,失败返回NULL。新增部分不做初始化。
如果ptr为NULL,则与malloc()等效。
如果size为0,则与free()等效。
可能会分配新的内存空间,如果发生这种情况,原内存会自动释放,其内容会拷贝到新内存中,但是如果分配失败,原内存不会释放。
char* p = (char*)malloc (10);
char* p2 = realloc (p, 20);
if (p2)
  p = p2;
else {
  free (p);
  return -1;
}
举例:录入多行文本,每行不超过255个字符,行数不限,输入!表示输入结束,将之前输入的所有内容拼成一个字符串输出。
输入> 达内
输入> 科技
输入> 有限公司
输入> !
输出> 达内科技有限公司
九、函数指针及其解引用
1.用指针存储代码区中的函数地址。所有的函数都有地址,而函数名实际上就是该函数的符号地址。
2.定义语法
函数:返回类型 函数名 (形参表) {函数体;}
函数指针:
返回类型 (*函数指针名) (形参表);
例如:
int foo (int a, double b){...}
int bar (int a, double b)
{...}
int (*pfoo) (int, double) = foo;
pfoo = bar;
3.解引用语法
函数指针名 (实参表);
pfoo (10, 3.14); // 调用bar
----------------
pfoo = &bar;
(*pfoo) (10, 3.14);
第十二课  IO流与标准库
一、IO流的打开和关闭
FILE* fopen (
  const char* filename, //文件路径
  const char* mode // 打开模式
);
打开模式:
r: 读
w: 写
a: 追加
r+: 读写,文件必须存在,从头开始
w+: 写读,文件不存在就创建,文件存在就清空
a+: 读写,文件不存在就创建,文件存在就追加
b: 二进制方式
UNIX/Linux:二进制方式作用不大
Windows:二进制方式,对读写内容不做任何转换。非二进制方式,写入\n,实际写入\r\n,文件中\r\n,读到的\n。
返回值是IO流结构体指针,用户调用其他IO流函数。
int fclose (
  FILE* fp // fopen的返回值
);
成功返回0,否则返回EOF。
进程一启动,以下标准IO流是默认打开的:
stdout: 标准输出
stdin: 标准输入
stderr: 标准出错
二、格式化IO
int fprintf (
  FILE* stream, // IO流指针
  const char* format,// 格式字符串
  ... // 输出数据项
);
printf(...)实际就是fprintf (stdout, ...)
格式字符串:
%[标志][宽度][.精度][h|l|ll]类型符
标志:
- 左对齐
+ 输出正负号
# 输出进制标识
0 用0填充
宽度.精度:123.34,宽度6,精度2,%6.2f
h  short
l  long/double
ll long long
类型符:
d 十进制整数
c 字符
s 空字符结尾的字符串
f 浮点数
x/X 十六进制整数
o 八进制整数
p 地址(十六进制)
u 无符号十进制整数
g 浮点数(自动选择最短形式)
e 浮点数(科学计数法)
int fscanf (
  FILE* stream, // IO流指针
  const char* format, // 格式字符串
  ... // 地址表
);
1)以空白字符(空格、制表、换行)作为数据分隔符。
2)模式匹配:根据格式化字符串的模式进行匹配,从中提取数据。
3)禁止赋值:*
4)字符集表示:只读取某个特定字符集中的字符,只要遇到字符集以外的字符即刻返回。
三、非格式化IO
int fputc (
  int c, // 字符
  FILE* stream // IO流指针
);
成功返回c,失败返回EOF。
int fgetc (
  FILE* stream // IO流指针
);
成功返回读到的字符,失败或者遇到文件尾返回EOF。
四、二进制IO
size_t fread (
  void* buf, // 缓冲区指针
  size_t size, // 期望读取的数据单元字节数
  size_t count, // 期望读取的数据单元数
  FILE* stream // IO流指针
);
成功返回实际读取的数组单元数。失败或遇到文件尾返回0。
size_t fwrite (
  void* buf, // 缓冲区指针
  size_t size, // 期望写入的数据单元字节数
  size_t count, // 期望写入的数据单元数
  FILE* stream // IO流指针
);
成功返回实际写入的数据单元数,失败返回0。
五、流位置与随机访问
六、可变参数
七、日期时间

八、实用工具

#include <stdio.h>
void foo (int* c, int size) {
}
void bar (int (*a)[3], int size) {
}
int main (void) {
  int a[2][3] = {1,2,3,4,5,6};
  // 降维
  int* b = (int*)a;
  int i, j;
  for (i = 0; i < 6; i++)
    printf ("%d ", b[i]/* *(b+i) */);
  printf ("\n");
  int c[6] = {1,2,3,4,5,6};
  // 升维
  int (*d)[2] = (int (*)[2])c;
  for (i = 0; i < 3; i++) {
    for (j = 0; j < 2; j++)
      printf ("%d ", d[i][j]/* *(*(d+i)+j) */);
    printf ("\n");
  }
  foo (c, sizeof (c) / sizeof (c[0]));
  bar (a, sizeof (a) / sizeof (a[0]));
  return 0;
}

#include <stdio.h>
#include <stdlib.h>
double g_balance = 0.0;
double g_rate = 0.01;
void clean (void) {
  scanf ("%*[^\n]");
  scanf ("%*c");
}
int menu (void) {
  printf ("--------\n");
  printf ("迷你银行\n");
  printf ("--------\n");
  printf ("[1] 清户\n");
  printf ("[2] 存款\n");
  printf ("[3] 取款\n");
  printf ("[4] 查询\n");
  printf ("[5] 结息\n");
  printf ("[6] 调息\n");
  printf ("[0] 退出\n");
  printf ("--------\n");
  printf ("请选择:");
  int sel = -1;
  scanf ("%d", &sel);
  clean ();
  return sel;
}
void query (void) {
  printf ("当前余额:%.2lf\n", g_balance);
}
void clear (void) {
  g_balance = 0;
  query ();
}
void save (void) {
  printf ("存款金额:");
  double save;
  scanf ("%lf", &save);
  clean ();
  g_balance += save;
  query ();  
}
void withdraw (void) {
  printf ("取款金额:");
  double withdraw;
  scanf ("%lf", &withdraw);
  clean ();
  if (g_balance < withdraw)
    printf ("余额不足!\n");
  else {
    g_balance -= withdraw;
    query ();
  }
}
void settle (void) {
  g_balance *= (1 + g_rate);
  query ();
}
void adjust (void) {
  printf ("当前利率:%.2lf\n", g_rate);
  printf ("存款利率:");
  scanf ("%lf", &g_rate);
  clean ();
}
void quit (void) {
  printf ("再见!\n");
  exit (0);
}
int main (void) {
  void (*deal[]) (void) = {quit, clear, save, withdraw, query, settle, adjust};
  for (;;) {
    int sel = menu ();
    if (sel >= 0 && sel < sizeof (deal) / sizeof (deal[0]))
      deal[sel] ();
    else
      printf ("选择错误!\n");
  }
  return 0;
}

#include <stdio.h>
#include <string.h>
// 以二进制形式打印一个字节
void printb (char byte) {
  size_t i;
  for (i = 0; i < 8; i++)
    printf ("%c", byte & 1<<7-i ? '1' : '0');
  printf (" ");
}
// 以二进制形式打印一个内存块
void printm (void* buf, size_t size) {
  size_t i;
  for (i = 0; i < size; i++)
    printb (((char*)buf)[i]);
  printf ("\n");
}
int main (void) {
  int a = 0x12345678;
  printm (&a, sizeof (a));
  double d = 3.14;
  printm (&d, sizeof (d));
  struct {
    char name[128];
    int age;
  } student = {"张飞", 28};
  printm (&student, sizeof (student));
  return 0;
}

#include <stdio.h>
int main (void) {
  FILE* fp = fopen ("fmt.txt", "w");
  if (! fp) {
    perror ("fopen");
    return -1;
  }
  fprintf (fp, "[%-10d]\n", 12);
  fprintf (fp, "[%+10d]\n", 12);
  fprintf (fp, "[%6.2f]\n", 123.45678);
  fprintf (fp, "[%x,%#X,%#o]\n", 15, 15, 15);
  fprintf (fp, "[%e]\n", 0.000123456);
  int i;
  for (i = 1; i < 10; i++)
    fprintf (fp, "%*c\n", i, '*');
  fclose (fp);
  fprintf (stdout, "hello world\n");
  fprintf (stderr, "hello world\n");
  fp = fopen ("fmt2.txt", "r");
  if (! fp) {
    perror ("fopen");
    return -1;
  }
  int a;
  double b;
  char c[256], d[256];
  fscanf (fp, "%d%lf%s%s", &a, &b, c, d);
  printf ("[%d]\n[%lf]\n[%s]\n[%s]\n", a, b, c, d);
  int e, f;
  fscanf (fp, "%d+%d=%d", &a, &e, &f);
  printf ("%d, %d, %d\n", a, e, f);
  fscanf (fp, "%*d%d", &a);
  printf ("%d\n", a);
  fscanf (fp, "%s", c);
  printf ("%s\n", c);
  fscanf (fp, "%*c");
  fscanf (fp, "%[a-z]%d", c, &a);
  printf ("%s, %d\n", c, a);
  fscanf (fp, "%*c");
  fscanf (fp, "%[^a-c]%[a-z]", c, d);
  printf ("%s, %s\n", c, d);
  fclose (fp);
  return 0;
}

#include <stdio.h>
int add (int a, int b) {
  return a + b;
}
int sub (int a, int b) {
  return a - b;
}
int mul (int a, int b) {
  return a * b;
}
int div (int a, int b) {
  return a / b;
}
int mod (int a, int b) {
  return a % b;
}
int cal (int a, int b, int (*pfunc) (int, int)) {
  return pfunc (a, b);
}
int main (void) {
  int (*pfunc) (int, int);
  pfunc = add;
  printf ("%d\n", pfunc (10, 20));
  pfunc = sub;
  printf ("%d\n", pfunc (30, 10));
  printf ("%d\n", cal (10, 20, add));
  printf ("%d\n", cal (15, 2, div));
  printf ("%d\n", cal (15, 2, mod));
  return 0;
}

#include <stdio.h>
int main (void) {
  FILE* fp1 = fopen ("get.txt", "r");
  FILE* fp2 = fopen ("put.txt", "w");
  int c;
  for (;;) {
    c = fgetc (fp1);
    if (c == EOF)
      break;
    fputc (c, fp2);
  }
  fclose (fp2);
  fclose (fp1);
  return 0;
}

#include <stdio.h>
#include <stdlib.h>
int main (void) {
  int* p = (int*)malloc (sizeof (int));
  *p = 100;
  printf ("%d\n", *p);
  free (p);
  //p = (int*)malloc (5 * sizeof (int));
  p = (int*)calloc (5, sizeof (int));
  int i;
  for (i = 0; i < 5; i++)
    p[i] = i;
  for (i = 0; i < 5; i++)
    printf ("%d ", p[i]);
  printf ("\n");
  free (p);
  p = realloc (NULL, 1024 * sizeof (int));
  if (! p) {
    perror ("出错啦!");
    return -1;
  }
  int* p2 = realloc (p, /*2048000*/0xFFFFFFFF * sizeof (int));
  if (! p2) {
    perror ("又出错啦!");
    free (p);
    return -1;
  }
  printf ("%p, %p\n", p, p2);
  p = p2;
  realloc (p, 0);
  return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
  char* full = NULL;
  for (;;) {
    printf ("输入> ");
    char line[256];
    gets (line);
    if (! strcmp (line, "!"))
      break;
    if (! full) {
      full = (char*)malloc ((strlen (line) + 1) * sizeof (char));
      if (! full) {
        perror ("错误> ");
        return -1;
      }
      strcpy (full, line);
    }
    else {
      char* new = (char*)realloc (full, (strlen (full) + strlen (line) + 1) * sizeof (char));
      if (! new) {
        perror ("错误> ");
        free (full);
        return -1;
      }
      strcat (full, line);
    }
  }
  printf ("输出> %s\n", full);
  free (full);
  return 0;
}

#include <stdio.h>
void swap (int* a, int* b) {
  int c = *a;
  *a = *b;
  *b = c;
}
void swap2 (const char** a, const char** b) {
  const char* c = *a;
  *a = *b;
  *b = c;
}
int main (void) {
  int a = 100;
  int* p = &a;
  int** pp = &p; // pp -> p -> a
  printf ("a=%d,&a=%p\n", a, &a);
  printf ("p=%p,&p=%p,*p=%d\n", p, &p, *p);
  printf ("pp=%p,*pp=%p,**pp=%d\n", pp, *pp, **pp);
  int x = 100, y = 200;
  swap (&x, &y);
  printf ("%d %d\n", x, y);
  const char* pa = "hello";
  const char* pb = "world";
  printf ("%s %s\n", pa, pb);
  swap2 (&pa, &pb);
  printf ("%s %s\n", pa, pb);
  return 0;
}

#include <stdio.h>
#include <string.h>
int intcmp (const void* pv1, const void* pv2) {
  return *(const int*)pv2 - *(const int*)pv1;
}
int szcmp (const void* pv1, const void* pv2) {
  const char** pp1 = (const char**)pv1;
  const char** pp2 = (const char**)pv2;
  return strcmp (*pp1, *pp2);
}
int main (void) {
  int a[] = {13, 34, 9, 27, 77, 10, 64};
  int len = sizeof (a) / sizeof (a[0]);
  qsort (a, len, sizeof (a[0]), intcmp);
  int i;
  for (i = 0; i < len; i++)
    printf ("%d ", a[i]);
  printf ("\n");
  const char* b[] = {"beijing", "chongqing", "shanghai", "tianjin", "jinan", "guangzhou", "hangzhou"};
  len = sizeof (b) / sizeof (b[0]);
  qsort (b, len, sizeof (b[0]), szcmp);
  for (i = 0; i < len; i++)
    printf ("%s ", b[i]);
  printf ("\n");
  return 0;
}

#include <stdio.h>
int main (void) {
  char sz[256];
  int a;
  scanf ("%s", sz);
  printf ("输入整数:");
  char c;
  scanf ("%c%d", &c, &a);
  printf ("%s, [%c], %d\n", sz, c, a);
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值