第6章 玩转数组

6-1 数组基础

C语言设计哲学

include/io_utils.h

#ifndef BASICC_IO_UTILS_IO_UTILS_H_
#define BASICC_IO_UTILS_IO_UTILS_H_

#include <stdio.h>
#include <limits.h>

void PrintBinary(unsigned int value);

//#define PRINT_METADATA
#ifdef PRINT_METADATA
# define PRINTLNF(format, ...) printf("("__FILE__":%d) %s: "format"\n", __LINE__, __FUNCTION__ , ##__VA_ARGS__)
#else
# define PRINTLNF(format, ...) printf(format"\n", ##__VA_ARGS__)
#endif

#define PRINT_CHAR(char_value) PRINTLNF(#char_value": %c", char_value)
#define PRINT_WCHAR(char_value) PRINTLNF(#char_value": %lc", char_value)
#define PRINT_INT(int_value) PRINTLNF(#int_value": %d", int_value)
#define PRINT_LONG(long_value) PRINTLNF(#long_value": %ld", long_value)
#define PRINT_LLONG(long_value) PRINTLNF(#long_value": %lld", long_value)
#define PRINT_BINARY(int_value) PrintBinary((unsigned int) int_value);
#define PRINT_HEX(int_value) PRINTLNF(#int_value": %#x", int_value)
#define PRINT_BOOL(bool_value) PRINTLNF(#bool_value": %s", bool_value ? "true" : "false")
#define PRINT_DOUBLE(double_value) PRINTLNF(#double_value": %g", double_value)
#define PRINT_STRING(string_value) PRINTLNF(#string_value": %s", string_value)

#define PRINT_ARRAY(format, array, length) \
{ int array_index; \
for (array_index = 0; array_index < length; ++array_index) { \
  printf(format, array[array_index]); \
};\
printf("\n"); }

#define PRINT_INT_ARRAY_LN(array, length) \
{ int i; \
for (i = 0; i < length; ++i) { \
  PRINTLNF(#array"[%d]: %d", i, array[i]); \
}}

#define PRINT_INT_ARRAY(array, length) PRINT_ARRAY("%d, ", array, length)
#define PRINT_CHAR_ARRAY(array, length) PRINT_ARRAY("%c, ", array, length)
#define PRINT_DOUBLE_ARRAY(array, length) PRINT_ARRAY("%g, ", array, length)

#endif //BASICC_IO_UTILS_IO_UTILS_H_

01.array_basics.c

#include <stdio.h>
#include "io_utils.h"

#define ARRAY_SIZE 10
// 全局作用域
int global_array[ARRAY_SIZE];

int main() {
  // index from 0!!!
  auto int array[ARRAY_SIZE];

  for (int i = 0; i < ARRAY_SIZE; ++i) {
    //array[i] = i;
    PRINT_HEX(global_array[i]);
  }

  int array_2[ARRAY_SIZE] = {0,1,2,3,4,5,6,7,8,9};
  for (int i = 0; i < ARRAY_SIZE; ++i) {
    PRINT_INT(array_2[i]);
  }

  double array_double[5] = {0.1, 2.3};
  for (int i = 0; i < 5; ++i) {
    PRINT_DOUBLE(array_double[i]);
  }

  // C99 指定位置初始化
  char array_char[5] = {[2] = 'o', 'l', 'l'};
  for (int i = 0; i < 5; ++i) {
    PRINT_CHAR(array_char[i]);
  }
  return 0;
}

6-2 数组的边界

02.array_limits

#include <stdio.h>
#include "io_utils.h"

#define ARRAY_SIZE 5

int main() {
  int array[ARRAY_SIZE];
  int array_with_expression[3 + 2];
  PRINT_INT(array[0]);
  PRINT_INT(array[5]);

  int value = 2;

  // ....
  // C99, VLA; gcc OK; MSVC ERROR
  int array_size_of_value[value];

  const int kSize = 5; // C++ OK
  int array_size_of_const[kSize]; // C99, VLA; gcc OK; MSVC ERROR

  // array[5] => array + 5
  return 0;
}

变长数组(VLA)

数组的长度可以用变量来声明的数组

C语言 标准从C99开始支持该特性

GCC 提供了相应的扩展;MSVC不支持

6-3 字符串

#include <stdio.h>
#include "io_utils.h"

int main() {
  char string[] = "Hello World";

  for (int i = 0; i < 11; ++i) {
    PRINT_CHAR(string[i]);
  }
  // short %hd
  // NULL \0
  PRINTLNF("%s", string);

  char string_zh[] = "你好,中国";

  wchar_t ws[] = L"你好,中国";
  return 0;
}

6-4 函数的数组类型参数

C语言极致效率之源

04.array_parameter.c

#include <stdio.h>
#include "io_utils.h"

#define LENGTH 10

int SumIntArray(int array[], int length) {
  int sum = 0;
  for (int i = 0; i < length; ++i) {
    sum += array[i];
  }
  return sum;
}

int main() {
  int array[LENGTH] = {1, 4, 7, 0, 10, 33, 654, 392, 23, 43};
  PRINT_INT(SumIntArray(array, 10));

  int smaller_array[5] = {1,2,3,4,5};
  PRINT_INT(SumIntArray(smaller_array, 5));

  int bigger_array[15] = {3, 6, 4, 7, 0, 10, 33, 654,6, 4, 7, 0, 10, 33, 654};
  PRINT_INT(SumIntArray(bigger_array, 15));
  return 0;
}

6-5 二维数组

数组参数的正确使用姿势

05.2d_array.c

#include <stdio.h>
#include "io_utils.h"

// vla C99; gcc; msvc x
void SumIntArrays(int rows, int columns, int array[][columns], int result[]) {
  for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < columns; ++j) {
      result[i] += array[i][j];
    }
  }
}

int main() {
  int vehicle_limits[5][2] = {
      0, 5, 1, [1][1] = 6, 2, 7, 3, 8, 4, 9
  };

  //int [2]
  //vehicle_limits[0]

  for (int i = 0; i < 5; ++i) {
    for (int j = 0; j < 2; ++j) {
      vehicle_limits[i][j] = i + j;
    }
  }

  int scores[5][4] = {
      {135, 135, 138, 277},
      {105, 134, 108, 265},
      {113, 107, 145, 232},
      {123, 99, 140, 227},
      {98, 118, 127, 242}
  };

  int result[5] = {0};
  SumIntArrays(5, 4, scores, result);
  PRINT_INT_ARRAY(result, 5);
  return 0;
}

6-6 案例:打乱数组的顺序

06.shuffle_array.c

#include <stdio.h>
#include "io_utils.h"
#include <stdlib.h>
#include <time.h>

#define PLAYER_COUNT 50

void SwapElements(int array[], int first, int second) {
  int temp = array[first];
  array[first] = array[second];
  array[second] = temp;
}

void ShuffleArray(int array[], int length) {
  srand(time(NULL));
  //[0, RAND_MAX]
  for (int i = length - 1; i > 0; --i) {
    int random_number = rand() % i;
    SwapElements(array, i, random_number);
  }
}

int main() {
  int players[PLAYER_COUNT];
  for (int i = 0; i < 50; ++i) {
    players[i] = i;
  }
  // players : 0, 1, ..., 49
  PRINT_INT_ARRAY(players, PLAYER_COUNT);
  ShuffleArray(players, PLAYER_COUNT);
  PRINT_INT_ARRAY(players, PLAYER_COUNT);
  return 0;
}

6-7 案例:数组元素的排序

Lomuto分割法

07.quick_sort.c

#include <stdio.h>
#include "io_utils.h"
#include <stdlib.h>
#include <time.h>

#define PLAYER_COUNT 50

void SwapElements(int array[], int first, int second) {
  int temp = array[first];
  array[first] = array[second];
  array[second] = temp;
}

void ShuffleArray(int array[], int length) {
  srand(time(NULL));
  //[0, RAND_MAX]
  for (int i = length - 1; i > 0; --i) {
    int random_number = rand() % i;
    SwapElements(array, i, random_number);
  }
}

int Partition(int array[], int low, int high) {
  int pivot = array[high];
  int partition = low;
  for (int i = low; i < high; ++i) {
    if (array[i] < pivot) {
      SwapElements(array, i, partition++);
    }
  }
  SwapElements(array, partition, high);

  return partition;
}

void QuickSort(int array[], int low, int high) {
  if (low >= high) return;
  int partition = Partition(array, low, high);
  QuickSort(array, low, partition - 1);
  QuickSort(array, partition + 1, high);
}


int main() {
  int players[PLAYER_COUNT];
  for (int i = 0; i < 50; ++i) {
    players[i] = i;
  }
  // players : 0, 1, ..., 49
  PRINT_INT_ARRAY(players, PLAYER_COUNT);
  ShuffleArray(players, PLAYER_COUNT);
  PRINT_INT_ARRAY(players, PLAYER_COUNT);

  QuickSort(players, 0, PLAYER_COUNT - 1);

  PRINT_INT_ARRAY(players, PLAYER_COUNT);

  return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.17)

get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "_" ProjectId ${ProjectId})
project(${ProjectId} C)

set(CMAKE_C_STANDARD 11)

include_directories("include")

file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
foreach(file ${files})
    get_filename_component(name ${file} NAME)
    add_executable(${name} ${file})
endforeach()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陶喜儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值