从神经多样性视角看待我在 C 语言上的开源之旅
我了解到，如果你能找到适合你的方法，不管老师和其他学生怎么说，你都可以学到任何你感兴趣的开源技能。我生于 1982 年，以人类的年岁计算，这只过去了 40 年（在写这篇文章的时候）。然而就计算机发展而言，那已经是很久以前了。十岁的时候，我得到了我的第一台电脑，一台 Commodare 64 计算机。后来，我买了一台 Amiga，到了13岁的时候，我买了一台 “IBM 兼容” 机（那时，大家都这么称呼它）。高中的时候，我用图形计算器做了很多基本的编程。高二的时候，我学习了基本的 C 语言编程，然后到了高三，我开始做更高级的 C 语言编程，开始应用库、指针和图形界面。我从编程学生成为老师的旅程在我的大学时代，我学习了 Java，所以 Java 成为了我的主要语言。我还为一种叫做个人数据助理（PDA）的设备编写了一些 C# 语言的程序，这是现代智能手机的前身。因为 Java 语言是面向对象的、跨平台的，并且使得 GUI 编程变得容易，我想以后我的大部分编程工作都会用 Java 来完成。在大学里，我也发现自己有教学的天赋，所以我帮助别人编程，而当我选修计算机科学时，他们也帮助我学习数学。在大学后期，我选修了一些 C 语言编程的课程，目的是学习基本的嵌入式编程和测量仪器的控制。30 岁之后，我用 C 语言作为教学工具，教高中生学习用 C 语言编程。我还用 Fritzing 教高中生如何编写 Arduino 程序。我对 C 语言编程的兴趣在去年再次被唤醒，当时我找到了一份工作，帮助大学生学习计算机科目中的差异。我如何接触 C 语言和其他语言进行编程每个人学习的方式都不一样。作为一个患有 阿斯伯格综合症 Asperger's 和多动症（ADHD）的 神经多样性 neurodiverse 人士，我的学习过程有时与其他人很不一样。当然，每个人都有不同的学习风格，尽管神经多样性人士可能比其他人更喜欢某种学习风格。我倾向于用图片和文字来思考。就我个人而言，我需要一步一步地解码事物，一步一步地理解它们。这使得 C 语言适合我的学习风格。当我学习代码的时候，我通过学习观察一行行的代码，比如我面前的 # include <stdio.h> ，逐渐将代码合并到我的大脑中。根据我在互联网上获取的对其他神经多样性人群的描述，他们中的一些人似乎也有这种学习风格。我们“内化代码”。有些自闭症人士在记忆大段代码方面比我强得多，但过程似乎是一样的。在理解诸如结构、指针、指针的指针、矩阵和向量之类的概念时，用图片来思考是很有帮助的，比如在编程教程和书籍中可以找到的那些。我喜欢使用 C 语言来理解工作是如何在较低的级别上完成的，例如 文件输入和输出（I/O）、网络编程等等。这并不意味着我不喜欢处理字符串操作或创建数组等任务的库。我也喜欢用 Java 语言创建数组和向量的简单性。然而，对于创建用户界面，尽管我已经在 C 语言中看过这样的代码，但是我更喜欢使用图形化编辑器，比如 Netbeans 和类似的编辑器。我理想中用于创建应用程序的 C 语言 GUI 开源工具如果我想象一个理想的用 C 语言创建 GUI 的开源工具，它将类似于 Netbeans，例如，通过拖放来创建 GTK 接口。还可以在按钮上绑定 C 语言函数，等等，来使它们执行操作。也许有这样一个工具。我承认我没怎么仔细查找过。为什么我鼓励年轻的神经多样性的人学习 C语言游戏行业 是一个很大的产业。一些研究表明，神经多样性的孩子可能比其他孩子更专注于游戏。我会告诉一个神经多样性的高中生或大学生，如果你学习 C 语言，你可能会学到一些基础知识，例如，为显卡编写高效的驱动程序，或者编写高效的文件 I/O 例程来优化他们最喜欢的游戏。我还要诚实地说，学习需要时间和精力，但是值得付出努力。一旦你学会了它，你就可以更好地控制硬件一类的东西。对于学习 C 语言，我建议一个神经多样性的孩子安装一个初学者友好的 Linux 发行版，然后在网上找到一些教程。我还建议一步一步地分解事物，并给它们绘制图表，例如，指针。我这样做是为了更好地理解这个概念，这对我很有效。最后，这就是它的意义所在: 不管老师和其他学生怎么说，找到一种适合你的学习方法，用它来学习你感兴趣的开源技能。这是可以做到的，任何人都可以做到。（题图：DA/f0d98968-4c13-4395-8414-3690bc20b0ae）via: https://opensource.com/article/22/5/my-journey-c-neurodiverse-perspective作者：Rikard Grossman-Nielsen 选题：lkxed 译者：CanYellow 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
如何编写 C 程序在 Linux 上创建音乐播放列表
使用我在 Linux 上制作的这个 C 程序在旅途中聆听你喜爱的歌曲。我最近在 Linux 中编写了一个 C 程序，从我广泛的 MP3 库中创建一个较小的随机 MP3 文件选集。该程序会遍历一个包含我的 MP3 库的目录，然后创建一个包含随机的、较小的歌曲选集的目录。然后我将这些 MP3 文件复制到我的智能手机上，以便随时随地收听。瑞典是一个人口稀少的国家，有许多农村地区没有完整的手机覆盖。这就是在智能手机上拥有 MP3 文件的原因之一。另一个原因是我并不总是有钱购买流媒体服务，所以我喜欢拥有自己喜欢的歌曲的副本。你可以从它的 Git 仓库 下载我的应用。我专门为 Linux 编写了它，部分原因是在 Linux 上很容易找到经过良好测试的文件 I/O 例程。多年前，我尝试使用专有的 C 库在 Windows 上编写相同的程序，但在尝试文件复制时遇到了困难。Linux 使用户可以轻松直接地访问文件系统。本着开源的精神，我没费多少力气就找到了 Linux 的文件 I/O 代码来激发我的灵感。我还发现了一些启发了我的分配内存的代码。我编写了随机数生成的代码。该程序的工作方式如下所述：询问源目录和目标目录。询问存放 MP3 文件的目录下的文件个数。搜索你希望复制的收藏的百分比（从 1.0% 到 88.0%）。如果你有 1000 个文件的集合，并希望从你的集合中复制 125 个文件而不是 120 个文件，你也可以输入 12.5% 之类的数字。我将上限设置为 88%，因为复制超过 88% 的库将基本生成与你的基础库相似的库。当然，代码是开源的，因此你可以根据自己的喜好自由修改。使用指针和 malloc 分配内存。一些操作需要内存，包括代表音乐收藏中文件的字符串列表。还有一个列表来保存随机生成的数字。生成所有文件范围内的随机数列表（例如，如果集合有 1000 个文件，则为 1 到 1000）。复制文件。其中一些部分比其他部分更简单，但代码只有大约 100 行：#include <dirent.h> #include <stdio.h> #include <string.h> #include <sys/types.h> /* include necessary header files */ #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #define BUF_SIZE 4096 /* use buffer of 4096 bytes */ #define OUTPUT_MODE 0700 /*protect output file */ #define MAX_STR_LEN 256 int main(void) { DIR *d; struct dirent *dir; char strTemp[256], srcFile[256], dstFile[256], srcDir[256], dstDir[256]; char **ptrFileLst; char buffer[BUF_SIZE]; int nrOfStrs=-1, srcFileDesc, dstFileDesc, readByteCount, writeByteCount, numFiles; int indPtrFileAcc, q; float nrFilesCopy; // vars for generatingRandNumList int i, k, curRanNum, curLstInd, numFound, numsToGen, largNumRange; int *numLst; float procFilesCopy; printf("Enter name of source Directory\n"); scanf("%s", srcDir); printf("Enter name of destionation Directory\n"); scanf("%s", dstDir); printf("How many files does the directory with mp3 files contain?\n"); scanf("%d", &numFiles); printf("What percent of the files do you wish to make a random selection of\n"); printf("enter a number between 1 and 88\n"); scanf("%f", &procFilesCopy); // allocate memory for filesList, list of random numbers ptrFileLst= (char**) malloc(numFiles * sizeof(char*)); for (i = 0; i < numFiles; i++) { ptrFileLst[i] = (char*)malloc(MAX_STR_LEN * sizeof(char)); } largNumRange = numFiles; nrFilesCopy = (procFilesCopy / 100) * numFiles; numsToGen = (int)((procFilesCopy / 100) * numFiles); printf("nrFilesCopy=%f", nrFilesCopy); printf("NumsToGen=%d", numsToGen); numLst = malloc(numsToGen * sizeof(int)); srand(time(0)); numLst[0] = rand() % largNumRange + 1; numFound=0; do { curRanNum = (int)rand() % largNumRange + 1; if (numLst[0] == curRanNum) { numFound=1; } } while(numFound == 1); numLst[1] = curRanNum; getchar(); curLstInd = 1; i = 0; while(1) { do { numFound = 0; curRanNum = (int)rand() % largNumRange + 1; for (int k = 0; k <= curLstInd; k++){ if (numLst[k] == curRanNum) numFound = 1; } } while(numFound == 1); numLst[curLstInd+1] = curRanNum; curLstInd++; i++; // numsToGen=Total numbers to generate minus two // already generated by the code above this loop if (i == (numsToGen-2)) break; } d = opendir(srcDir); if (d) { while ( (dir = readdir(d)) != NULL ) { strcpy(strTemp, dir->d_name); if (strTemp[0] != '.') { nrOfStrs++; strcpy(ptrFileLst[nrOfStrs], strTemp); } } closedir(d); } for (q = 0; q <= curLstInd; q++) { indPtrFileAcc = numLst[q]; strcpy(srcFile, srcDir); strcat(srcFile, "/"); strcat(srcFile, ptrFileLst[indPtrFileAcc]); strcpy(dstFile, dstDir); strcat(dstFile, "/"); strcat(dstFile, ptrFileLst[indPtrFileAcc]); srcFileDesc = open(srcFile, O_RDONLY); dstFileDesc = creat(dstFile, OUTPUT_MODE); while(1) { readByteCount = read(srcFileDesc, buffer, BUF_SIZE); if (readByteCount <= 0) break; writeByteCount = write(dstFileDesc, buffer, readByteCount); if(writeByteCount <= 0) exit(4); } //close the files close(srcFileDesc); close(dstFileDesc); } } 这段代码可能是最复杂的：while(1) { readByteCount = read(srcFileDesc, buffer, BUF_SIZE); if (readByteCount <= 0) break; writeByteCount = write(dstFileDesc, buffer, readByteCount); if (writeByteCount <= 0) exit(4); } 这将从指定的文件中读取多个字节（readByteCount）到字符缓冲区中。该函数的第一个参数是文件名（srcFileDesc）。第二个参数是一个指向字符缓冲区的指针，这之前在程序中声明过。该函数的最后一个参数是缓冲区的大小。程序返回读取的字节数（在本例中为 4 个字节）。如果返回的数字为 0 或更少，则第一个 if 子句会跳出循环。如果读取字节数为 0，则所有写入完成，循环中断以写入下一个文件。如果读取的字节数小于 0，则发生错误并退出程序。当读取 4 个字节时，它会写入它们。write 函数接受三个参数。第一个是要写入的文件，第二个是字符缓冲区，第三个是要写入的字节数（4 个字节） .该函数返回写入的字节数。如果写入了 0 个字节，则发生了写入错误，因此第二个 if 子句退出程序。while 循环读取并复制文件，一次 4 个字节，直到文件被复制。复制完成后，你可以将随机生成的 mp3 文件的目录复制到你的智能手机。复制和写入例程相当有效，因为它们使用 Linux 中的文件系统调用。改进代码该程序很简单，可以在用户界面和灵活性方面进行改进。例如，你可以实现一个计算源目录中文件数量的函数，这样你就不必手动输入它。你可以添加选项，这样你就可以非交互地传递百分比和路径。但是代码做了我需要它做的事情，它是 C 编程语言简单效率的演示。via: https://opensource.com/article/22/7/c-linux-mp3作者：Rikard Grossman-Nielsen 选题：lkxed 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出