提交 0bef2f4b 编写于 作者: B Ben
......@@ -3,7 +3,7 @@
Dear Reader,
Here are all of the examples from _21st Century C_ by Ben Klemens [ http://tinyurl.com/C-for-moderns ]. You'll notice that the captions for all of the examples in the text end in a filename in parens, like (string_utilities.c); that name is referring to the file here.
Here are all of the examples from the second edition of _21st Century C_ by Ben Klemens [ http://tinyurl.com/c-for-moderns-2 ]. You'll notice that the captions for all of the examples in the text end in a filename in parens, like (string_utilities.c); that name is referring to the file here.
* Each .c file has a note about how to compile it. Some involve a makefile, and some have a command or two to cut/paste onto your command line. dict_use.c includes an extensive script that runs autoconf on the system.
......@@ -22,7 +22,7 @@ Here's the GNU sed command to do the changes on every .c file in the current dir
#For Clang and icc, which don't need the -std=... flag at all:
sed -i -e 's/-std=gnu11//g' *.c
* If you get linker errors about resolving the (common but not C-standard) function asprintf, use the libiberty library, which means adding the -liberty flag to your LDLIBS. For example, MSYS includes libiberty as part of its development package. As a last resort, I have provided the source code for asprintf here.
* If you get linker errors about resolving the (common but not C-standard) function asprintf, use the version provided as an example in asprintf.c, and the function declaration in that file. Or use the libiberty library, which means adding the -liberty flag to your LDLIBS. For example, MSYS includes libiberty as part of its development package.
Have fun with them,
......
/* Compile with:
CFLAGS="-g -Wall -std=gnu11 -O3 -DTest_asprintf" make asprintf
*/
#ifndef HAVE_ASPRINTF
#include <stdio.h> //vsnprintf
#include <stdlib.h> //malloc
#include <stdarg.h> //va_start et al
/* The declaration, to put into a .h file. The __attribute__ tells the compiler to check printf-style type-compliance.
It's not C standard, but a lot of compilers support it. Just remove it if yours doesn't. */
int asprintf(char **str, char* fmt, ...) __attribute__ ((format (printf,2,3)));
int asprintf(char **str, char* fmt, ...){
va_list argp;
va_start(argp, fmt);
char one_char[1];
int len = vsnprintf(one_char, 1, fmt, argp);
if (len < 1){
fprintf(stderr, "An encoding error occurred. Setting the input pointer to NULL.\n");
*str = NULL;
va_end(argp);
return len;
}
va_end(argp);
*str = malloc(len+1);
if (!str) {
fprintf(stderr, "Couldn't allocate %i bytes.\n", len+1);
return -1;
}
va_start(argp, fmt);
vsnprintf(*str, len+1, fmt, argp);
va_end(argp);
return len;
}
#endif
#ifdef Test_asprintf
int main(){
char *s;
asprintf(&s, "hello, %s.", "—Reader—");
printf("%s\n", s);
free(s);
asprintf(&s, "%c", '\0');
printf("blank string: [%s]\n", s);
free(s);
int i = 0;
asprintf(&s, "%i", i++);
printf("Zero: %s\n", s);
free(s);
}
#endif
/* Compile with:
export CFLAGS="-g -Wall -O3 --std=c11 -pthread -latomic"
make c_factors
*/
#include <pthread.h>
#include <stdatomic.h>
#include <stdlib.h> //malloc
#include <string.h> //memset
#include <stdio.h>
int get_max_factors(_Atomic(int) *factor_ct, long int max){
//single-threading to save verbiage.
int global_max=0;
for (long int i=0; i< max; i++){
if (factor_ct[i] > global_max)
global_max = factor_ct[i];
}
return global_max;
}
typedef struct {
_Atomic long int *tally;
atomic_int *factor_ct;
int max, thread_ct, this_thread;
} tally_s;
void *add_tally(void *vin){
tally_s *in = vin;
for (long int i=in->this_thread; i < in->max; i += in->thread_ct){
int factors = in->factor_ct[i];
in->tally[factors]++;
}
return NULL;
}
typedef struct {
long int i, max;
_Atomic(int) *factor_ct;
} one_factor_s;
void *mark_factors(void *vin){
one_factor_s *in = vin;
long int si = 2*in->i;
for (long int scale=2; si < in->max; scale++, si=scale*in->i) {
in->factor_ct[si]++;
}
return NULL;
}
int main(){
long int max = 1e7;
_Atomic(int) *factor_ct = malloc(sizeof(_Atomic(int))*max);
int thread_ct = 4;
pthread_t threads[thread_ct];
atomic_init(factor_ct, 0);
atomic_init(factor_ct+1, 1);
for (long int i=2; i< max; i++)
atomic_init(factor_ct+i, 2);
one_factor_s x[thread_ct];
for (long int i=2; i<= max/2; i+=thread_ct){
for (int t=0; t < thread_ct && t+i <= max/2; t++){
x[t] = (one_factor_s){.i=i+t, .max=max,
.factor_ct=factor_ct};
pthread_create(&threads[t], NULL, mark_factors, x+t);
}
for (int t=0; t< thread_ct && t+i <=max/2; t++)
pthread_join(threads[t], NULL);
}
int max_factors = get_max_factors(factor_ct, max);
_Atomic(long int) tally[max_factors+1];
memset(tally, 0, sizeof(long int)*(max_factors+1));
tally_s thread_info[thread_ct];
for (int i=0; i< thread_ct; i++){
thread_info[i] = (tally_s){.this_thread=i, .thread_ct=thread_ct,
.tally=tally, .max=max,
.factor_ct=factor_ct};
pthread_create(&threads[i], NULL, add_tally, thread_info+i);
}
for (int t=0; t< thread_ct; t++)
pthread_join(threads[t], NULL);
for (int i=0; i<max_factors+1; i++)
printf("%i\t%li\n", i, tally[i]);
}
/* Compile with:
export CFLAGS="-g -Wall -O3 --std=c11 -pthread -latomic"
export LDLIBS="-lm"
make c_primes
*/
#include <stdio.h>
#include <stdatomic.h>
#include <stdlib.h> //malloc
#include <stdbool.h>
#include <pthread.h>
#include <math.h> //sqrt
typedef struct {
long int *plist;
long int length;
long int max;
} prime_s;
int add_a_prime(_Atomic prime_s *pin, long int new_prime){
prime_s p = atomic_load(pin);
p.length++;
p.plist = realloc(p.plist, sizeof(long int) * p.length);
if (!p.plist) return 1;
p.plist[p.length-1] = new_prime;
if (new_prime > p.max) p.max = new_prime;
atomic_store(pin, p);
return 0;
}
typedef struct{
long int i;
_Atomic prime_s *prime_list;
pthread_mutex_t *mutex;
} test_s;
void* test_a_number(void *vin){
test_s *in = vin;
long int i = in->i;
prime_s pview;
do {
pview = atomic_load(in->prime_list);
} while (pview.max*2 < i);
bool is_prime = true;
for (int j=0; j < pview.length && pview.plist[j] <= sqrt(i); j++)
if (!(i % pview.plist[j])){
is_prime = false;
break;
}
if (is_prime){
pthread_mutex_lock(in->mutex);
int retval = add_a_prime(in->prime_list, i);
if (retval) {printf("Too many primes.\n"); exit(0);}
pthread_mutex_unlock(in->mutex);
}
return NULL;
}
int main(){
prime_s inits = {.plist=NULL, .length=0, .max=0};
_Atomic prime_s prime_list = ATOMIC_VAR_INIT(inits);
pthread_mutex_t m;
pthread_mutex_init(&m, NULL);
int thread_ct = 3;
test_s ts[thread_ct];
pthread_t threads[thread_ct];
add_a_prime(&prime_list, 2);
long int max = 1e6;
for (long int i=3; i< max; i+=thread_ct){
for (int t=0; t < thread_ct && t+i < max; t++){
ts[t] = (test_s) {.i = i+t, .prime_list=&prime_list, .mutex=&m};
pthread_create(threads+t, NULL, test_a_number, ts+t);
}
for (int t=0; t< thread_ct && t+i <max; t++)
pthread_join(threads[t], NULL);
}
prime_s pview = atomic_load(&prime_list);
for (int j=0; j < pview.length; j++)
printf("%li\n", pview.plist[j]);
}
......@@ -15,7 +15,7 @@ dictionary *dictionary_new (void){
static void dictionary_add_keyval(dictionary *in, keyval *kv){
in->length++;
in->pairs = realloc(in->pairs, sizeof(keyval*)*in->length);
in->pairs = realloc(in->pairs, in->length*sizeof(keyval*));
in->pairs[in->length-1] = kv;
}
......@@ -41,5 +41,6 @@ dictionary *dictionary_copy(dictionary *in){
void dictionary_free(dictionary *in){
for (int i=0; i< in->length; i++)
keyval_free(in->pairs[i]);
free(in->pairs);
free(in);
}
......@@ -2,7 +2,7 @@
----------
#Or, use the script in dict_use.c to use as an Autotools build check.
CFLAGS=-g -Wall -O3 `pkg-config --cflags glib-2.0`
LDADD=`pkg-config --libs glib-2.0`
LDLIBS=`pkg-config --libs glib-2.0`
dict_test: dict.o keyval.o
----------
......@@ -44,10 +44,11 @@ void test_copy(dfixture *df, gconstpointer ignored){
}
void test_failure(){
if (g_test_trap_fork(0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)){
if (g_test_subprocess()){ //we are in the sub-test.
dictionary *dd = dictionary_new();
dictionary_add(dd, NULL, "blank");
}
g_test_trap_subprocess(NULL, 0, 0);
g_test_trap_assert_failed();
g_test_trap_assert_stderr("NULL is not a valid key.\n");
}
......
/* Compile with:
LDLIBS="-lm -ldl -lreadline" CFLAGS="-g -Wall -std=gnu11 -O3" make dynamic
*/
#define _GNU_SOURCE //cause stdio.h to include asprintf
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -12,25 +11,23 @@ void get_a_function(){
fprintf(f, "#include <math.h>\n"
"double fn(double in){\n");
char *a_line = NULL;
char *header = ">>double fn(double in){\n>> ";
char *prompt = ">>double fn(double in){\n>> ";
do {
free(a_line);
a_line = readline(header);
a_line = readline(prompt);
fprintf(f, "%s\n", a_line);
header = ">> ";
prompt = ">> ";
} while (strcmp(a_line, "}"));
fclose(f);
}
void compile_and_run(){
char *run_me;
asprintf(&run_me, "c99 -fPIC -shared fn.c -o fn.so");
if (system(run_me)!=0){
if (system("c99 -fPIC -shared fn.c -o fn.so")!=0){
printf("Compilation error.");
return;
}
void *handle = dlopen("fn.so", RTLD_LAZY);
void *handle = dlopen("./fn.so", RTLD_LAZY);
if (!handle) printf("Failed to load fn.so: %s\n", dlerror());
typedef double (*fn_type)(double);
......
......@@ -12,7 +12,7 @@ double one_dist(gsl_vector *v1, void *v2){
long double distance(apop_data *data, apop_model *model){
gsl_vector *target = model->parameters->vector;
return -apop_map_sum(data, .fn_vp=one_dist, .param=target, .part='r');
return -apop_map_sum(data, .fn_vp=one_dist, .param=target);
}
apop_model *min_distance= &(apop_model){
......@@ -25,9 +25,8 @@ int main(){
2.9, 8.6,
-1.3, 3.7,
2.9, 1.1);
Apop_model_add_group(min_distance, apop_mle, .method= APOP_SIMPLEX_NM,
Apop_model_add_group(min_distance, apop_mle, .method= "NM simplex",
.tolerance=1e-5);
Apop_model_add_group(min_distance, apop_parts_wanted);
apop_model *est=apop_estimate(locations, min_distance);
apop_model *est = apop_estimate(locations, min_distance);
apop_model_show(est);
}
push:
@if [ "x$(MSG)" = 'x' ] ; then \
echo "Usage: MSG='whatever.' make push"; fi
echo "Usage: MSG='your message here.' make push"; fi
@test "x$(MSG)" != 'x'
git commit -a -m "$(MSG)"
git svn fetch
......
/* Suggested makefile:
----------
P=mapreduce_wc
objects=string_utilities.o
CFLAGS=`pkg-config --cflags glib-2.0` -g -Wall -std=gnu99 -O3 -fopenmp
LDLIBS=`pkg-config --libs glib-2.0` -fopenmp
$(P): $(objects)
----------
*/
#include "stopif.h"
#include "wordcount.c"
int main(int argc, char **argv){
argc--;
argv++;
Stopif(!argc, return 0, "Please give some file names on the command line.");
long int total_wc = 0;
#pragma omp parallel for \
reduction(+:total_wc)
for (int i=0; i< argc; i++){
long int this_count = wc(argv[i]);
total_wc += this_count;
printf("%s:\t%li\n", argv[i], this_count);
}
printf("Σ:\t%li\n", total_wc);
}
/* Compile with:
export CFLAGS="-g -Wall -std=gnu11 -O3" #the usual.
make na
CFLAGS="-g -Wall -std=gnu11 -O3 -lm" make na
*/
#include <stdio.h>
#include <math.h> //isnan
#include <math.h> //isnan, NAN, nan
double ref;
double set_na(){
if (!ref) {
ref=0/0.;
char *cr = (char *)(&ref);
cr[2]='a';
}
if (!ref) ref=nan("21");
return ref;
}
......
/* Compile with:
CFLAGS="-g -Wall -std=gnu11 -O3" make noreturn #the usual.
*/
#include <stdio.h>
#include <unistd.h> //sleep
#include <stdlib.h> //exit, _Exit, et al.
void wail(){
fprintf(stderr, "OOOOooooooo.\n");
}
void on_death(){
for (int i=0; i<4; i++)
fprintf(stderr, "I'm dead.\n");
}
_Noreturn void the_count(){
for (int i=5; i --> 0;){
printf("%i\n", i); sleep(1);
}
//quick_exit(1);
//_Exit(1);
exit(1);
}
int main(){
at_quick_exit(wail);
atexit(wail);
atexit(on_death);
the_count();
}
/* Suggested makefile:
----------
P=openmp_atoms
CFLAGS=-g -Wall -std=gnu99 -O3 -fopenmp
$(P):
----------
*/
#include <omp.h>
#include <stdio.h>
#include <string.h> //memset
#include "openmp_getmax.c"
int main(){
long int max = 1e7;
int *factor_ct = malloc(sizeof(int)*max);
factor_ct[0] = 0;
factor_ct[1] = 1;
for (long int i=2; i< max; i++)
factor_ct[i] = 2;
#pragma omp parallel for
for (long int i=2; i<= max/2; i++)
for (long int scale=2; scale*i < max; scale++) {
#pragma omp atomic update
factor_ct[scale*i]++;
}
int max_factors = get_max(factor_ct, max);
long int tally[max_factors+1];
memset(tally, 0, sizeof(long int)*(max_factors+1));
#pragma omp parallel for
for (long int i=0; i< max; i++){
#pragma omp atomic update
tally[factor_ct[i]]++;
}
for (int i=0; i<=max_factors; i++)
printf("%i\t%li\n", i, tally[i]);
}
/* Suggested makefile:
----------
P=openmp_factors
CFLAGS=`pkg-config --cflags glib-2.0` -g -Wall -std=gnu99 -O3 -fopenmp
LDLIBS=`pkg-config --libs glib-2.0` -fopenmp
$(P):
----------
*/
#include <omp.h>
#include <stdio.h>
#include <stdlib.h> //malloc
#include <string.h> //memset
#include "openmp_getmax.c"
int main(){
long int max = 1e7;
int *factor_ct = malloc(sizeof(int)*max);
int lock_ct = 128;
omp_lock_t locks[lock_ct];
for (long int i=0; i< lock_ct; i++)
omp_init_lock(&locks[i]);
factor_ct[0] = 0;
factor_ct[1] = 1;
for (long int i=2; i< max; i++)
factor_ct[i] = 2;
#pragma omp parallel for
for (long int i=2; i<= max/2; i++)
for (long int scale=2; scale*i < max; scale++) {
omp_set_lock(&locks[scale*i % lock_ct]);
factor_ct[scale*i]++;
omp_unset_lock(&locks[scale*i % lock_ct]);
}
int max_factors = get_max(factor_ct, max);
long int tally[max_factors+1];
memset(tally, 0, sizeof(long int)*(max_factors+1));
#pragma omp parallel for
for (long int i=0; i< max; i++){
int factors = factor_ct[i];
omp_set_lock(&locks[factors % lock_ct]);
tally[factors]++;
omp_unset_lock(&locks[factors % lock_ct]);
}
for (int i=0; i<=max_factors; i++)
printf("%i\t%li\n", i, tally[i]);
}
/* See compilation notes in atomic_factors.c, openmp_atoms.c, or pthread_factors.c*/
int get_max(int *array, long int max){
int thread_ct = omp_get_max_threads();
int maxes[thread_ct];
memset(maxes, 0, sizeof(int)*thread_ct);
#pragma omp parallel for
for (long int i=0; i< max; i++){
int this_thread = omp_get_thread_num();
if (array[i] > maxes[this_thread])
maxes[this_thread] = array[i];
}
int global_max=0;
for (int i=0; i< thread_ct; i++)
if (maxes[i] > global_max)
global_max = maxes[i];
return global_max;
}
/* Suggested makefile:
----------
P=openmp_wc
objects=string_utilities.o
CFLAGS=`pkg-config --cflags glib-2.0` -g -Wall -std=gnu99 -O3 -fopenmp
LDLIBS=`pkg-config --libs glib-2.0` -fopenmp
$(P): $(objects)
----------
*/
#include "stopif.h"
#include "wordcount.c"
int main(int argc, char **argv){
argc--;
argv++;
Stopif(!argc, return 0, "Please give some file names on the command line.");
int count[argc];
#pragma omp parallel for
for (int i=0; i< argc; i++){
count[i] = wc(argv[i]);
printf("%s:\t%i\n", argv[i], count[i]);
}
long int sum=0;
for (int i=0; i< argc; i++) sum+=count[i];
printf("Σ:\t%li\n", sum);
}
/* Compile with:
CFLAGS="-g -Wall -std=gnu11 -O3" make print_dispatch
*/
#define skip_main
#include "print_methods.c"
textlist_s recipe = {.title="Starfish and Coffee",
.len=2, .items=(char*[]){"Starfish", "Coffee"}};
void textlist_print(textlist_s *in){
if (in->print){
in->print(in);
return;
}
printf("Title: %s\n\nItems:\n", in->title);
for (int i=0; i< in->len; i++)
printf("\t%s\n", in->items[i]);
}
int main(){
textlist_print(&save);
printf("\n-----\n\n");
textlist_print(&recipe);
}
/* Compile with:
CFLAGS="-g -Wall -std=gnu11 -O3" make print_methods
*/
#include <stdio.h>
#include "print_typedef.h"
static void print_ad(textlist_s *in){
printf("BUY THIS %s!!!! Features:\n", in->title);
for (int i=0; i< in->len; i++)
printf("∙ %s\n", in->items[i]);
}
static void print_song(textlist_s *in){
printf("♫ %s ♫\nLyrics:\n\n", in->title);
for (int i=0; i< in->len; i++)
printf("\t%s\n", in->items[i]);
}
textlist_s save = {.title="God Save the Queen",
.len=3, .items=(char*[]){
"There's no future", "No future", "No future for me."},
.print=print_song};
textlist_s spend = {.title="Never mind the Bollocks LP",
.items=(char*[]){"By the Sex Pistols", "Anti-consumption themes"},
.len=2, .print=print_ad};
#ifndef skip_main
int main(){
save.print(&save);
printf("\n-----\n\n");
spend.print(&spend);
}
#endif
#ifndef textlist_s_h
#define textlist_s_h
typedef struct textlist_s {
char *title;
char **items;
int len;
void (*print)(struct textlist_s*);
} textlist_s;
#endif
/* See compilation notes in print_vtable_use.c*/
#include <stdio.h>
#include "print_vtable.h"
GHashTable *print_fns;
void check_print_fn(print_fn_type pf) { }
void textlist_print_html(textlist_s *in){
if (!print_fns) print_fns = g_hash_table_new(g_direct_hash, g_direct_equal);
print_fn_type ph = g_hash_table_lookup(print_fns, in->print);
if (ph) {
ph(in);
return;
}
printf("<title>%s</title>\n<ul>", in->title);
for (int i=0; i < in->len; i++)
printf("<li>%s</li>\n", in->items[i]);
printf("</ul>\n");
}
/* See compilation notes in print_vtable_use.c*/
#include <glib.h>
#include "print_typedef.h"
extern GHashTable *print_fns;
typedef void (*print_fn_type)(textlist_s*);
void check_print_fn(print_fn_type pf);
#define print_hash_add(object, print_fn){ \
check_print_fn(print_fn); \
g_hash_table_insert(print_fns, (object)->print, print_fn); \
}
void textlist_print_html(textlist_s *in);
/* Suggested makefile:
----------
P=print_vtable_use
objects=print_vtable.o
CFLAGS=`pkg-config --cflags glib-2.0` -g -Wall -std=gnu11 -O3
LDLIBS=`pkg-config --libs glib-2.0`
$(P): $(objects)
----------
*/
#define skip_main
#include "print_methods.c"
#include "print_vtable.h"
static void song_print_html(textlist_s *in){
printf("<title>♫ %s ♫</title>\n", in->title);
for (int i=0; i < in->len; i++)
printf("%s<br>\n", in->items[i]);
}
int main(){
textlist_print_html(&save);
printf("\n-----\n\n");
print_hash_add(&save, song_print_html);
textlist_print_html(&save);
}
/* Compile with:
export CFLAGS="-g -Wall -O3 --std=c99 -pthread -fopenmp"
make pthread_factors
*/
#include <omp.h> //get_max is still OpenMP
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> //malloc
#include <string.h> //memset
#include "openmp_getmax.c"
typedef struct {
long int *tally;
int *factor_ct;
int max, thread_ct, this_thread, mutex_ct;
pthread_mutex_t *mutexes;
} tally_s;
void *add_tally(void *vin){
tally_s *in = vin;
for (long int i=in->this_thread; i < in->max; i += in->thread_ct){
int factors = in->factor_ct[i];
pthread_mutex_lock(&in->mutexes[factors % in->mutex_ct]);
in->tally[factors]++;
pthread_mutex_unlock(&in->mutexes[factors % in->mutex_ct]);
}
return NULL;
}
typedef struct {
long int i, max, mutex_ct;
int *factor_ct;
pthread_mutex_t *mutexes ;
} one_factor_s;
void *mark_factors(void *vin){
one_factor_s *in = vin;
long int si = 2*in->i;
for (long int scale=2; si < in->max; scale++, si=scale*in->i) {
pthread_mutex_lock(&in->mutexes[si % in->mutex_ct]);
in->factor_ct[si]++;
pthread_mutex_unlock(&in->mutexes[si % in->mutex_ct]);
}
return NULL;
}
int main(){
long int max = 1e7;
int *factor_ct = malloc(sizeof(int)*max);
int thread_ct = 4, mutex_ct = 128;
pthread_t threads[thread_ct];
pthread_mutex_t mutexes[mutex_ct];
for (long int i=0; i< mutex_ct; i++)
pthread_mutex_init(&mutexes[i], NULL);
factor_ct[0] = 0;
factor_ct[1] = 1;
for (long int i=2; i< max; i++)
factor_ct[i] = 2;
one_factor_s x[thread_ct];
for (long int i=2; i<= max/2; i+=thread_ct){
for (int t=0; t < thread_ct && t+i <= max/2; t++){//extra threads do no harm.
x[t] = (one_factor_s){.i=i+t, .max=max,
.factor_ct=factor_ct, .mutexes=mutexes, .mutex_ct=mutex_ct};
pthread_create(&threads[t], NULL, mark_factors, &x[t]);
}
for (int t=0; t< thread_ct; t++)
pthread_join(threads[t], NULL);
}
FILE *o=fopen("xpt", "w");
for (long int i=0; i < max; i ++){
int factors = factor_ct[i];
fprintf(o, "%i %li\n", factors, i);
}
fclose(o);
int max_factors = get_max(factor_ct, max);
long int tally[max_factors+1];
memset(tally, 0, sizeof(long int)*(max_factors+1));
tally_s thread_info[thread_ct];
for (int i=0; i< thread_ct; i++){
thread_info[i] = (tally_s){.this_thread=i, .thread_ct=thread_ct,
.tally=tally, .max=max, .factor_ct=factor_ct,
.mutexes=mutexes, .mutex_ct =mutex_ct};
pthread_create(&threads[i], NULL, add_tally, &thread_info[i]);
}
for (int t=0; t< thread_ct; t++)
pthread_join(threads[t], NULL);
for (int i=0; i<=max_factors; i++)
printf("%i\t%li\n", i, tally[i]);
}
pyexec_LTLIBRARIES=libpvnrt.la
libpvnrt_la_SOURCES=ideal.c
pyexec_LIBRARIES=libpvnrt.a
libpvnrt_a_SOURCES=ideal.c
SUBDIRS=.
......
......@@ -4,13 +4,13 @@
# then the usual ./configure; make; sudo make install.
if [ -e autodemo ]; then sudo rm -r autodemo; fi
if [ -e autodemo ]; then rm -r autodemo; fi
mkdir -p autodemo
cp ../ideal.h ../ideal.c Makefile.am configure.ac autodemo/
cd autodemo
touch NEWS README AUTHORS ChangeLog #still cheating.
mkdir py
cp ../setup.py ../ideal.py.c py/
cp ../setup.py.in ../ideal.py.c py/
cp ../Makefile.py.am py/Makefile.am
autoreconf -iv
......
......@@ -14,5 +14,5 @@ if test "$PYTHON" != : ; then
AC_CONFIG_SUBDIRS([py])
fi
AC_CONFIG_FILES([Makefile py/Makefile])
AC_CONFIG_FILES([Makefile py/Makefile py/setup.py])
AC_OUTPUT
......@@ -2,10 +2,10 @@ from distutils.core import setup, Extension
py_modules= ['pvnrt']
Emodule = Extension('pvnrt',
libraries=['pvnrt'],
library_dirs=['..'],
sources = ['ideal.py.c'])
Emodule = Extension('pvnrt', ['ideal.py.c']
, library_dirs=['@srcdir@/..']
, libraries=['pvnrt']
)
setup (name = 'pvnrt',
#provides='pvnrt',
......
/* Compile with:
CFLAGS="-g -Wall -O3 --std=gnu11 -Dtest_regexes" make regex
*/
#define _GNU_SOURCE //cause stdio.h to include asprintf
#include "stopif.h"
#include <regex.h>
#include "regex_fns.h"
#include <string.h> //strlen
#include <stdlib.h> //malloc, memcpy
static int count_parens(const char *string){
int out = 0;
int last_was_backslash = 0;
for(const char *step=string; *step !='\0'; step++){
if (*step == '\\' && !last_was_backslash){
last_was_backslash = 1;
continue;
}
if (*step == ')' && !last_was_backslash)
out++;
last_was_backslash = 0;
}
return out;
}
int regex_match_base(regex_fn_s in){
Stopif(!in.string, return -1, "NULL string input");
Stopif(!in.regex, return -2, "NULL regex input");
regex_t re;
int matchcount = 0;
if (in.substrings) matchcount = count_parens(in.regex);
regmatch_t result[matchcount+1];
int compiled_ok = !regcomp(&re, in.regex, REG_EXTENDED
+ (in.use_case ? 0 : REG_ICASE)
+ (in.substrings ? 0 : REG_NOSUB) );
Stopif(!compiled_ok, return -3, "This regular expression didn't compile: \"%s\"", in.regex);
int found = !regexec(&re, in.string, matchcount+1, result, 0);
if (!found) return 0;
if (in.substrings){
*in.substrings = malloc(sizeof(char*) * matchcount);
char **substrings = *in.substrings;
//match zero is the whole string; ignore it.
for (int i=0; i< matchcount; i++){
if (result[i+1].rm_eo > 0){//GNU peculiarity: match-to-empty marked with -1.
int length_of_match = result[i+1].rm_eo - result[i+1].rm_so;
substrings[i] = malloc(strlen(in.string)+1);
memcpy(substrings[i], in.string + result[i+1].rm_so, length_of_match);
substrings[i][length_of_match] = '\0';
} else { //empty match
substrings[i] = malloc(1);
substrings[i][0] = '\0';
}
}
in.string += result[0].rm_eo; //end of whole match;
}
regfree(&re);
return matchcount;
}
char * search_and_replace(char const *base, char const*search, char const *replace){
char *regex, *out;
asprintf(&regex, "(.*)(%s)(.*)", search);
char **substrings;
int match_ct = regex_match(base, regex, &substrings);
if(match_ct < 3) return NULL;
asprintf(&out, "%s%s%s", substrings[0], replace, substrings[2]);
for (int i=0; i< match_ct; i++)
free(substrings[i]);
free(substrings);
return out;
}
#ifdef test_regexes
int main(){
char **substrings;
int match_ct = regex_match("Hedonism by the alps, savory foods at every meal.",
"([He]*)do.*a(.*)s, (.*)or.* ([em]*)al", &substrings);
printf("%i matches:\n", match_ct);
for (int i=0; i< match_ct; i++){
printf("[%s] ", substrings[i]);
free(substrings[i]);
}
free(substrings);
printf("\n\n");
match_ct = regex_match("", "([[:alpha:]]+) ([[:alpha:]]+)", &substrings);
Stopif(match_ct != 0, return 1, "Error: matched a blank");
printf("Without the L, Plants are: %s", search_and_replace("Plants\n", "l", ""));
}
#endif
/* See compilation notes in regex.c*/
typedef struct {
const char *string;
const char *regex;
char ***substrings;
_Bool use_case;
} regex_fn_s;
#define regex_match(...) regex_match_base((regex_fn_s){__VA_ARGS__})
int regex_match_base(regex_fn_s in);
char * search_and_replace(char const *base, char const*search, char const *replace);
/* Compile with:
make LDLIBS='-lm' CFLAGS="-g -Wall -std=gnu11" seamlessthree
*/
#include <stdio.h>
#include <math.h>
typedef struct point {
double x, y;
} point;
typedef struct {
union {
struct {
double x, y;
};
point p2;
};
double z;
} threepoint;
double length (point p){
return sqrt(p.x*p.x + p.y*p.y);
}
double threelength (threepoint p){
return sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
}
int main(){
threepoint p = {.x=3, .y=0, .z=4};
printf("p is %g units from the origin\n", threelength(p));
double xylength = length(p.p2);
printf("Its projection onto the XY plane is %g units from the origin\n", xylength);
}
/* Compile with:
make LDLIBS='-lm' CFLAGS="-g -Wall -std=gnu11 --ms-extensions" seamlesstwo
make LDLIBS='-lm' CFLAGS="-g -Wall -std=gnu11 -fms-extensions" seamlesstwo
*/
#include <stdio.h>
#include <math.h>
......
......@@ -8,12 +8,12 @@ char error_mode;
/** To where should I write errors? If this is \c NULL, write to \c stderr. */
FILE *error_log;
#define Stopif(assertion, error_action, ...) do { \
#define Stopif(assertion, error_action, ...) { \
if (assertion){ \
fprintf(error_log ? error_log : stderr, __VA_ARGS__); \
fprintf(error_log ? error_log : stderr, "\n"); \
if (error_mode=='s') abort(); \
else {error_action;} \
} } while(0)
} }
/* Compile with:
export CFLAGS="-g -Wall -std=gnu11 -O3" #the usual.
make strtod
*/
#include "stopif.h"
#include <stdlib.h> //strtod
#include <math.h> //pow
......@@ -8,5 +12,5 @@ int main(int argc, char **argv){
double in = strtod(argv[1], &end);
Stopif(*end, return 2, "I couldn't parse '%s' to a number. "
"I had trouble with '%s'.", argv[1], end);
printf("The square of %g is %g\n", argv[1], pow(in, 2));
printf("The square of %s is %g\n", argv[1], pow(in, 2));
}
/* Compile with:
export CFLAGS="-g -Wall -std=gnu11 -O3" #the usual.
make times_table
*/
#include <math.h> //NAN
#include <stdio.h>
......@@ -9,7 +13,6 @@ void matrix_cross_base(double *list1, double *list2){
int count1 = 0, count2 = 0;
while (!isnan(list1[count1])) count1++;
while (!isnan(list2[count2])) count2++;
if (!count1 || !count2) {printf("missing data."); return;}
for (int i=0; i<count1; i++){
for (int j=0; j<count2; j++)
......
#include <stdlib.h>
#include <stdio.h>
void double_in(int *in){
*in *= 2;
}
int main(){
int x= 10;
double_in(&x);
printf("x is now %i.\n", x);
}
#include <assert.h>
int main(){
int list[100];
int *list2 = list; //Declares list2 as a pointer-to-int,
//pointing to the same block of memory list points to.
*list2 = 7; //list2 is a pointer-to-int, so *list2 is an int.
assert(list[0] == 7);
}
#include <stdio.h>
int main(){
printf("13./5=%g\n", 13./5);
printf("13/5=%i\n", 13/5);
printf("13%%5=%i\n", 13%5);
}
#include <stdio.h>
void loops(int max){
int i=0;
do {
printf("Hello #%i\n", i);
i++;
} while (i < max); //Note the semicolon.
}
int main(){
loops(3); //prints three greetings
loops(0); //prints one greeting
}
#include <stdio.h>
void error_print(FILE *ef, int error_code, char *msg){
fprintf(ef, "Error #%i occurred: %s.\n", error_code, msg);
}
int main(){
FILE *error_file = fopen("example_error_file", "w"); //open for writing
error_print(error_file, 37, "Out of karma");
}
#include <stdio.h>
int main(){
for (int i=0; i < 10; i++){
printf("Hello #%i\n", i);
}
}
#include <stdio.h>
int main(){
for (int i=0; i < 10; i++) printf("Hello #%i\n", i);
}
#include <stdio.h>
int main(){
printf("Hello, world.\n");
}
#include <stdio.h>
int main(){
if (6 == 9)
printf("Six is nine.\n");
int x=3;
if (x==1)
printf("I found x; it is one.\n");
else if (x==2)
printf("x is definitely two.\n");
else
printf("x is neither one nor two.\n");
}
#include <stdio.h>
int intlist[10];
int main(){
int len=20;
char string[len];
intlist[7] = 7;
snprintf(string, len, "Item seven is %i.", intlist[7]);
printf("string says: <<%s>>\n", string);
}
CFLAGS=-g -Wall -std=gnu11 -O3
LDLIBS=-lm
#include <stdlib.h> //malloc and free
#include <stdio.h>
int main(){
int *intspace = malloc(3000*sizeof(int));
for (int i=0; i < 3000; i++)
intspace[i] = i;
FILE *cf = fopen("counter_file", "w");
for (int i=0; i < 3000; i++)
fprintf(cf, "%i\n", intspace[i]);
free(intspace);
fclose(cf);
}
#include <stdlib.h>
#include <stdio.h>
void double_in(int *in){
*in *= 2;
}
int main(){
int x[1];
*x= 10;
double_in(x);
printf("x now points to %i.\n", *x);
}
#include <stdio.h>
typedef struct {
int numerator, denominator;
double value;
} ratio_s;
ratio_s new_ratio(int num, int den){
return (ratio_s){.numerator=num, .denominator=den, .value=num/(double)den};
}
void print_ratio(ratio_s r){
printf("%i/%i = %g\n", r.numerator, r.denominator, r.value);
}
ratio_s ratio_add(ratio_s left, ratio_s right){
return (ratio_s){
.numerator=left.numerator*right.denominator
+ right.numerator*left.denominator,
.denominator=left.denominator * right.denominator,
.value=left.value + right.value
};
}
int main(){
ratio_s twothirds= new_ratio(2, 3);
ratio_s aquarter= new_ratio(1, 4);
print_ratio(twothirds);
print_ratio(aquarter);
print_ratio(ratio_add(twothirds, aquarter));
}
#include <stdio.h>
typedef struct {
int numerator, denominator;
double value;
} ratio_s;
int main(){
printf("size of two ints: %zu\n", 2*sizeof(int));
printf("size of two ints: %zu\n", sizeof(int[2]));
printf("size of a double: %zu\n", sizeof(double));
printf("size of a ratio_s struct: %zu\n", sizeof(ratio_s));
}
#include <math.h> //The square root function is declared here.
#include <stdio.h>
int main(){
double x = 49;
printf("The truncated square root of x is %g.\n",
x > 0 ? sqrt(x) : 0);
}
#include <stdio.h>
int main(){
double pi= 3.14159265; //POSIX defines the constant M_PI in math.h, by the way.
int count= 10;
printf("%g times %i = %g.\n", pi, count, pi*count);
}
#include <stdio.h>
int main(){
int i=0;
while (i < 10){
printf("Hello #%i\n", i);
i++;
}
}
......@@ -40,6 +40,7 @@ int main(int argc, char **argv){
char *ucs = localstring_to_utf8(string_from_file(argv[1]));
Stopif(!ucs, return 1, "Exiting.");
FILE *out = fopen("uout.html", "w");
Stopif(!out, return 1, "Couldn't open uout.html for writing.");
fprintf(out, "<head><meta http-equiv=\"Content-Type\" "
......@@ -48,6 +49,7 @@ int main(int argc, char **argv){
fprintf(out, "Its Unicode encoding required %zu bytes.<br>", strlen(ucs));
fprintf(out, "Here it is, with each space-delimited element on a line "
"(with commentary on the first character):<br>");
ok_array *spaced = ok_array_new(ucs, " \n");
for (int i=0; i< spaced->length; i++, (spaced->elements)++){
fprintf(out, "%s", *spaced->elements);
......
/* See compilation notes in openmp_wc.c or mapreduce_wc.c*/
#include "string_utilities.h"
int wc(char *docname){
char *doc = string_from_file(docname);
if (!doc) return 0;
char *delimiters = " `~!@#$%^&*()_-+={[]}|\\;:\",<>./?\n";
ok_array *words = ok_array_new(doc, delimiters);
if (!words) return 0;
double out= words->length;
ok_array_free(words);
return out;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册