2017-04-12 7 views
0

を割り当てることなく、2次元char配列に1次元char配列を変換:私は、例えば、文字列を有するメモリ

char* cmd = "a bcd ef hijk lmmopq";

文字列が空白で分割セグメントで構成され、セグメントの数が固定されていません。

直感的に、私は例えば、動的にメモリを割り当てることにより、2Dのchar文字列を取得することができます

char** argv = malloc(); 
char* argv[0] = malloc(); 
... 
char* argv[i] = malloc(); 

しかし、私は元の配列は、メモリ割り当てを避けるために、以下のような文字列を2dに変換することができますか?私のコメントに引き続き、あなたが例えば、とあなたの文字列をトークン化することができます

char* argv[] = {"a", "bcd", "ef", "hijk", "lmmopq"}; 
+1

'char ** argv'は2次元配列ではなく、ポインタへのポインタです。 'char a [3] [4]'は2D配列です。 – chux

+0

*「メモリ割り当てを避けるために、以下のような2次元のchar配列を得ることはできますか?」「私は得ることができますか?どこから?あなたはその配列のサイズを事前に知っていますか? –

+0

元のcmdを2次元配列に変換したい。後で2次元配列のように使いたいです。@ AlexLop。 –

答えて

0

strtokを参照し、個々の単語へのポインタをへのポインタへのポインタに割り当てます。

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

#define MAX 10 

int main (void) { 

    char *cmd = (char[]){"a bcd ef hijk lmmopq"},  /* compound literal */ 
    // char cmd[] = "a bcd ef hijk lmmopq"; /* otherwise declare as array */ 
     *arr[MAX] = {NULL}, 
     *delim = " \n"; 
    size_t n = 0; 

    for (char *p = strtok (cmd, delim); n < MAX && p; p = strtok (NULL, delim)) 
     arr[n++] = p; 

    for (int i = 0; i < (int)n; i++) 
     printf ("arr[%d]: %s\n", i, arr[i]); 

    return 0; 
} 

*使用例/出力**

$./bin/str2ptp 
arr[0]: a 
arr[1]: bcd 
arr[2]: ef 
arr[3]: hijk 
arr[4]: lmmopq 

注:たとえばあなたはstrtokとしてstrtokから文字列リテラル文字列を変更を渡すことはできません。配列へのポインタを使用するか、最初に通常のchar[]配列として宣言して初期化します。


動的にあなたが20個の単語または2000個の単語を読むことができるかどうか分からない場合は、あなたが簡単に動的にポインタのブロックを割り当てることにより、状況に対処することができます

の単語の数が不明のため、ポインタを割り当てると、以前の最大割り当てに再び達した場合には、再度reallocが実行されます。これは単純なプロセスです。

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

#define MAX 10 
#define MAXB 4096 

int main (void) { 

    char cmd[MAXB] = "", /* buffer of 4096 chars to hold each line input */ 
     **arr = calloc (MAX, sizeof *arr), 
     *delim = " \n"; 
    size_t n = 0, max = MAX; 

    while (fgets (cmd, MAXB, stdin)) { /* read each line of input on stdin */ 

     size_t len = strlen (cmd); /* get line length */ 
     if (cmd[len - 1] == '\n') /* test for trailing '\n' */ 
      cmd[--len] = 0;   /* overwrite with nul-byte */ 

     for (char *p = strtok (cmd, delim); p; p = strtok (NULL, delim)) { 
      arr[n++] = p; 

      if (n == max) { /* realloc arr by MAX if n == MAX */ 
       void *tmp = realloc (arr, (max + MAX) * sizeof *arr); 
       if (!tmp) { 
        fprintf (stderr, "error: memory exhausted.\n"); 
        break; 
       } 
       arr = tmp; /* zero new pointers (optional) */ 
       memset (arr + max, 0, MAX * sizeof *arr); 
       max += MAX; /* update current max iteration */ 
      } 
     } 
     for (int i = 0; i < (int)n; i++) 
      printf ("arr[%2d]: %s\n", i, arr[i]); 
    } 

    free (arr); /* don't forget, if you allocate it -> you free it. */ 

    return 0; 
} 

の上には、常にあなたの割り当てを、例えばと検証if (!arr) { /* handle error */ }は、簡略化のためにarrの最初の割り当てから省略されました。

使用例/入力

$ echo "A quick brown fox jumps over the lazy dog while the dog watched" | \ 
./bin/strtop2pdyn 
arr[ 0]: A 
arr[ 1]: quick 
arr[ 2]: brown 
arr[ 3]: fox 
arr[ 4]: jumps 
arr[ 5]: over 
arr[ 6]: the 
arr[ 7]: lazy 
arr[ 8]: dog 
arr[ 9]: while 
arr[10]: the 
arr[11]: dog 
arr[12]: watched 
+0

トークンが20個の場合はどうなりますか?または100?最後のトークンはスペースで区切られた 'X-MAX'部分文字列で構成されます – Rogus

+0

あなたは' MAX'を十分に大きく設定するか、必要に応じて*を動的に割り当てる*を選択します。しかしながら、この問題の文脈において、問題の定義は、「5」トークンのセットに関するものであった。もし私がこれを実装していたら、 'arr'に最初の' MAX'ポインタを動的に割り当て、必要に応じて 'realloc'を呼び出して、そこにある多くの単語を扱います。 –

+0

それは正しいですが、OPはトークンの数が固定されておらず、彼はメモリ割り当てを避けたいと述べました。 'MAX'を十分に大きな値に設定する時代のほとんどはうまくいきますが、IMHOは悪い習慣です。 – Rogus

1

別の答えで指摘したように区切り文字(スペース)は、ヌルターミネータに置き換えられるように、strtokはその場であなたの文字列を分割するために使用することができます。

文字列の数を知るには、文字列を2回繰り返す必要があります。

size_t count_spaces (const char* src) 
{ 
    size_t spaces=0; 
    for(; *src != '\0'; src++) 
    { 
    if(*src == ' ') 
    { 
     spaces++; 
    } 
    } 
    return spaces; 
} 

が続いて2回目の反復のために、 strtokを使用します。最初の繰り返しのために、このような文字列を、変更されませんいくつかの簡単な&の簡単な関数を発明。完全な例:

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

size_t count_spaces (const char* src) 
{ 
    size_t spaces=0; 
    for(; *src != '\0'; src++) 
    { 
    if(*src == ' ') 
    { 
     spaces++; 
    } 
    } 
    return spaces; 
} 

void tokenize (char* restrict src, 
       size_t dst_size, 
       char* restrict dst [dst_size]) 
{ 
    size_t i; 
    char* ptr = strtok(src, " "); 
    for(i=0; i<dst_size && ptr != NULL; i++) 
    { 
    dst[i] = ptr; 
    ptr = strtok(NULL, " "); 
    } 
} 

int main (void) 
{ 
    char str [] = "a bcd ef hijk lmmopq"; 
    size_t size = count_spaces(str) + 1; 
    char* ptr_arr [size]; 

    tokenize(str, size, ptr_arr); 

    for(size_t i=0; i<size; i++) 
    { 
    puts(ptr_arr[i]); 
    } 
} 
関連する問題