ファイルIOで1行ずつの処理は
2005-05-25-1 / カテゴリ: [programming][c] / [permlink]

fgets を使って、\nまで読んだのか、\0まで読んだのか、そうでないのかをチェック
  input_buf = (char *)malloc(sizeof(char) * cur_mem_size);
  if (input_buf == NULL) {
    perror("memory alocate error(input_buf)\n");
    exit(1);
  }

  // EOF まで読み込み
  while (!feof(fp)) {
    if (fgets(read_buf, INPUT_BUFFER, fp)) {
      strcat(input_buf, read_buf);

      if (!feof(fp) && input_buf[strlen(input_buf) - 1] != '\n') {
        // EOFでなく かつ 行の途中までしか読めなかった
        cur_mem_size += INPUT_BUFFER;
        printf("%d\n", cur_mem_size);
        input_buf = (char *)realloc(input_buf, sizeof(char) * cur_mem_size);
        if (input_buf == NULL) {
          perror("realloc error\n");
          exit(1);
        }
      }
      else {
        // EOFまたは行末まで読んだ
        printf("[%s]", input_buf);  // 行に対する処理
        input_buf[0] = '\0';
      }
    }
  }
cur_mem_size ずつファイルを読み込み、行末までよんでなかったら、バッファを realloc して更に読む、というやり方。こんなんで良いのだろうか。

独習C
2005-05-22-1 / カテゴリ: [c][programming][diary][] / [permlink]

日曜日だとゆーのに、深夜の電話番。電話がならなければただの夜更し(ぉぃ)。ぃゃ、別に起きてなくても良いんだけど、睡眠中に鳴るケータイに反応できる程、敏感ではないので、徹夜せざるを得ない身体がうらめしい。

ただ起きててもアホらしいので、独習CでC言語のお勉強。一気に200ページ程読んでしまった。
2年生子ちゃんが(押えるべきポイントを)見て分かりやすいように、(自分は理解できてる範囲も含めて)テストに出そうな項目(笑)にマーカーをどんどん引いて行く。

switch-case って、Perl 使いだったせいか、イマイチ使いどころがわからん。

独習C 購入
2005-05-21-1 / カテゴリ: [c][programming][] / [permlink]

1年前位に買った「猫でも分かるCプログラミング」だと、ちょっと情報が足りなくなってきたので、初・中級用のつもりで購入。割と読みやすい。
「C言語 ポインタが理解できない理由」を一通り読んでたおかげかな?

2年生の子にはちょっと敷居が高いかもしんないけど、猫わかに載ってない範囲で勉強するには良いかな?

ちょうど、すぐわかるPerl + 独習Perl と同じ体制になったな(笑

条件コンパイルを行う
2005-04-26-1 / カテゴリ: [programming][c] / [permlink]

予めデバッグフラグを #define で定義し、#ifdef 〜 #endif でブロック(?)を囲む
#define DEBUG 1
:
:
#ifdef DEBUG
 // ここにコード
 // DEBUGが定義されていればコンパイルされる。
#endif
:
:

malloc, realloc 基本
2005-04-23-1 / カテゴリ: [c][programming] / [permlink]

メモリを確保する
malloc
「プログラムが」使用出来るメモリ領域を確保する。
#include <stdio.h>
#include <stdlib.h>

int main() {
  char *str;
  char *str2 = "hogefoobar";

  str = (char *)malloc(strlen(str2) + 1);  /* str2の文字列長+1('\0'用)を確保し
                                              str にそのアドレスを保持 */
  if (str == NULL) {                       /* malloc の例外処理 */
    perror("cannot malloc\n");
    return -1;
  }

  strcpy(str, str2);                       /* 文字列のコピー */
  printf("str: [%s] %p\n", str, str);
  printf("str2: [%s] %p\n", str2, str2);

  free(str);                               /* メモリの開放 */

  return 0;
}
malloc 前にどこかのアドレスをさしていた場合は、その内容はなくなる…のかな

realloc
プログラムが使用出来る既存のメモリ領域を拡大する。既存のメモリ領域から連続した領域が空いていればそこが、空いていなければ、別の位置に領域確保&既存の位置のデータのコピーが行われる。多分
#include <stdio.h>
#include <stdlib.h>

int main() {
  char *str;
  char *str2 = "foobar";

  str = (char *)malloc(strlen(str2) + 1);  /* まずは str に領域確保 */
  if (str == NULL) {
    perror("cannot malloc\n");
    return -1;
  }
  strcpy(str, str2);
  printf("str: [%s] %p (size: %d)\n", str, str, strlen(str));

  str = (char *)realloc(str, strlen(str) + strlen(str2) + 1);
                                           /* str に更に str2 分を追加 */
  if (str == NULL) {
    perror("cannot realloc\n");
    return -1;
  }

  strcat(str, str2);                       /* str = str + str2 */
  printf("str: [%s] %p (size: %d)\n", str, str, strlen(str));

  free(str);

  return 0;
}
↑ realloc しないとコアダンプした(cygwin/gcc)

文字列を指定文字(デリミタ)で区切って、部分文字列のアドレスを得る
2005-04-22-1 / カテゴリ: [programming][c] / [permlink]

strtok(string, charset)
#include <string.h>

char string[] = "name, title, date, value\n";
char delim[] = ", \r\n";
char *token;

printf("[%s] (%p)\n", string, string);
printf("----\n");
token = strtok(string, delim);
while (token != NULL) {
  printf("[%s] (%p)\n", token, token);
  token = strtok(NULL, delim);
}
出力は
[name, title, date, value
] (0x22efa0)
----
[name] (0x22efa0)
[title] (0x22efa6)
[date] (0x22efad)
[value] (0x22efb3)
コールするたびに、デリミタで指定した文字セット以外が連続する文字列の末尾に '\0' をいれ、先頭のポインタを返す。(よって string は壊れる)
コール時に前回のポインタを記憶しているので、NULL になるまで複数回実行すれば、対象文字列をバラせる。

便利だけど、そろそろ Perl でやりたくなってきた。

標準ライブラリのヘッダファイルはどこに?
2005-04-21-5 / カテゴリ: [programming][c] / [permlink]

/usr/include
です。

文字列中から文字を探し、長さを得る
2005-04-21-4 / カテゴリ: [programming][c] / [permlink]

strspn(string, charset) / strcspn(string, charset) で
#include <string.h>

char string[] = "abcdefg";
char target[] = "def";
size_t len1, len2;

len1 = strspn(string, target);
len2 = strcspn(string, target);
strspn は、string の先頭から target の文字のみの部分文字列の長さ。
strcspn は、string の先頭から target 以外の文字のみの部分文字列の長さ。

Perl だと
my $string = "abcdefg";
my $target = "def";
my ($len1, $len2);

$len1 = length join "", ($string =~ /^([$target]*)/);
$len2 = length join "", ($string =~ /^([^$target]*)/);
ってコトかな? (うそっぽい)

文字列中から文字を探し、アドレスを得る
2005-04-21-3 / カテゴリ: [programming][c] / [permlink]

1文字探す場合は strchr(string, char), strrchr(string, char) で
#include <string.h>

char string[] = "abcdefg";
char target = 'c';
char *p;

p = strchr(string, target);
p には、string 中の最初の c の位置のアドレスが入る
strrchr は、最後のアドレスが入る(末尾から探す)
文字が見つからなかった場合は null になる。

複数文字のうちの1文字を探す(targetに複数文字を指定)場合は
char *strpbrk(string, charset)
char string[] = "sample string";
char target[] = "aiueo";
char *p;

p = strpbrk(string, target);
p には "sample string" の先頭から、"aiueo" の中のどれか1文字が最初に見つかる、2文字目の "a" の位置のアドレスが入る。
見つからなければ null

文字列長の取得
2005-04-21-2 / カテゴリ: [programming][c] / [permlink]

strlen(string) を使う
#include <stdio.h>
size_t strlen(const char *str);
文字列を指すポインタを渡すと、文字数(size_t型)を返す

const で定数宣言
2005-04-21-1 / カテゴリ: [programming][c] / [permlink]

変数を const で修飾すると、read-only な変数になる。
const int i = 123;
i = 456;
コンパイルすると
strlen.c: In function `main':
strlen.c:10: error: assignment of read-only variable `i'

Perl なら
use constant VALUE => 123;
だ。

厳密には「定数」というわけでなく、「読み出し専用」にするってこと。

文字列をフォーマット通りに分割する
2005-04-20-1 / カテゴリ: [programming][c] / [permlink]

sscanf(string, format, ...) を使う
#include <stdio.h>
int sscanf(const char *s, const char *format, ...);
           入力文字列     入力書式文字列      格納可変個引数
コード
char buf[] = "5/4/20";
int yy, mm, dd;

sscanf(buf, "%2d/%2d/%2d", &yy, &mm, &dd);
で、yy に 5, mm に 4, dd に 20 が入る
Referrer (Inside): [2006-03-13-3]

C言語 文字列の宣言・代入
2005-04-19-5 / カテゴリ: [programming][c] / [permlink]

(charへのポインタで)
char *str;
str = "hoge";
このとき、strcpy(str, "hoge"); はできない。
ポインタが指しているアドレスが不定の場合に文字列をセットできないから…かな

(charの配列で)
char str[32];
strcpy(str, "hoge");
このとき、str = "hoge"; はできない。
str は配列名であって変数でないから…らしい
ただし、
char str[32] = "hoge";
は OK

C言語 配列とポインタの関係
2005-04-19-4 / カテゴリ: [programming][c] / [permlink]

int a[4] = {1, 2, 3, 4};
for (i = 0; i < 4; i++) {
	printf("&a[%d]: %p\n", i, &a[i]);   /* 各要素のアドレスを print */
}
printf("a: %p\n", a);                 /* 配列名をポインタとして print */
出力
&a[0]: 0x22efb0
&a[1]: 0x22efb4
&a[2]: 0x22efb8
&a[3]: 0x22efbc
a: 0x22efb0p
配列名は、その配列の先頭要素のアドレスを指している
カテゴリ: c / 前ページ 1 2 3

最終更新時間: 2013-05-02 16:12