Memo on C Language Programming

Starting yesterday I have been reading the official manual of C programming language from GNU. I have finished 17 chapters out of 20-something chapters of the whole manual. I realized that the best way to learn an open-source stuff is indeed to read the documentation/help manual.

Yesterday I covered basic knowledge of the programming language such as type, expression, function, and pointer. It didn’t take much time because I have read other materials on C before. I did spend some time understanding pointers since in Java there is no explicit definition of pointer.

Today’s new materials include IO, String operation and “making” a program with multiple C source code files. I’m going to write down here things new to me.

 

  1. File IO:
#include <stdio.h>
#include <stdlib.h>

int main() {
	FILE *stream;
	stream = fopen("shit.dat", "w");
	int my_array[2][2] =
	{
		{1,2},
		{3,4}
	};
	size_t object_size = sizeof(int);
	size_t object_count = 4;

	if (stream == NULL) {
		printf("shit.dat could not be created\n");
		exit(0);
	}
	printf("file opened for writing\n");
	fwrite(&my_array, object_size, object_count, stream);
	fclose(stream);
	
	stream = fopen("shit.dat", "r");
	if (stream == NULL) {
		printf("shit.dat could not be read\n");
		exit(0);
	}
	printf("file opened for reading\n");
	fread(&my_array, object_size, object_count, stream);
	fclose(stream);

	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 2; j++) {
			printf("%d ", my_array[i][j]);
		}
		printf("\n");
	}
	return 0;
}

Most important functions for input/output with files would be fopen, fclose, fread, fwrite, getline and fprintf. According to the manual, it is suggested to use fread, getline and fwrite since they are safer than the rest, some of which are already deprecated. It’s worth noting that the second and the third parameters of fwrite and fread are of type size_t. Other than this, this part is pretty easy.

 

2. Combination of getline and sscanf

getline is a safe method, if you pass in an uninitialized string pointer, the program will create a buffer of a proper size for you and populate the variable. However, if you use methods like scanf instead, you may encounter buffer overflow errors, which can be very common. getline returns a line of text before a linebreak from a stream, which can be either stdin or a file.

Then, sscanf is used to read stuff of a specific type or a format from the string. This combination, according to the manual, is much better than using scanf alone, since it avoids many errors.

Example code:

#include <stdlib.h>
#include <stdio.h>

int main()
{
	int args_assigned = 0;
	size_t nbytes = 2;
	char *my_string;
	int int1, int2, int3;

	while (args_assigned != 3)
	{
		puts("Please enter three integers separated by whitespace.");
		my_string = (char *) malloc(nbytes + 1);
		getline(&my_string, &nbytes, stdin);
		args_assigned = sscanf(my_string, "%d %d %d", &int1, &int2, &int3);
		if (args_assigned != 3)
		{
			puts("Invalid input!");
		}
		else
		{
			printf("Three integers: %d %d %d\n", int1, int2, int3);
		}
	}
	return 0;
}

It doesn’t matter that my_string is initialized with a very small size: getline will take care of that.

 

3. ARGP

ARGP is such a strong tool!! With this, it’s very easy to parse parameters passed to the program and provide the users with usage explanations and documentations interactively.

The boss function is argp_parse, which takes four parameters: 1. parameter options, in a struct type, 2. a function to handle the option and parameter fields, 3. a string describing the arguments format, 4. a string that documents the program.

There are so many options available for customization. Although it’s hard to remember all of the parameter types and requirements, in actual development process I can just copy the old example piece of code and continue happily from there.

Example code:

#include <stdio.h>
#include <argp.h>

const char *argp_program_version = "argex 1.0";
const char *argp_program_bug_address = "<han.yu@duke.edu>";

/* This structure is used by main to communicate with parse_opt. */
struct arguments
{
	char *args[2];
	int verbose;
	char *outfile;
	char *string1, *string2;
};

/*
 * 	OPTIONS. Field 1 in ARGP.
 * 	Order of fields: {NAME, KEY, ARG, FLAGS, DOC}.
*/
static struct argp_option options[] = 
{
	{"verbose", 'v', 0, 0, "Produce verbose output"},
	{"alpha", 'a', "STRING1", 0, "Do something with STRING1 related to the letter A"},
	{"bravo", 'b', "STRING2", 0, "Do something with STRING2 related to the letter B"},
	{"output", 'o', "OUTFILE", 0, "Output to OUTFILE instead of to standard output"},
	{0}
};

/*
 * PARSER. Field 2 in ARGP.
 * Order of parameters: KEY, ARG, STATE.
*/
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
	struct arguments *arguments = state->input;
	switch (key)
	{
		case 'v':
			arguments->verbose = 1;
			break;
		case 'a':
			arguments->string1 = arg;
			break;
		case 'b':
			arguments->string2 = arg;
			break;
		case 'o':
			arguments->outfile = arg;
			break;
		case ARGP_KEY_ARG:
			if (state->arg_num >= 2)
			{
				argp_usage(state);
			}
			arguments->args[state->arg_num] = arg;
			break;
		case ARGP_KEY_END:
			if (state->arg_num < 2)
			{
				argp_usage(state);
			}
			break;
		default:
			return ARGP_ERR_UNKNOWN;
	}
	return 0;
}

/*
 * ARGS_DOC. Field 3 in ARGP.
 * A description of the non-option command-line arguments that we accept.
*/
static char args_doc[] = "ARG1 ARG2";

/*
 * DOC. Field 4 in ARGP.
 * Program documentation.
*/
static char doc[] = 
"argex -- A program to demonstrate how to code command-line options and arguments.\vFrom the GNU C Tutorial.";

/*
 * The ARGP structure itself.
*/
static struct argp argp = {options, parse_opt, args_doc, doc};

/*
 * The main function.
 * Notic how now the only function call needed to process all command-line options and arguments nicely is argp_parse.
*/
int main (int argc, char **argv)
{
	struct arguments arguments;
	FILE *outstream;
	char waters[] = "Some long sentence";

	/* Set argument defaults */
	arguments.outfile = NULL;
	arguments.string1 = "";
	arguments.string2 = "";
	arguments.verbose = 0;

	/* Where the magic happens */
	argp_parse(&argp, argc, argv, 0, 0, &arguments);

	/* Where do we send output? */
	if (arguments.outfile)
			outstream = fopen(arguments.outfile, "w");
	else
		outstream = stdout;

	/* Print argument values */
	fprintf(outstream, "alpha = %s\nbravo = %s\n\n", arguments.string1, arguments.string2);
	fprintf(outstream, "ARG1 = %s\nARG2 = %s\n\n", arguments.args[0], arguments.args[1]);

	/* If in verbose mode, pring song stanza */
	if (arguments.verbose)
		fprintf(outstream, "%s", waters);

	return 0;
}

When it runs it really behaves like a “legit” GNU open source software!

 

I also read about makefiles: its rules, targets and variables that can simplify the code. I guess tomorrow I’ll read more about C. If I finish this manual I’ll take a look at the GNU Make manual.

Anyway, it’s cool that a book originally written 30 years ago is still not outdated at all.

 

9 thoughts on “Memo on C Language Programming”

  1. 它讓神經原在常規的緊張鍛煉中進行共振燃燒,由此帶來健身運動所無法達到的效果。Ion Magnum複雜的振動波是基于於二十多年對神經原燃燒信號的研究手工製作的。 設備製造者的臨床研究結果顯示,30分鐘的治療相當於在健身房10個小時的運動,可以燃燒高達5000卡路里的熱量。其他臨床研究顯示肌肉生成的速度以及脂肪(表面脂肪以及深部脂肪)减少的速度相應都比運動的效果更好。對於Ion Magnum沒有進行理療的部位,甚至會有抗衰老防氧化的效果。 有受試者治療一次之後同一個部位减掉了3-4英寸(不像其他减肥治療中宣稱的那樣,一次治療减掉了5英寸,但那是全身20多個部位加起來减掉的尺寸)。同時,它還可以减掉脖子和下巴的脂肪,讓你的雙下巴消失 . 每次治療需要25分鐘。治療前後的效果非常明顯,而且會持續1-2天。要想達到更好的效果,最好接受1-2個小時的治療。

  2. Derma Veil ® 被喻為新世代逆齡完美輪廓塑造,最新一代的PLLA膠原。 2003年獲得Mexican Ministry of Health (SSA)認證及美國FDA出口認證,並於2006年在拉丁美洲及遠東至東南亞地區廣泛使用,多個臨床實例見證能改善老化、遺傳、疾病(如脂肪萎縮)等引起的凹陷問題,其效果備受認同。蘊含兩大活性成分均具有生物兼容性及分解性,可逐步被人體自然分解吸收,有效塑造童顏肌 : 1. 聚左乳酸 (Poly-L-lactic acid / PLLA) : 促進骨膠原生長 2. 甘醇酸(Glycolic Acid ) 使皮膚表皮層黏膠性脂質鬆軟,改善皮膚厚度,加速細胞再生,減少皺紋及疤痕,加強保濕功能,增加光澤,美白效果。 由於甘醇酸分子較小,容易滲透皮膚 治療前: 皮膚的凹陷/皺紋 治療後: 成分被人體吸收、並刺激膠原增生,撫平皺紋及凹陷部位。 注入BOTOX(保妥適)會抑制突觸前膜釋放神經遞質,阻斷乙酰膽鹼(Acetylcholine)的釋放,從而使肌肉張力下降或癱瘓麻痺,皺紋也隨之而逐漸消失。

  3. 不黏膩持久的泥好蠟KMS中性風儀容全新3支型塑定型產品擺脫黏膩感創新最輕質地造型品激推 @ 潮流、美妝、消費 創造個人化風格的女性社群 PIXstyleMe 不黏膩持久的泥好蠟KMS中性風儀容全新3支型塑定型產品擺脫黏膩感創新最輕質地造型品激推

Leave a Reply

Your email address will not be published. Required fields are marked *