Archive

Archive for the ‘C/C++’ Category

TwSMS 發簡訊 (Linux C 版)

一月 21st, 2008

台灣簡訊(TwSMS)是國內一家線上傳簡訊的服務商,提供文字簡訊、語音簡訊等服務,價格也很合理,最重要的是有提供 API 介面,方便用戶在自己的程式中加入發送簡訊功能,官網已經有提供不少範例(PHP/ASP/JSP/Java/Perl/VB/BCB/Delphi),這邊也有 Ruby 的版本,不過就是沒看到 C 的,所以大略寫了一個 Linux C 版本,打算加入自己的嵌入式專題使用。

TwSMS 提供的 API 很簡單,只要由 HTTP 對 API server 發送 Request 即可,接著 server 就會回傳結果。程式先建立一個 socket 連線,然後發送簡訊,最後再擷取回傳碼檢查是否成功。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main()
{
	/* TWSMS 相關設定 */
	char *username = "username";   // 帳號
	char *password = "password"; // 密碼
	char *type = "now";         // 發送型態
	char *mobile = "0912xxxxxx"; // 電話
	char *message = "簡訊測試"; // 簡訊內容
	char *encoding = "big5";    // 簡訊內容編碼
	char *popup = "";          // 使用 POPUP 顯示
	char *mo = "";             // 使用雙向簡訊
	char *vldtime = "86400";    // 簡訊有效期限(秒)
	char *dlvtime = "";         // 預約時間

	int sockfd;
	int len = 0;
	char *host = "api.twsms.com";
	char msg[512], MSGData[512], buf[512];
	char *res, *checkRes;
	struct sockaddr_in address;
	struct hostent *hostinfo;

	bzero(&address, sizeof(address));
	hostinfo = gethostbyname(host);
	if (!hostinfo) {
		fprintf(stderr, "no host: %s\n", host);
		exit(1);
	}
	address.sin_family = AF_INET;
	address.sin_port = htons(80);
	address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;

	/* Create socket */
	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	/* Connect to server */
	if (connect(sockfd, (struct sockaddr *)&address, sizeof(address)) == -1) {
		perror("connect faild!\n");
		exit(1);
	}

	/* Request string */
	len = snprintf(msg, 512,
				  "username=%s&password=%s&type=%s&encoding=%s&popup=%s&mo=%s&mobile=%s"
				  "&message=%s&vldtime=%s&dlvtime=%s", username, password, type, encoding,
				  popup, mo, mobile, message, vldtime, dlvtime);

	/* HTTP request content */
	snprintf(MSGData, 512,
			"POST /send_sms.php HTTP/1.1\r\n"
			"Host: %s\r\n"
			"Content-Length: %d\r\n"
			"Content-Type: application/x-www-form-urlencoded\r\n"
			"Connection: Close\r\n\r\n"
			"%s\r\n", host, len, msg);

	/* Send message */
	send(sockfd, MSGData, strlen(MSGData), 0);

	/* Response message */
	recv(sockfd, buf, 512, 0);

	for (res = strtok(buf, "\n"); strncmp(res, "resp", 4) != 0; res = strtok(NULL, "\n"));
	checkRes = strtok(res, "=");
	checkRes = strtok(NULL, "=");

	if (atoi(checkRes) <= 0) {
		printf("傳送失敗\n");
	} else {
		printf("傳送完成\n");
	}

	close(sockfd);
	return 0;
}

C/C++, 程式筆記 , , ,

C 語言中 printf 的問題(續)

九月 30th, 2007

前一篇當中提到了 printf 結果異常的問題,在睡前翻了一下手邊借來的「C Primer Plus」,沒想到就有提到這個問題,印象中其他書籍似乎都沒有講到,C Primer 系列果然是好書!

簡單來說就是 C 語言中,compiler 可以選擇先計算函數中的哪個參數,以增加編譯程式的效率,所以前一篇的例子:


printf("%d, %d", age, age++);

compiler 很可能會先算第二個參數,先改變了 num 數值,這樣就造成結果不如預期了。

在「C Primer Plus 5/e 中文精華版」第五章有寫道,遵循以下原則可以避免這些問題:

  1. 請勿在函數當中,對使用不止一次的參數使用遞增或遞減運算子。
  2. 請勿在運算式當中,對使用不止一次的變數使用遞增或遞減運算子。

第一點就是上面所說的例子,第二點的例子如下:


n = 3;
y = n++ + n++;

在 C 標準中並沒有定義這行程式會如何執行,是哪一個先加 1 再運算,還是都先不加,造成了含糊不清的結果,應當避免這種寫法。

C/C++, 程式筆記 ,

C 語言中 printf 的問題

九月 30th, 2007

今天有個學妹問我一個 C 程式的問題:下面程式的結果為何?


#include <stdio.h>
int main(void)
{
    int age = 20;
    printf("You are now %d, and will be %d in one year", age, age++);
    return 0 ;
}

自認觀念還不錯的我直接就回答「20, 20」。但沒想到實際跑的答案竟然是「21, 20」,這真是出乎意料的結果啊!

馬上另外測試了其他有 printf 函式的語言,如 Java、PHP,結果也都是正確的「20, 20」,所以不知道是 C printf 的 bug 還是什麼原因,希望有人能解答。

請看:C 語言中 printf 的問題(續)

C/C++, 程式筆記 , ,

OpenGL-海龜作圖法

一月 16th, 2007

海龜作圖法(Turtle Graphics),意思是模仿海龜移動的方式,只能前進及左右轉,而將海龜的尾巴當作畫筆,可以放下及抬起。
本範例為二維空間,使用 OpenGL 搭配 C++ 實做。

程式功能介紹:
1、由 turtle.txt 檔案讀入作圖指令。
2、INIT - 設定海龜初始位置。(x 軸, y 軸, 龜頭角度)
3、PEN - 設定尾巴狀態。(0 抬起 / 1放下)
4、FW - 海龜向前移動。(移動長度)
5、RIGHT - 海龜右轉角度。(角度)
6、LEFT - 海龜左轉角度。(角度)


#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <GL/glut.h>
using namespace std;

const GLfloat PI = 3.141593;

class Turtle {
private:
    bool penStatus, a;
    GLfloat x1, y1, x2, y2; //座標
    GLfloat cAngle; //角度
public:
    Turtle() //constractor
    {
        penStatus = 0;
        x1 = y1 = x2 = y2 = 0.0;
        cAngle = 0.0;
        a = 0;
    }

    /* 設定海龜位置 */
    void InitPoint(GLfloat x, GLfloat y, GLfloat angle)
    {
        x1 = x; y1 = y; cAngle = angle; a = 1;
        if (penStatus) //如果 pen down 應該畫出一點
        {
            glBegin(GL_POINTS);
                glVertex2f(x, y);
            glEnd();
        }
    }
    /* 海龜向前移動 */
    void forward(GLfloat L)
    {
        x2 = x1 + L * cos(cAngle*PI/180);
        y2 = y1 + L * sin(cAngle*PI/180);

        if (penStatus)
        {
            glBegin(GL_LINES);
                glVertex2f(x1, y1);
                glVertex2f(x2, y2);
            glEnd();
        }

        x1 = x2; y1 = y2;
    }
    /* 海龜右轉角度 */
    void right(GLfloat angle)
    {
        cAngle = (a) ? cAngle - angle : angle;
        a = 1;
    }
    /* 海龜左轉角度 */
    void left(GLfloat angle)
    {
        cAngle = (a) ? cAngle + angle : angle;
        a = 1;
    }
    /* 設定畫筆狀態(0 up/1 down) */
    void setPen(bool value)
    {
        penStatus = value;
		if (value) //pen down 畫出一點
		{
			glBegin(GL_POINTS);
				glVertex2f(x1, y1);
			glEnd();
		}
    }

};

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */

    char cmd[10];
    float x, y, angle;
    bool p;
    ifstream fp("turtle.txt");
    Turtle t;

    while (!fp.eof())
    {
        fp >> cmd;
        if (!strcmp(cmd, "INIT")) {
            fp >> x >> y >> angle;
            t.InitPoint(x, y, angle);
        } else if (!strcmp(cmd, "FW")) {
            fp >> x;
            t.forward(x);
        } else if (!strcmp(cmd, "RIGHT")) {
            fp >> x;
            t.right(x);
        } else if (!strcmp(cmd, "LEFT")) {
            fp >> x;
            t.left(x);
        } else if (!strcmp(cmd, "PEN")) {
            fp >> p;
            t.setPen(p);
        }
    }

    glFlush(); /* clear buffers */
}

int main(int argc, char** argv)
{

/* Standard GLUT initialization */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); /* default, not needed */
    glutInitWindowSize(500, 500); /* 500 x 500 pixel window */
    glutInitWindowPosition(0, 0); /* place window top left on display */
    glutCreateWindow("Turtle Graphics"); /* window title */
    glutDisplayFunc(display); /* display callback invoked when window opened */

/* attributes */
    glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
    glColor3f(1.0, 0.0, 0.0); /* draw in red */
/* set up viewing */
/* 500 x 500 window with origin lower left */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 500.0, 0.0, 500.0);
    glMatrixMode(GL_MODELVIEW);

    glutMainLoop(); /* enter event loop */

    return 0;
}

turtle.txt

C/C++, 程式筆記 ,

[OOP] - 第一章作業­

三月 17th, 2006

功能說明:

輸入長及寬 => 10 7
輸入邊框及填充字元 => C +
執行結果:
CCCCCCCCCC
C++++++++C
C++++++++C
C++++++++C
C++++++++C
C++++++++C
CCCCCCCCCC

程式實作:


#include <iostream>
#include <iomanip>
using namespace std; 

int main()
{
    int width, height;
    char border, inner; 

    cout << "Enter Width and Height => ";
    cin >> width >> height;
    cout << "Enter Border and Inner character => ";
    cin >> border >> inner;
    for (int i=1; i<=height; i++)
    {
        if (i==1 || i==height)
            cout << setw(width) << setfill(border) << border << endl;
        else
            cout << border << setw(width-1) << setfill(inner) << border << endl;
    }
    system("PAUSE");
    return 0;
}

C/C++ ,