ラベル C言語 の投稿を表示しています。 すべての投稿を表示
ラベル C言語 の投稿を表示しています。 すべての投稿を表示

2011年2月7日月曜日

さっきの続き

Twitterでたくさんの愛の鞭・・・
いや、ツッコミをいただきました。

えっと、そんなわけで修正したのですが、
ラストのコード、\0がコピーされてませんね。
for文にすればいいのだとおもうのですが、
すいません、目が限界のようなのでそろそろ寝ます。

また明日。
チャオ★

おい・・・。


えっとですね、ツッコミはすごくありがたいのです。
現実世界でもありがたいのですが、ネットもこんなにありがたいとは!!感動です!!
容赦なくお願いします。
あ、氏ねとかはやめてあげてね。なんていうか、こう・・・温かい目でおねがいします。

ありがとうございます!!

いただいたツッコミを返せるまでがんばります!!

2011年2月6日日曜日

C言語の文字列コピーが危険でござる。

前にもちろっと書いたと思いますが、C言語の勉強をしております。
C言語のむずかしいところっていうのは
概念が
「アドレス」
っていうところですね。
「アドレス」と「値(AとかBとかの値)」だと扱いが違うので
頭の中がこんがらがってたまに「うはー!!(汗)」ということがおこります。
うはー!!ってなによ?と思われそうですが、値をいれたいのにアドレス入れちゃったとか
アドレスに変な値をいれて変なアドレスになってしまう
つまり
メモリ破壊が発生します。

今のパソコン様はかしこいので壊れないですが、昔のものはちょっと危ないそうです。
昔といっても、相当昔なのであんまりこのへんは考えなくてもいいです。が!!
メモリに厳密にならないといけない世界では超重要な世界です。
これを理解しないと、いかんみたいです。C言語は。

というわけで、
身近なところからせめていくわけです。
文字列コピーが危険というお話しをします。でも知識がにわかです。
って言い訳をして逃げるあたりがかっこわるい。

C言語における文字列の扱いは難しいです。
文字型の配列を使用する もしくは 文字型のポインタを利用するしかないです。
(って考えると、JavaのString型って本当にありがたい)

問題なのが 配列 は 値
ポインタは アドレス

というわけで「概念」が違うのです。この違いって話すとむずかしいっつか、
私もよくわかってない箇所が多いので、
日本語と英語ぐらいにおもってください。
故に、これはダメな例です。

#include

void main() {
char work[5] = "ABC";

char *copy;

/* これ、大変 */
*copy = work;

printf("orignal:%s",work);
printf("copy:%s",copy);

};


コンパイルエラーで怒られます。なぜか?
アドレスに値を渡そうとしているので通じないのです。
英語の人にひたすら日本語で話しかけてる感じですかね。通じません。

だから、コピーの際には翻訳が必要になるのです。

配列にあわせてやるとか、ポインタにあわせてやるとか。
で、ここで登場するのがstrcpyという関数。

C言語は文字列コピーの際にstrcpyという関数を使います。
軽く書いたらこんな感じです。

#include
#include

void main() {
char *work;
work = "ABC";
char copy[50];

/* strcpy (char *s1,const char *s2)
/* *s1:複写先
/* *s2:複写元 */
strcpy(copy,work);

printf("original:%s\n",work);
printf("copy:%s\n",copy);

};


コメントでちょこっとかいてますが、これ、アドレスをコピーするんですよね。
が、このstrcpyとやらはやっかいなことに
「コピー先のこと、考えてません」

ためしにさっきのコードをこうしてみましょう。


#include
#include

void main() {
char *work;
work = "copy de copy";
char copy[10];

/* strcpy (char *s1,const char *s2)
/* *s1:複写元
/* *s2:複写先 */
strcpy(copy,work);

printf("original:%s\n",work);
printf("copy:%s\n",copy);

};


コンパイルは通りますが、実行したら即終了します。
コピー元のほうが、コピー先より大きいからです。サイズが。
strcpy関数はこれを考えてないので死にます。

そういう時の回避としてstrncpyを使用します。

strncpy(copy,work,10);

最後に「サイズ」を指定するので死ぬことは防げます。
かしこいことに、大きくても、文字列の終わりである「\0」は絶対確保してくれるので元が長くても少なくとも落ちることはありません。
が、変な文字にはなります。サイズはあたまにいれておきましょう。

「って、おめー!!文字数がきまったぶんだけってのはむずかしいべや!!」(何弁?)

ってもあるかとおもいます。
そういう時は、strcpyを自作すればいいだけです。ちょっとめんどいですけど。
要するにコピーなんで、
配列を1文字ずつみてやって、アドレスに渡してやればいいだけですね。
で、終了文字がやってきたら、終了すればいいのです。
コードにするとこう。

文字型同士(値同士)

#include

void main(){
char work[50] = "ABC";
char copy[50];
int i;

for(i = 0;work[i] != '\0'; i++) {
copy[i] = work[i];
};

printf("orignal:%s\n",work);
printf("copy:%s\n",copy);

};


ポインタと値でやってみた。

#include

void main() {
char *work;
work = "ABC";
char copy[10];
int i;
int j;

for(i = 0;work[i] != '\0';i++) {
copy[i] = work[i];
};

printf("orignal:%s\n",work);

/* \0までコピーしているので、直前の長さまで表示 */
printf("copy:");
j = 0;
while(j < i) {
printf("%c",copy[j]);
j++;
};
printf("\n");


};


上記2つは厳密には間違いですね。
だって、strcpy関数はポインタとポインタを渡すので
(アドレスをわたすってことね)
というわけで正しく書くと・・・


#include
#include
#include

void main(){
char *work;
char *copy;
int i;

work = "ABCDEFGHIJK";
copy = malloc (strlen(work) +1);

i = 0;

while(work[i] != '\0') {
*(copy+i) = *(work +i);
i++;

};
printf("orignal:%s\n",work);
printf("copy:%s\n",copy);

free(copy);

};


となります。
じつはこれ、もうちょっと簡単にかけるってことを
コード書いた後に調べて愕然としました(涙)
苦労したのに。
mallocとか
値とアドレスの渡しにはつまづかなくて、ずっとおちてたのは
iの初期化を忘れてたという
超凡ミス・・・。
だって、サクラエディタでやってるしなぁ・・・。

さて、

スペシャル簡易コード、
そのあたりは
このページの下のあたりにのってます。ご参考にどうぞ。


あー、それにしてもこういう時間は楽しい。本当はsplit関数自作したかったぜ。


追記
最初のコードと最後のコードにミスがあってツイッターでフルボッコにあったでござる。
文字列ってこわいわーね。

最初の copy = work はただしいので通ります。
*copy = work がとおりません。

orignalのスペルちがいました。originalですね。英語だめっす!!

えーと、最後のコード、mallocしているので
最後にfreeが必要です。

みなさんありがとう。


まだまだつっこみがきた。
sizeof って()つけたらだめなんですね。
そしてsizeofでなくて、文字数とるならstrlenなんですね。
あう、string.h使わないとだめなんか。あうあうあ。

ご参考 → http://www.ne.jp/asahi/hishidama/home/tech/c/sizeof.html

あと、最初のところ、アドレスに値を渡してどーん!!ですね。


ツッコミ歓迎ですー。勉強になるので!!
@morihimeまでどうぞ。

・・・でも「初心者しね」とか言わないでね(けっこう凹むんで)

2011年1月19日水曜日

QtのAPI一覧

解説とかは
まぁ、時間がとれたときにするんだけど・・・
(さっき作ったプログラムを上司にみせたら「どっかにまとめなさい」って言われたので
ちまちまこのブログでやろうと思います。気が向いたら)

とりあえず
QtのAPI一覧はここ。

Qt 4.7 API 一覧

本家のページなので
英語です。
日本語版探すのがめんどくさかったのでとりあえずここを参照してます。

バージョンによっていろいろあるらしいです。トップで探してください。今のところ4.7が最新なのかな。


そんな感じで。

眠い。ねるー!!

QtのlabelでHelloWorld

そいえば、さっきのQtのインストールのときに
win32api.hがないやんけ!!ってエラーでたんですけど、
あれはバージョンがちがうので怒られたっぽいのでとりあえず無視。

で、さっそくQtでGUIプログラミングです。
お決まりのHello Worldをさっそく。



#include
#include

int main(int argc, char ** argv)
{
QApplication app(argc, argv);
QLabel* label = new QLabel("Hello World");
label -> show();


return app.exec();
}



ビルドして実行するとラベルが表示されます。
では、さくさくとつくっていきまする。

2011年1月18日火曜日

GUIでいけそうな感じのC言語開発環境の用意。

C言語はがりがりプログラムを書いてもごもごするタイプなのですが、
今のご時勢、コンソールの対話型プログラムもどうかとおもうので、

GUIツールキットを探しました。C/C++で使えそう かつ eclipseでいけそうなの。

そしたら
Qt(キュートと読む)に出会いました。

Qt本家(英語だよ!!)

まずは
フレームワークのみをおとして
eclipseに導入したい人はこちら も。

windowsバージョンを落としてきて
さくっとインストール。

Qt本体はDLに時間がかかるのですね(我が家の回線が遅いだけですが)。
のんびりお茶のみながらまつこと数十分。
で、インストール。

eclipseのadd-Inのインストールは
eclipseとMinGWの場所を聞かれるのでさくっとこたえる。

さくっとがポイント。
インストールが終わって・・・あ、eclipseは再起動したほうがよいでしょうね。
これでいいかな?とおもったら、めんどくさいことに設定が必要。

window -> preference -> Qt -> Add

Qtの名前は適当に。(まぁ、正確なのがいいのかな?)
name -> Qt4.7.1
Bin path -> C:\qt\4.7.1\bin
include path -> C:\qt\4.7.1\include

ちなみにbinをちゃんと設定したらincludeは自動ではいります。

さて、これでようやく・・・とGUIでさくさくつくったるけ!とおもったら
consoleでやりなされというお達し。うむ。


参考サイト:Qt + Eclipse CDT で構築する Windows GUI アプリ開発

eclipseでC言語の環境をつくる。 その3

MinGWのダウンロードとインストールが終わって、お湯もわけてお茶も飲んだので
続いては

環境変数にPATHを通します。

C:\MinGW\bin;

↑各自の環境にあわせてください。

コマンドプロンプトを立ち上げて、gccを入力。
gcc: no input files
と出たらちゃんとできてるとのこと。(まぁ、なにもないので・・・)

これでいいかな?とおもったら、eclipseにはさらに設定がいるらしいです。たぶんきっと。

window -> Preferences -> C/C++ -> New CDT project wizard -> MakefileProject

New Make Projects -> Binary Parser -> PE Window Parser にチェックを入れる。


準備ができたので早速。
file -> new -> C Project で新規プロジェクトの作成。

適当にHelloWorld_2で、empty project と MinGW GCC を選択。
ちなみに「_2」なのはさっきMinGWを落とす前につくっちゃったから、適当にナンバリング。
若気の至りはのこしておくのだ!!(笑)

で、作成をすると、Includesにはたくさんの.hファイルがならんでおります。
大丈夫そうですね。

では、お決まりのHelloWorldを。
・・・の前に、邪魔なのでeclipseの自動ビルド機能をオフに。
project -> Build Automatically のチェックをはずす。

そして、ファイルがごったごたになりそうなのでsourceフォルダを作成。
その下にsourceファイルを作成しました。

ありがちですが、「main.c」です。(拡張子も指定しないといかんらしい)

では、コード。

#include

int main(void) {
printf("hello world!!");
return 0;
}


ありがちな初心者コードです。コピペせずに写経して下さい(笑)
あとは、プロジェクトを右クリックして、build project を選択すると
いろいろできます・・・。

またプロジェクトの右クリックで、Run As を選択
local C/C++ Application を選んでコンソールを確認。

hello world!!

というわけで、基本形は完了です。




参考サイト:eclipse+CDTをセットアップしてみよう

eclipseでC言語の環境をつくる。 その2

プラグインをインストールして(長い)、
プロジェクトをつくってみたら、Includesのところになにもない。
というわけでHelloWorldすらつくれない。

・・・む?

たりないものを考える。

CDTの機能は
・リソース管理
・エディタ機能
・ビルド
・デバック
・ほか、ユーティリティー

さて、C言語はエディタ→コンパイル→リンクという流れで作成するらしいのだが
まだ、エディタしか用意してないじゃないか!!

ということで
コンパイルする道具・・・コンパイラを用意。
windowsでも動作するフリーのコンパイラということで、MinGWを用意。

MinGWのDLページ をよくみたら、Looking for the latest version?のところに最新インストーラーつきがあったのでそれを光の速さでDL。
警告でるけど、気にせず実行。

画面に従ってインストール。とりあえずオプション全部。
ダウンロードを勝手にしてくれるので、待つのみ。その間にお湯をわかしてきます。(寒い)


参考サイト:初心者のためのポイント学習C言語
MinGW
MinGW(wikipedia)

eclipseでC言語の開発環境を用意する。

お姉さん、あんたAndroidとかJavaとかそういうの勉強するんじゃなかったっけ?
と思われそうですが・・・

仕事でもなんでもなく、
諸般の都合でC言語をやることになりました。
で、復讐・・・ではなく、復習のためにblogに書きます。

さて、C言語でプログラムを組むわけですが、なにはなくとも開発環境です。
フリーのソフトから普段使いなれている
eclipseを選んでみました。
普段はjavaなので、workspaceはC言語のために用意しました。
C直下に適当な名前。

で、プラグイン(CDT)をインストールでございます。
私が使っているのは、eclipse3.5 classic です。

最初から入っているものではないとのことなのでさくりとインストール。

help -> Install New Software
開くとなんかサイトのURLを要求されるのでCDTのサイトを。

http://download.eclipse.org/tools/cdt/releases/galileo/

これをいれる。(3.5なのでこれですよ)
あとは適当にチェックを入れてインストールです。

もちろん、エクリプスサイトからzipを落としてきていれてもいいんですけど、
めんどくさいので・・・。

で、待っている間に洗濯ものが干せました。
いったんここまで。

参考サイト:エクリプス