Category: C 程序设计

我的第一个Windows窗体程序

By 深空, 2009年10月20日 22:20

  虽然之前也用JAVA编写过窗体程序,但毕竟不是原装的,这次采用C来写Windows窗体,发现比JAVA简单一些,HOHO

#include <windows.h>
#include <windowsx.h>

int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd) {
    MessageBox(NULL, "Hello world!", "你好世界!", MB_OK | MB_ICONASTERISK);
    return 0;
}

  采用Visual Studio 2008,创建的空项目,直接编译竟然就可以了。

我的第一个Windows窗体程序

我的第一个Windows窗体程序

VN:F [1.9.3_1094]
Rating: 7.1/10 (10 votes cast)
VN:F [1.9.3_1094]
Rating: +4 (from 10 votes)

Fork子进程

By 深空, 2009年09月04日 00:11

  这两天下载了无数版本Linux,包括openSuse 11.1,Ubuntu 9.04,Suse Enterprise Desktop 11等,在虚拟机上装了下,感觉还是不错的。

SUSE Linux Desktop 11

SUSE Linux Desktop 11


  当然装这个主要是要在上面学学C开发啦,顺便读读《UNIX环境高级编程(第二版)》,不错的书,不过理解起来有难度。第一章就讲fork子进程了,当然对于我这种菜鸟,看起来是晕头转向,恰好小寒同学从中给予指点,让我略微明白了一下下,于是乎有了下面的程序:

#include <stdio.h>
#include <stdlib.h>
main() {
    int i = 0;
    while (i < 1000) {
        pid_t pid_i = fork();
        if (pid_i == 0) {
            printf("child:%d\n", i);
            //exit(0);
        } else {
            i++;
        }
    }
}

  厄,编译执行后后果自负哈。要想正常就把exit的注释去掉啦,否则是个死循环(10002n, n->+∞)。

  然后我来根据我的回忆理解一下这段代码。pid_t 是pid(进程id)的类型,其实感觉就是个int,没看源代码不清楚是不是,哈哈。第六行开始调用fork()函数产生一个子进程,这个产生过程是在父进程执行的,所以这个fork在这个时候只执行了一次,不过执行后就产生父子两个进程,所以其实pid是被赋了两次,你可以在fork()调用之后把后面的代码看成一个分身术,分成两套独立代码,其中父进程给pid_i赋值,得到子进程id,而子进程也做赋值操作,只不过得到的是0,注意进程id是一个非负值,如果为负则表示出错误了。接下去父子该干嘛干嘛,还是按照往下的程序执行了,在fork完成的当口,所有状态拆成两份。fork完成后,各干各的!fork单词的含义体现得淋漓尽致(见注解)。
  嗯,没错,这就是我对进程的理解,雷不?
  注:

简明英汉词典
fork
D.J.[fɔ:k]
K.K.[fɔrk]
n.
1 餐叉
2 耙子, 叉
3 (道路或河流的)分岔处
vi.
分叉
vt.
1 走岔路
2 叉; 耙
VN:F [1.9.3_1094]
Rating: 7.1/10 (10 votes cast)
VN:F [1.9.3_1094]
Rating: +1 (from 11 votes)

计算N以内质数的个数

By 深空, 2009年08月29日 23:53

总结两点:
  1、注意内存分配中int是占4个字节,不能分配多少个int就直接写多少个,而要乘以int的长度大小,因为它(malloc)分配的是字节数;
  2、能省则省,一开始我把isNotPrime声明为int,这样到99999999内存就太大了分配不了,后来改成char,至少节约3/4内存,可以测试更大的数;
完整代码如下,算法是网上看别人的算法:

/**
 * 计算2~N的质数
 * skchen @ 2009-08-29 22:26
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 999999999

main() {
    int i = 0;
    int *numbers;
    char *isNotPrime;
    int j = 0;
    int count = 0;
    numbers = malloc(N / 2);
    isNotPrime = malloc(N * sizeof(char));
    for (i = 0; i < N; i++) {
        isNotPrime[i] = 0;
        if (i < (N / 8)) {
            numbers[i] = 0;
        }
    }

    for (i = 2; i < N; ++i) {
        if (isNotPrime[i] == 0) {
            numbers[count] = i;
            //printf("%d,", i);
            count++;
            for (j = i + i; j < N; j += i) {
                isNotPrime[j] = 1;
            }
        }
    }
    printf("总共%d个质数\n", count);
    printf("CPU运行时间:%d", clock());
    free(numbers);
    free(isNotPrime);
}

稍微修改了下算法,在我的电脑上至少可以计算这么大的范围了:

/**
 * 计算2~N的质数
 * skchen @ 2009-08-30 04:58
 */

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

#define N 2999999999

main() {
    unsigned long int i = 0;
    //int *numbers;
    char *isNotPrime;
    unsigned long int j = 0;
    unsigned long int count = 0;
    //numbers = malloc(N / 8);
    isNotPrime = malloc(N * sizeof(char) / 2);
    for (i = 0; i < N / 2; i++) {
        isNotPrime[i] = 0;
        //if (i < (N / 32)) {
        //    numbers[i] = 0;
        //}
    }

    //numbers[0] = 2;
    count++;
    for (i = 3; i < N; i += 2) {
        if (isNotPrime[(i - 1) / 2] == 0) {
            //numbers[count] = i;
            //printf("%d,", i);
            count++;
            if (i < N / 2) {
                for (j = i + i; j < N && j < N - i; j += i) {
                    if (j % 2 == 0) {
                        continue;
                    }
                    isNotPrime[(j - 1) / 2] = 1;
                }
            }
        }
    }
    printf("总共%d个质数\n", count);
    printf("CPU运行时间:%d", clock());
    //free(numbers);
    free(isNotPrime);
}
VN:F [1.9.3_1094]
Rating: 8.8/10 (5 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 4 votes)

使用动态内存存放字符串

By 深空, 2009年08月28日 21:19

  调了半天才搞定,其中问题之一是把下标增量声明为int,导致溢出。(char为1字节,int为4字节)。还有可能调用malloc后产生的指针最好不要使用吧?反正书上是直接赋给另外一个指针变量。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
    char *str;
    char *str1;
    str = malloc(100 * sizeof(char));
    str1 = str;
    strcpy_s(str1, 100, "hello world!");
    printf("%s\n", str1);
    free(str);
}

  竟然还需要拷贝才能进去,不能直接等于,厄,没想到存个字符串这么麻烦呀,不知道有没有其他好的方法。使用strcpy_s的话str指针并不会偏移:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
    char *str;
    str = malloc(100 * sizeof(char));
    strcpy_s(str, 100, "hello world!");
    printf("%s\n", str);
    free(str);
}

  其实也可以使用下标给字符串赋值,或者使用+号进行偏移:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
    char *str;
    char *str1 = "hello world!";
    int i;
    str = malloc(100 * sizeof(char));
    for (i = 0; str1[i] != '\0'; i++) {
        str[i] = str1[i];
    }
    str[i] = '\0';
    printf("%s\n", str);
    free(str);
}

  或者:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
    char *str;
    char *str1 = "hello world!";
    int i;
    str = malloc(100 * sizeof(char));
    for (i = 0; str1[i] != '\0'; i++) {
        *(str + i) = str1[i];
    }
    *(str + i) = '\0';
    printf("%s\n", str);
    free(str);
}

  另外一个动态分配内存的例子,写了半个小时:

/**
 * 获取用户输入的字符串,打印行号
 * skchen @ 2009.08.29 03:03
 */
#include <stdio.h>
#include <stdlib.h>

#define MEM_SIZE 100

void main() {
    //行号
    int line_num = 1;
    //行字符数
    int char_num = 1;
    //行指针
    char *line = NULL;
    //用户输入的字符
    char c;
    //已分配内存大小
    int total_mem_size = 0;
   
    while ((c = getchar()) != EOF && c != '\n') {
        do {
            //看看内存空间是否足够用,要留一位给\0
            if (total_mem_size < char_num) {
                //分配扩大内存空间
                line = realloc(line, total_mem_size + MEM_SIZE);
                if (line == NULL) {
                    printf("动态内存分配错误!程序退出!\n");
                    exit(EXIT_FAILURE);
                }
                //如果分配成功,内存总分配大小加上去
                total_mem_size += MEM_SIZE;
            }
            //把字符给数组
            line[char_num - 1] = c;
            char_num++;
            //继续获取字符
            c = getchar();
            //判断是否回车,如果不是则未结束,继续循环
        } while (c != '\n');
        //添加字符串结束符
        line[char_num - 1] = '\0';
        //打印结果
        printf("line: %d, length: %d, size: %d, string: %s\n", line_num, char_num, total_mem_size, line);
        //释放内存
        free(line);
        //指针重新置为NULL
        line = NULL;
        //内存大小置为0
        total_mem_size = 0;
        //字符长度初始化为1
        char_num = 1;
        //行号+1
        line_num++;
    }
    exit(EXIT_SUCCESS);
}
VN:F [1.9.3_1094]
Rating: 8.8/10 (5 votes cast)
VN:F [1.9.3_1094]
Rating: +1 (from 5 votes)

简单的MySQL查询

By 深空, 2009年08月26日 17:50

  今天尝试在SUSE上写连接MySQL的代码,赫赫,很初级,不要笑我,调试了好久才成功。

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

#define DB_HOST "localhost"
#define DB_NAME "test"
#define DB_USER "root"
#define DB_PASS ""

main() {
    MYSQL *conn;
    MYSQL_RES *result;
    MYSQL_ROW row;

    if (mysql_init(conn) == NULL) {
        printf("init error");
    }
    if (mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, MYSQL_PORT, NULL, 0) == NULL) {
        printf("connect error");
    }
    if (mysql_query(conn, "SELECT * FROM test LIMIT 10") != 0) {
        printf("query error");
    }
    result = mysql_store_result(conn);
    printf("rows:%d\n", mysql_num_rows(result));
    while (row = mysql_fetch_row(result)) {
        printf("ip name is : %s\n", row[0]);
    }
    mysql_close(conn);
}

  编译选项需要把libmysqlclient.o包进来,还有MySQL的include目录。

gcc -o query query.c -I /usr/local/services/mysql-5.0.26-client/include/mysql -L /usr/local/services/mysql-5.0.26-client/lib/mysql -lmysqlclient

  在Windows上用Visual Studio也需要设置include目录,还有要把libmysql.lib包进来。

VN:F [1.9.3_1094]
Rating: 8.3/10 (3 votes cast)
VN:F [1.9.3_1094]
Rating: +1 (from 3 votes)

京ICP备05002071号 ©2003-2010 深空