C言語関係掲示板

過去ログ

No825 文字列の分割(配列&ポインタ)

[戻る] [ホームページ]
No.10429

文字列の分割(配列&ポインタ)
投稿者---たま(2003/11/11 17:01:49)


はじめまして。いろいろと調べたのですが、分からないので
お願いします。

配列に文字列「This is not an apple」を代入し、これを単語ごとに
分割して、それぞれ新たに配列に代入する。
(This is not an appleの5つに分ける。)
この処理を、ポインタと配列をつかう2種類のプログラムをつくりたい
のですが、どうしたらいいのでしょうか。

宜しくお願いします。

No.10433

Re:文字列の分割(配列&ポインタ)
投稿者---なお(2003/11/11 18:12:02)


ポインタverはstrtokを使えば何とかなりそうです。

No.10434

Re:文字列の分割(配列&ポインタ)
投稿者---たま(2003/11/11 18:16:12)


アドバイスありがとうございます。
ですが、私はポインタがまだまだ入門者のため、
わかりません。具体的に数行で構いませんので、
例文を書いていただけませんでしょうか?
宜しくお願いします。

No.10442

Re:文字列の分割(配列&ポインタ)
投稿者---たか(2003/11/11 22:16:04)


割り込み失礼します。

配列版なんてのはしばらく書いた事がなかったのでゴチャゴチャしてい
ます。もしかしたらバグが残っているかも知れません。もっとスマート
に書きたいのですが・・・スペース文字の扱いを厳しくしていたらこんな
になってしまいました。逆にポインタ版の方はほとんどスペース文字の
チェックをしていませんので文字列の与え方によっては配列版と異なる
結果が出る場合があります。

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

#define N 20
#define LEN 30

int apart_by_array(char str[][LEN], const char *s);
int apart_by_pointer(char *strp[], const char *s);

int main(void)
{
  int n1, n2, i;
  char str[N][LEN], *strp[N], *s = "This is not an apple";

  /* 配列版 */
  n1 = apart_by_array(str, s);
  printf("配列版の分解\n");
  for (i = 0; i < n1; i++)
    printf("%3d: %s\n", i + 1, str[i]);
  
  /* ポインタ版 */
  n2 = apart_by_pointer(strp, s);
  printf("ポインタ版の分解\n");
  for (i = 0; i < n2; i++) {
    printf("%3d: %s\n", i + 1, strp[i]);
    free(strp[i]);
  }
  
  return 0;
}

/* 配列版の分解 */
int apart_by_array(char str[][LEN], const char *s)
{
  int n, i, j;
  
  if (strlen(s) == 0) return 0;
  for (i = 0, n = 0; s[i]; i++)
    if (s[i] != ' ') n++;
  if (n == 0) return 0;
  
  for (i = 0; s[i] == ' '; i++);
  for (j = 0, n = 0; s[i]; i++) {
    if (s[i] != ' ')
      str[n][j++] = s[i];
    else {
      str[n][j] = '\0';
      while (s[i] == ' ') i++;
      if (s[i] == '\0' && s[i - 1] == ' ') break;
      i--;
      n++;
      j = 0;
    }
  }
  str[n][j] = '\0';
  return n + 1;
}

int apart_by_pointer(char *strp[], const char *s)
{
  int n = 0;
  char *p, *ds;
  
  ds = strdup(s);
  
  if ((p = strtok(ds, " ")) == NULL) {
    free(ds);
    return 0;
  }
  strp[n++] = strdup(p);
  while (p = strtok(NULL, " "))
    strp[n++] = strdup(p);
  free(ds);
  return n;
}


No.10444

Re:文字列の分割(配列&ポインタ)
投稿者---ともじ(2003/11/11 22:23:47)


こんばんは。

>配列に文字列「This is not an apple」を代入し、これを単語ごとに
>分割して、それぞれ新たに配列に代入する。
>(This is not an appleの5つに分ける。)
>この処理を、ポインタと配列をつかう2種類のプログラムをつくりたい
>のですが、どうしたらいいのでしょうか。

配列は2次元配列に格納すればいいのですか。
#include <stdio.h>

#define N 20
#define M 20

int main(void)
{
    char str[] = "This is not an apple";
    char word[N][M+1];
    int i = 0, j = 0, k = 0;

    while (str[i] != '\0') {
        if (str[i] != ' ') {
            word[j][k] = str[i];
            k++;
            if (k >= M) break;
        }
        else {
            word[j][k] = '\0';
            k = 0;
            j++;
            if (j >= N) break;
        }
        i++;
    }
    word[j][k] = '\0';

    return 0;
}


ポインタはポインタの配列に文字列リテラルのアドレスを格納すれば
いいですか。
#include <stdio.h>
#include <string.h>

#define N 20

int main(void)
{
    char str[] = "This is not an apple";
    char *word[N];
    int i = 0, j;

    word[i] = strtok(str, " ");
    while (word[i] != NULL && i < N-1) {
        i++;
        word[i] = strtok(NULL," ");
    }

    return 0;
}


なお、両方とも結果の表示部分は削りました。(意地悪したわけでは
ありません。念のため。)
自分で表示してみてください。

#あ、たかさんの方が早かった。

No.10446

Re:文字列の分割(配列&ポインタ)
投稿者---たま(2003/11/11 22:28:14)


ありがとうございます。とても助かりました。
私はBasicは得意なほうなんですが、Cはいつも
詰まってしまうのです。勉強不足でした。

ありがとうございました。

No.10447

Re:文字列の分割(配列&ポインタ)
投稿者---たか(2003/11/11 22:33:05)


>私はBasicは得意なほうなんですが、Cはいつも
>詰まってしまうのです。勉強不足でした。

Basicがお得意でしたら、C言語の文字列は'\0'で終わることを除けば
Basicと同じですよ。ただしLEFT$, MID$, RIGHT$なんて便利な関数は
ありませんけどね。そのためにポインタ版で書くことがほとんどです。

私の配列版を見て頂くとおわかりのように、配列で書くと実に面倒です。
空文字列や語尾にスペースがくっついている場合なども考慮しています。

その点ともじさんのはうまく書けているなあ。