【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.22677

文字列の切り出し
投稿者---とおる(2005/08/17 01:32:03)


こんにちは。
随分前に、こちらの掲示板に投稿させて頂きました。
残念ながら、解決しませんでした。

やりたいことは、文字列の切り出しです。

ヘッダファイル
typedef struct {
char TCD[128]; //担当者コード
char SCD[128]; //商品コード
long Su; //数量
} DATAINFO;

Cファイル
static DATAINFO* dat3;

char temp[]="ABC,123,DEF,456";

tempの文字列を
dat3->TCD
dat3->SCD
dat3->Su
のそれぞれに分けたいと考えています。

前回教えて頂いた方法は、strncpyやstrtokの方法でした。
for分でループし、文字を取得して構造体のメンバに格納
していたのですが、上手くいきませんでした。
(dat3->TCD[0]=temp[5]、dat3->TCD[1]=temp[6])

strncpyやstrtokを使わない方法で文字列を切り出す方法
は実現できないでしょうか。
ポインタなどを上手く使って出来ないものなのでしょうか。

よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:文字列の切り出し 22678 ぽこ 2005/08/17 02:05:00
<子記事> Re:文字列の切り出し 22679 si 2005/08/17 02:54:53
<子記事> Re:文字列の切り出し 22682 まきじ 2005/08/17 12:35:58


No.22678

Re:文字列の切り出し
投稿者---ぽこ(2005/08/17 02:05:00)



>strncpyやstrtokを使わない方法で文字列を切り出す方法
>は実現できないでしょうか。

おそらく可能です。
「おそらく」というのは情報が足らないため、おそらくです。
まず、ここを見ている回答者の理解を助けるために、
前回のリンクを張ってください。

#自分で探す気にならないというのが本音ですが。。

次に、どう上手くいかなかったのか説明しましょう。
(特に前回提示された方法では、何が駄目だったか?)
あと、とおるさんが書かれたソース(そんなに長くなければ)を丸々
載せてください。


この投稿にコメントする

削除パスワード

No.22680

Re:文字列の切り出し
投稿者---Blue(2005/08/17 09:09:23)


> #自分で探す気にならないというのが本音ですが。。
ログNo.22399にありました。
過去ログの未整理ログにも登録されていないので、リンク先が変わる可能性があります。
(スレッド番号(?)は一意ですが)

> (dat3->TCD[0]=temp[5]、dat3->TCD[1]=temp[6])
と前回の発言をみると、C言語における文字列の扱い方を理解していなようですが。

> strncpyやstrtokを使わない方法で文字列を切り出す方法
> は実現できないでしょうか。
と考えるのはなぜでしょうか?
出来ているものを使ったほうがより安定していると思うのですが。
# 課題かなんかでしょうか?



この投稿にコメントする

削除パスワード

No.22695

Re:文字列の切り出し
投稿者---とおる(2005/08/17 22:51:59)


こんにちは。
色々教えて頂き、ありがとうございます。

バーコードリーダーの開発をしています。
使える標準関数は、
strcpy
strcat
strcmp
strlen
memcpy
memcmp
memset
atoi(似たような関数ですが、機能は同じです)
です。

>あと、とおるさんが書かれたソース(そんなに長くなければ)を丸々
>載せてください。
作成中の関数です。
main関数から呼ばれるようになっています。

void dispData( char* pData )
{
int i = 0;
int j = 0;
int s = 0;

//各項目に分割
for (i = 0 ; pData[i] != '\0' ; i++ ){
if ( pData[i] == ',' ){
j++;
}
switch (j)
{
case 2:
if ( pData[i] == ',' ){
s = 0;
} else {
dat3->TCD[s] = pData[i];
s++;
}
break;
case 3:
if ( pData[i] == ',' ){
dat3->TCD[s] = '\0';
s = 0;
} else {
dat3->SCD[s] = pData[i];
}
break;
}
}
return ;
}

バーコードリーダーの画面に表示する関数を使って
dat3->TCDを表示したのですが、dat3->TCDには
データが入っていませんでした。

よろしくお願いします。


この投稿にコメントする

削除パスワード

No.22701

Re:文字列の切り出し
投稿者---まきじ(2005/08/17 23:49:57)


>dat3->TCDを表示したのですが、dat3->TCDには
>データが入っていませんでした。

dat3 の領域が確保されていないからです。
si さんのを参考してください。


この投稿にコメントする

削除パスワード

No.22704

Re:文字列の切り出し
投稿者---とおる(2005/08/18 00:51:25)


こんにちは。

>dat3 の領域が確保されていないからです。
>si さんのを参考してください。
mallocが使えないみたいで、コンパイルしたらエラーが
出てしまいました。

memsetみたいなもので代用できないでしょうか?
すみません。
構造体が慣れてなくて...。

よろしくお願いします。



この投稿にコメントする

削除パスワード

No.22705

Re:文字列の切り出し
投稿者---たかお(2005/08/18 01:11:26)


void dispData( char* pData )
{
}

内で、dat3が存在していなからです。
dat3がどこにも宣言されていないか、dat3のアドレスが渡されてきていない
からだと思います。
間違っていたらすみません。


この投稿にコメントする

削除パスワード

No.22706

Re:文字列の切り出し
投稿者---とおる(2005/08/18 01:32:04)


こんにちは。

>void dispData( char* pData )
>{
>}
>
>内で、dat3が存在していなからです。
>dat3がどこにも宣言されていないか、dat3のアドレスが渡されてきていない
>からだと思います。
>間違っていたらすみません。
宣言は、

ヘッダファイル
typedef struct {
char TCD[128]; //担当者コード
char SCD[128]; //商品コード
long Su; //数量
} DATAINFO;

Cファイル(宣言部)
static DATAINFO* dat3;

としています。

これだけでは足りないのでしょうか?
すみません。
ご指摘お願いします。


この投稿にコメントする

削除パスワード

No.22707

Re:文字列の切り出し
投稿者---たかお(2005/08/18 01:36:36)


>Cファイル(宣言部)
>static DATAINFO* dat3;

の領域はどこで確保されてますか。
確保した領域をdispData関数に渡していますか。

dispData関数内で使うためには、確保したdat3を渡してやらなければ
ならないと思うのですが



この投稿にコメントする

削除パスワード

No.22708

Re:文字列の切り出し
投稿者---まきじ(2005/08/18 01:43:42)


>static DATAINFO* dat3;

DATAINFO へのポインタを格納するだけの領域しか
確保されていません。(処理系依存ですが、例えば 4 バイト)

実際は

char TCD[128];
char SCD[128];
long Su;

だけの領域が必要です。

解りにくいのであれば、無理にポインタを使わずに
配列でやってみてください。


この投稿にコメントする

削除パスワード

No.22709

Re:文字列の切り出し
投稿者---たかお(2005/08/18 02:06:31)


>>static DATAINFO* dat3;
>

dat3は、ポインタなので、構造体のサイズの領域を確保する必要が
あると思いますし、確保した領域を渡す必要があると思います。
間違っていたらすみません。

宣言が、グローバルでしたら渡す必要はないですね。
間違っていたらすみません。




この投稿にコメントする

削除パスワード

No.22710

Re:文字列の切り出し
投稿者---rvr_driver(2005/08/18 08:08:54)


>構造体が慣れてなくて...。

今回の問題は構造体ではないです。
ポインタを理解しているかどうかの問題です。
まきじさんやたかおさんが仰るように、dat3の領域が
確保されていないのが問題です。

mallocが使用できないというところまで判っているのですから
別の方法で領域を確保しなければいけませんよね。

DATAINFO構造体の変数を宣言し、その変数のアドレス
(といっていいのかな?)をdat3が指すようにすれば領域を確保
することが出来ます。

ポインタについては以下を見てみてください。
http://www9.plala.or.jp/sgwr-t/c/sec10.html



この投稿にコメントする

削除パスワード

No.22721

Re:文字列の切り出し
投稿者---とおる(2005/08/18 14:58:04)


こんにちは。

>今回の問題は構造体ではないです。
>ポインタを理解しているかどうかの問題です。
>まきじさんやたかおさんが仰るように、dat3の領域が
>確保されていないのが問題です。
>
>mallocが使用できないというところまで判っているのですから
>別の方法で領域を確保しなければいけませんよね。
>
>DATAINFO構造体の変数を宣言し、その変数のアドレス
>(といっていいのかな?)をdat3が指すようにすれば領域を確保
>することが出来ます。
随分調べていたのですが、まだ解決には至っていません。
もう少し、努力して調べてみます。

それと気になっていたのですが、先日投稿したコードは
間違っていなかったのでしょうか。
そちらの方も気になっています。

void dispData( char* pData )
{
int i = 0;
int j = 0;
int s = 0;

//各項目に分割
for (i = 0 ; pData[i] != '\0' ; i++ ){
if ( pData[i] == ',' ){
j++;
}
switch (j)
{
case 2:
if ( pData[i] == ',' ){
s = 0;
} else {
dat3->TCD[s] = pData[i];
s++;
}
break;
case 3:
if ( pData[i] == ',' ){
dat3->TCD[s] = '\0';
s = 0;
} else {
dat3->SCD[s] = pData[i];
}
break;
}
}
return ;
}

何か間違いがあれば、ご指摘願いたいと思います。
そもそも、上記のような配列間のデータの受け渡しで
文字列の切り出しは可能なのでしょうか。

宜しくお願いします。


この投稿にコメントする

削除パスワード

No.22722

Re:文字列の切り出し
投稿者---まきじ(2005/08/18 15:12:37)


>そもそも、上記のような配列間のデータの受け渡しで
>文字列の切り出しは可能なのでしょうか。

区切られているか否かということでしたら、トレースすれば解るでしょ?


この投稿にコメントする

削除パスワード

No.22729

Re:文字列の切り出し
投稿者---rvr_driver(2005/08/18 17:09:39)


仕様を理解していないので間違いがあるかどうかは判断できません。
文字列の切り出しについては可能と思います。
その前にdat3の領域確保が出来れば、文字列の切り出しが出来ているか
どうかの判断はつくと思います。

コードを見て気になる事項です。もし間違っていた場合は申し訳ないです。

1.pDataの文字数が不明なのでナル文字を文字の終端として判断するのは危険では?
  →pDataにナル文字がなかった場合はどのように考えてますか?
   pDataは必ずナル文字が入っている保障があれば問題ないと思いますが・・・。

2.case 2の場合のdat3->TCDの内容にナル文字が設定されていません。問題ないですか?

3.case 3の場合のdata3->SCDは1文字しか代入されませんが仕様どおりですか?

問題解決に充分なヒントは皆さんから回答を頂いていると思うので、
自分はこれ以上回答はしませんのでよろしくお願いします。


この投稿にコメントする

削除パスワード

No.22771

Re:文字列の切り出し
投稿者---とおる(2005/08/22 01:03:53)


こんにちは。
色々な方からのご指導感謝します。
結局ポインタを使わなくて、直接メンバを指定するようにしました。
とりあえず、上手くいきましたが...。

勉強のために今一度ご教示下さい。

1.構造体の直接メンバ指定の場合、領域の確保は必要ないのでしょうか。
2.ここ3日間ほど調べましたが、結局判りませんでした。教えて頂けないでしょうか。
>DATAINFO構造体の変数を宣言し、その変数のアドレス
>(といっていいのかな?)をdat3が指すようにすれば領域を確保
>することが出来ます。
C言語は初心者に近いため、努力不足だとは思いますが判りませんでした。

申し訳ございません。
よろしくお願いします。


この投稿にコメントする

削除パスワード

No.22772

Re:文字列の切り出し
投稿者---まきじ(2005/08/22 01:20:03)


>1.構造体の直接メンバ指定の場合、領域の確保は必要ないのでしょうか。

ポインタを止めたという事なら、宣言した時点で領域は確保されている
ので malloc() する必要ありません。


この投稿にコメントする

削除パスワード

No.22779

Re:文字列の切り出し
投稿者---rvr_driver(2005/08/22 23:45:20)


> 1.構造体の直接メンバ指定の場合、領域の確保は必要ないのでしょうか。

領域の確保は必要ありません。理由は・・・と言いたいところですが、
ポインタについては理解されましたでしょうか?
それが解らない限りは恐らく解らないままだと思います。

バーコードリーダーの開発ということは組み込みの開発と思います。
元のソースは自分で初めから設計、コーディングしているというのであれば
特に言う事はありません。今回の解決策でよいです。
誰かが設計、コーディングしたところで、とおるさんが途中からソースを
修正、追加しているものだとしたら安易にこの解決策をとったのであれば
お勧めしません。
なぜかは、開発の現場の方に聞いてみてください。
それなりの理由があるはずです。無ければ一番いいんですけどね。

> 2.ここ3日間ほど調べましたが、結局判りませんでした。教えて頂けないでしょうか。
> >DATAINFO構造体の変数を宣言し、その変数のアドレス
> >(といっていいのかな?)をdat3が指すようにすれば領域を確保
> >することが出来ます。
> C言語は初心者に近いため、努力不足だとは思いますが判りませんでした。

簡単ですがこんなものでいいでしょうか?

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

typedef struct {
    char TCD[128]; //担当者コード
    char SCD[128]; //商品コード
    long Su; //数量
} DATAINFO;

//Cファイル(宣言部)
static DATAINFO* dat3;
static DATAINFO data;   // DATAINFO構造体の変数を宣言
                        // →ここでDATAINFO構造体の実体(インスタンス)が出来ます

int main()
{
    printf("dat3とdataの違いをアドレスで確認\n");
    printf("dat3 adress : [%p]\n", dat3);      // ポインタ
    printf("data adress : [%p]\n\n", &data);        // 実体(インスタンス)
    
    dat3 = &data;      // その変数のアドレスをdat3が指すようにする
                        // →この行を削除すると領域が確保されないので
                        //   コンパイルエラーが発生したり、
                        //   運良くコンパイルできても異常終了したりします。

    printf("dat3がdataのアドレスを指している事をアドレスで確認\n");
    printf("dat3 adress : [%p]\n", dat3);      // ポインタ
    printf("data adress : [%p]\n\n", &data);        // 実体(インスタンス)
    
    strcpy(dat3->TCD, "DATAINFO構造体の変数を宣言し、\n");
    strcpy(dat3->SCD, "その変数のアドレスdat3が指すようにすれば\n");
    dat3->Su = 10;

    printf("%s%s領域が確保できます。\ndat3->Su = [%d]\n", dat3->TCD, dat3->SCD, dat3->Su);
                        // 領域が確保できます。
    
    // dat3とdataの違いをサイズで確認
    // この差がポインタと実体の違いになります
    // 詳しくは以前自分が紹介したサイトを参照するなり本で調べるなりして下さい。
    printf("sizeof(dat3) = [%d]\n", sizeof(dat3));    // ポインタ
    printf("sizeof(data) = [%d]\n", sizeof(data));    // 実体(インスタンス)

    return 0;
}




実行結果

dat3とdataの違いをアドレスで確認
dat3 adress : [00000000]
data adress : [0040C5A0]

dat3がdataのアドレスを指している事をアドレスで確認
dat3 adress : [0040C5A0]
data adress : [0040C5A0]

DATAINFO構造体の変数を宣言し、
その変数のアドレスdat3が指すようにすれば
領域が確保できます。
dat3->Su = [10]
sizeof(dat3) = [4]
sizeof(data) = [260]


この投稿にコメントする

削除パスワード

No.22794

Re:文字列の切り出し
投稿者---とおる(2005/08/24 14:06:08)


こんにちは。
rvr_driverさん、ありがとうございます。

勉強になりました。

なるほど...、他の変数を宣言しアドレスを
指定するということなんですね。

もっと勉強が必要のような気がします。

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


この投稿にコメントする

削除パスワード

No.22679

Re:文字列の切り出し
投稿者---si(2005/08/17 02:54:53)


/* 
文字列が、例の様に","(カンマ)区切りで、スペースが入っていないのであれば
sscanfで読み込むのが、普通かと思います。
  sample
*/ 
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char TCD[128]; //担当者コード
    char SCD[128]; //商品コード
    long Su; //数量
} DATAINFO;


int main(int argc,char **argv)
{
    DATAINFO *dat3;
    char temp[]="ABC,123,DEF,456";
    long dummy;
    int n,err;

    dat3 = malloc(sizeof(DATAINFO));
    if (dat3) {
        n = sscanf(temp,"%[^,],%d,%[^,],%d",dat3->TCD,&dummy,dat3->SCD,&dat3->Su);
        if (n == 4) {
            printf("TCD: %s\tdummy: %d\tSCD: %s\tSu: %d\n",dat3->TCD,dummy,dat3->SCD,dat3->Su);
            err = 0;
        } else {
            printf("sscanf error\n");
            printf("TCD: %s\tdummy: %d\tSCD: %s\tSu: %d\n",dat3->TCD,dummy,dat3->SCD,dat3->Su);
            err = 1;
        }
        free(dat3);
    } else {
        printf("malloc error\n");
        err = -1;
    }
    return err;
}



この投稿にコメントする

削除パスワード

No.22682

Re:文字列の切り出し
投稿者---まきじ(2005/08/17 12:35:58)


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

typedef struct{
    char tid[128];
    char sid[128];
    int n;
}DATA;

int strsep(char buf[]){

    static int pos = 0;
    int p = pos;
    
    while(buf[pos] != ',' && buf[pos] != '\0') pos++;
    
    if(buf[pos] == ','){
        buf[pos] = '\0';
        pos++;
        return p;
    }
    
    return -1;
}

void str_cpy(char *dst, const char *src){

    while((*dst = *src) != '\0'){
        dst++;
        src++;
    }
}

int main(void){

    char buf[]="1001,001,5";
    DATA dat={"","",-1};
    int pos;
    
    if((pos = strsep(buf)) != -1 ) str_cpy(dat.tid,&buf[pos]);
    if((pos = strsep(buf)) != -1 ) str_cpy(dat.sid,&buf[pos]);
    if((pos = strsep(buf)) != -1 ) dat.n = atoi(&buf[pos]);
    
    printf("tid : %s\nsid : %s\nn : %d\n",dat.tid,dat.sid,dat.n);
    return 0;
}
# atoi() は使ってますが・・・


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧