将字符串拆分为3d数组

时间:2015-10-21 10:33:04

标签: c++ c arrays string arduino

假设我们有一个字符串str

String str = "1,2,3,4444444444;5,6,7,8888888888;.9,10,11,1212121212;.";

定义字符串中嵌入的三个维度d1d2d3,如下所示:

  • d1包含以点“。”
  • 分隔的元素
  • d2包含以分号“;”
  • 分隔的元素
  • d3包含以逗号“,”
  • 分隔的元素

d3d2的孩子,d2d1(父母)的孩子。 d1 > d2 > d3

我们希望能够访问字符串中嵌入的每个元素,这意味着我们应该有一个结果 - 如下所示的数组:

d[0][0][0] = "1";
d[0][0][1] = "2";
d[0][0][2] = "3";
d[0][0][3] = "4444444444";
d[0][1][0] = "5";
d[0][1][1] = "6";
d[0][1][2] = "7";
d[0][1][3] = "8888888888";
d[1][0][0] = "9";
d[1][0][1] = "10";
d[1][0][2] = "11";
d[1][0][3] = "12121212";
  • 您可以看到d[i][j][k]其中k = [0, 2]是整数。
  • 您可以看到d[i][j][k]其中k = 3为长整数。

我们希望现在将这些字符串转换为适当的整数类型(常规整数或长整数)。这意味着我们的最终数组应如下所示:

d[0][0][0] = 1; // int
d[0][0][1] = 2; // int
d[0][0][2] = 3; // int
d[0][0][3] = 4444444444; // long int
d[0][1][0] = 5; // int
d[0][1][1] = 6; // int
d[0][1][2] = 7; // int
d[0][1][3] = 8888888888; // long int
d[1][0][0] = 9; // int
d[1][0][1] = 10; // int
d[1][0][2] = 11; // int
d[1][0][3] = 12121212; // long int

这个想法是在一个基于c / c ++的arduino微控制器上实现的。

这是我对它的看法,不幸的是不能正常工作。

  String data = "1,2,3,1445303228;4,5,6,1445303228;.7,8,9,1445303273;.";

  int data_length = data.length() + 1;

  if (data_length != 1) {

    char d0[data_length]; // couldn't do it with String, let's try char
    data.toCharArray(d0, data_length);

    int size1 = 32, size2 = 64; // intuitive sizes

    char d1[size1][136]; // strlen("1,2,3,1445303228") * 8, 17 * 8 = 136

    int i = 0;
    for (char *p = strtok(d0, "."); p != NULL; p = strtok(NULL, "."))
    strcpy(d1[i++], p); // d1

    int d1_length = i;

    char d2[d1_length][size2][17]; // strlen("1,2,3,1445303228") = 16

    int d2_length[size2];
    for (int i = 0; i < size2; i++) d2_length[i] = 0; // initialize array = 0

    for (int i = 0; i < d1_length; i++) {
      int j = 0;
      for (char *p = strtok(d1[i], ";"); p != NULL; p = strtok(NULL, ";"))
      strcpy(d2[i][j++], p); // d2

      d2_length[i] = j;
    }

    int d2_length_max = 0;
    for (int i = 0; i < size2; i++)
    if (d2_length[i] > d2_length_max) d2_length_max = d2_length[i];

    char d3[d1_length][d2_length_max][4][10];
    // d2 can have 4 d3's max, d3 can have 10 chars max

    for (int i = 0; i < d1_length; i++) {
      for (int j = 0; j < d2_length[i]; j++) {
        int k = 0;
        for (char *p = strtok(d2[i][j], ","); p != NULL; p = strtok(NULL, ","))
        strcpy(d3[i][j][k++], p); // d3
      }
    }

    int rows[d1_length][d2_length_max][3];
    long rows_long[d1_length][d2_length_max];

    for (int i = 0; i < d1_length; i++)
    for (int j = 0; j < d2_length[i]; j++)
    for (int k = 0; k < 3; k++)
    rows[i][j][k] = atoi(d3[i][j][k]); // char array to integer

    for (int i = 0; i < d1_length; i++)
    for (int j = 0; j < d2_length[i]; j++) {
      char temp[10];
      for (int k = 0; k < 10; k++) temp[k] = d3[i][j][3][k];
      rows_long[i][j] = atol(temp); // char array to long
    }

  }

请注意,长整数实际上是一个unix时间戳。

5 个答案:

答案 0 :(得分:1)

使用纯C中的动态平面数组,然后分配3D数组 每次需要时,数组大小为两倍 您可以使用define:

设置第一个大小
#define DEFAULT_SIZE 8 

如我的评论中所述,格式很奇怪;.应为.,最终;.应删除

我添加测试以检查下一行是否与第一行相同。

int main(void) { 
    char *data = "1,2,3,1445303228;4,5,6,1445303228;.7,8,9,1445303273;."; 
    char *p; 
    int size = DEFAULT_SIZE; 
    int nb_element = 0; 
    int s1 = 0; 
    int s2 = 0; 

    int cur1 = 0; 
    int cur2 = 0; 
    int cur3 = 0; 

    int *d = malloc(sizeof(int) * DEFAULT_SIZE); 
    int ***d3; 

    if (!d) { 
        return -1; 
    } 

    p = data; 
    while (*p) { 
        if (nb_element == size) { 
            size *= 2; 
            d = realloc(d, size * sizeof(int)); 
            if (!d) { 
                return -1; 
            } 
        } 
        d[nb_element++] = strtol(p, &p, 10); 
        switch (*p) { 
          case ',': 
            cur1++; 
            if (s1 && cur1 > s1) { 
                fprintf(stderr, "Too many element for %d, %d:" 
                        " get %d, expect %d\n", cur2, cur3, cur1, s1); 
                return -1; 
            } 
            break; 
          case ';': 
            cur1++; 
            cur2++; 
            if (s1 == 0) { 
                s1 = cur1; 
            } 
            cur1 = 0; 
            if (s2 && cur2 > s2) { 
                fprintf(stderr, "Too many element for %d:" 
                        " get %d, expect %d\n", cur3, cur2, s2); 
                return -1; 
            } 
            break; 
          case '.': 
          dot: 
            cur2++; 
            cur3++; 
            if (s2 == 0) { 
                s2 = cur2; 
            } 
            cur2 = 0; 
            cur1 = 0; 
            break; 
        } 
        p++; 
        /* XXX: ack due to strange format */ 
        if (*p == '.') 
            goto dot; 
    } 
    /*XXX! remove empty final line */ 
    cur3--; 

    d3 = malloc(sizeof(int **) * cur3); 
    for (int i = 0; i < cur3; i++) { 
        d3[i] = malloc(sizeof(int *) * s2); 
        for (int j = 0; j < s2; j++) { 
            d3[i][j] = malloc(sizeof(int) * s1); 
            for (int k = 0; k < s1; k++) {  
                d3[i][j][k] = d[i * s2 + j * s1 + k]; 
            } 
        } 
    } 
    free(d); 
    for (int i = 0; i < cur3; i++) { 
        for (int j = 0; j < s2; j++) { 
            for (int k = 0; k < s1; k++) { 
                fprintf(stdout, "d[%d][%d][%d] = %d\n", i,j,k, d3[i][j][k]); 
            } 
        } 
    } 
    return 0; 
} 

输出:

d[0][0][0] = 1
d[0][0][1] = 2
d[0][0][2] = 3
d[0][0][3] = 1445303228
d[0][1][0] = 4
d[0][1][1] = 5
d[0][1][2] = 6
d[0][1][3] = 1445303228
d[0][2][0] = 7
d[0][2][1] = 8
d[0][2][2] = 9
d[0][2][3] = 1445303273

答案 1 :(得分:0)

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

int c1,c2,c3;

int n=0;
char sResult[20];

void PrintLevel(int lvl){
    if(n){
        printf("d[%d][%d][%d] = \"%s\"\n",c3,c2,c1,sResult);
        n=0;
    }
    switch(lvl){
        case 3:
            c3++;
            c2=c1=0;
            break;
        case 2:
            c2++;
            c1=0;
            break;
        case 1:
            c1++;
    }

    return ;
}

void addChar(char c){
    sResult[n]=c;
    n++;
    sResult[n]=c=0;
}
/*______________________________________________________________________
*/

int main(){
    char buff[]= "0,1,2,4444444444;5,6,7,8888888888;.9,10,11,12121212;.";
    PrintLevel(0);
    char *p=buff;
    char c;
    int ret;
    int lvl;
    while(c=*p){

        lvl=(c==',')?1:((c==';')?2:((c=='.')?3:0) );

        if(lvl)
            PrintLevel(lvl);
        else
            addChar(c);
        p++;
    }
    PrintLevel(lvl);

}

答案 2 :(得分:0)

首先请注意,long太小而无法容纳:4444444444 It's max size is: 2147483647

如果使用long long,则可以通过regex_token_iterator雄辩地解析字符串。解析函数应该接受输入string和分隔符并返回分隔的strings。这些输入允许在类似于以下的函数中重用:

auto parse(const string& input, const string& delimiter) {
    const regex re("([^" + delimiter + "]+)" + delimiter + '?');

    return vector<string>(sregex_token_iterator(input.begin(), input.end(), re, 1), sregex_token_iterator());
}

这将返回分区input中的vector<string>。然后可以对此返回进行分区,直到每个分区仅包含数字字符的第三维。此时stoll可用于将string转换为long long。这种分区可以在嵌套循环中完成,如下所示:

vector<vector<vector<long long>>> foo;

for (auto& i : parse(str, "\\.")) {
    foo.resize(foo.size() + 1);
    for (auto& j : parse(i, ";")) {
        foo.back().resize(foo.back().size() + 1);
        for (auto& k : parse(j, ",")) {
            foo.back().back().push_back(stoll(k));
        }
    }
}

这方面的一个关键方面是每个分区必须包含一个数字。这由'+'中的re强制执行,如果连续分隔符出现则不匹配。 stoll非常健壮并且如果在输入string中会占用空格,但是如果仅包含空格的string或通常不包含数字的stoll被输入它,它将抛出一个空格错误。如果这是一个问题,请务必在致电Traceback (most recent call last): File "<string>", line 1, in <module> ImportError: dlopen(/Users/me/sx_direct_env/lib/python2.7/site-packages/cx_Oracle.so, 2): Library not loaded: /b/227/rdbms/lib/libclntsh.dylib.10.1 Referenced from: /Users/me/sx_direct_env/lib/python2.7/site-packages/cx_Oracle.so Reason: image not found 之前检查您的输入。

您可以在此处查看此实例:http://ideone.com/4vjdBx

答案 3 :(得分:0)

使用主要基于@milevyo's answer的代码。

struct ds { int a = 0, b = 0, c = 0; long d = 0; };

struct data {
  struct ds array[32][8];
  int i, j[24];

  int n = 0, d1, d2, d3; char r[11];
  void get(String array) {
    if (array.length() + 1 != 1) {
      char buff[array.length() + 1];
      array.toCharArray(buff, array.length() + 1);
      char c; char *p = buff; int l;
      while (c = *p) {
        l = (c == ',') ? 1 : ((c == ';') ? 2 : ((c == '.') ? 3 : 0));
        if (l) a(l); else ch(c); p++;
      }
      a(l);
    }
  }
  void a(int l) {
    if (n) {
      if (d1 == 0) array[d3][d2].a = atoi(r);
      else if (d1 == 1) array[d3][d2].b = atoi(r);
      else if (d1 == 2) array[d3][d2].c = atoi(r);
      else if (d1 == 3) array[d3][d2].d = atol(r);
      i = d3 + 1; j[d3] = d2 + 1; n = 0;
    }
    switch (l) {
      case 3: d3++; d2 = d1 = 0; break;
      case 2: d2++; d1 = 0; break;
      case 1: d1++; break;
    }
  }
  void ch(char c) { r[n] = c; n++; r[n] = c = 0; }
} data;

void setup () {
  Serial.begin(19200); 
  Serial.println(".."); 

  data.get("1,2,3,1445433855;4,5,6,1445433855;.7,8,9,1445438763;.");

  for (int i = 0; i < data.i; i++) {
    for (int j = 0; j < data.j[i]; j++) {
      for (int k = 0; k < 4; k++) {
        if (k == 0) Serial.print(data.array[i][j].a);
        else if (k == 1) Serial.print(data.array[i][j].b);
        else if (k == 2) Serial.print(data.array[i][j].c);
        else if (k == 3) Serial.print(data.array[i][j].d);
        Serial.print("\t");
      }
      Serial.println();
    }
    Serial.println();
  }
}

void loop () { }

1,2,3,1445433855;4,5,6,1445433855;.7,8,9,1445438763;.

..
1   2   3   1445433855  
4   5   6   1445433855  

7   8   9   1445438763  

经由

..
data.array[0][0].a  data.array[0][0].b  data.array[0][0].c  data.array[0][0].d
data.array[0][1].a  data.array[0][1].b  data.array[0][1].c  data.array[0][1].d

data.array[1][0].a  data.array[1][0].b  data.array[1][0].c  data.array[1][0].d

答案 4 :(得分:0)

我希望你保存了最后一篇文章,这是对最后一篇文章的更新,它按照要求处理2D数组。希望你发现它有用,如果是这样给我发一张明信片:)

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


/*__________________________________________________________________________
*/

struct DATA{
   char a;
   char b;
   char c;
   unsigned long d;
};


/*__________________________________________________________________________

  allocate DATA struct, and fill it.
  on error or no data, returns NULL
*/
struct DATA *ParseString(char **pstr){
    int val=0;
    char *p;
    struct DATA *data;
    if(!pstr) return NULL;

    char *str=*pstr;
    if(!str) return NULL;

    // can be ommited
    // skipping non digital chars
    while(*str && !isdigit(*str))
        str++;

    //no digits?
    if(!*str) return NULL;

    p=str;
    //ok at least one
    data=(struct DATA*) calloc(1,sizeof(struct DATA));//calloc to initialize all to 0
    for(int n=0;n<4;n++){
        val=0;
        while(isdigit(*p)){
            val*=10;
            val+=(*p)-'0';
            p++;
        }
        switch(n){
            case 0:
                data->a=val;
                break;
            case 1:
                data->b=val;
                break;
            case 2:
                data->c=val;
                break;
            case 3:
                data->d=val;
                break;
        }
        val=0;
        if(*p!=',')
            break;
        p++;

    }
    *pstr=p;
    return data;
}
/*__________________________________________________________________________

    calculate the size of DATA * arra[c1][c2]
*/
void countArrBoudaries(char *s,unsigned short *c1,unsigned short *c2){
    *c1=*c2=0;
    unsigned short _c1=0;
    while(*s){
        switch(*s){
            case ';':
                _c1++;
                break;
            case '.':
                if(_c1>*c1)
                    *c1=_c1;
                _c1=0;
                *c2+=1;
                break;
        }
        s++;
    }
}
/*__________________________________________________________________________
*/
int main(void){

    struct DATA **pdata,*data;
    char buff[]="1,2,3,1445303228;4,5,6,1445303228;.7,8,9,1445303273;.";
    char *p=buff;
    unsigned short c1,c2;
    countArrBoudaries(buff,&c1,&c2);
    pdata=(struct DATA**)calloc((c2*c1),sizeof(pdata));

    if(pdata){
        // loading
        for(int i=0;i<c1;i++)
            for(int j=0;j<c2;j++)
                pdata[i+(j*c1)]=ParseString(&p);

        // printing:
        for(int i=0;i<c1;i++)
            for(int j=0;j<c2;j++){
                data=pdata[i+(j*c1)];
                if(data){
                    printf("data[%u][%u]={%d,%d,%d,%u};\n",i,j,data->a,data->b,data->c,data->d);
                }else{
                    printf("data[%u][%u]=NULL;\n",i,j);
                }
            }

        // freeing memory:
        for(int i=0;i<(c1*c2);i++)
            free(pdata[i]);
        free(pdata);

    }
    printf("\n\nDONE\n\n");
    return 0;
}