簡體   English   中英

如何在C中將逗號分隔的char *轉換為uint32_t []數組

[英]How to convert comma separated char* to uint32_t[] array in C

我想將逗號分隔的char *轉換為C中的uint32_array []。是否有簡單的方法/例程來做到這一點?

我已經花了很多時間在SO上,並在C ++上找到了許多解決方案,但不是這樣的C: 解析以逗號分隔的std :: string,但是我認為從char *轉換為string到string並不是一個好的解決方案流到矢量並使用該矢量。

char input[] = "1 , 2 , 34, 12, 46, 100";

uint32_t output[] = { 1 , 2 , 34, 12, 46, 100 };

我將不勝感激。 非常感謝。

一種(多種)方法:

int converted = 0 ;
char* tok = input ;
int i = 0 ;
do
{
    converted = sscanf( tok, "%d", &output[i] ) ;
    tok = strchr( tok, ',' ) + 1 ;
    i++ ;

} while( tok != NULL && converted != 0 ) ;

您可以使用strtok()代替sscanf()strchr() ,但這會修改 input ,這可能是不希望的。

如果輸入是流而不是字符串,則它會更簡單:

int converted = 0 ;
int i = 0 ;
do
{
    converted = fscanf( fd, "%d,", &output[i] ) ;
    i++ ;

} while( !feof( fd ) && converted != 0 ) ;

我沒有提供任何防止output[i]超出范圍的方法-您可能也需要考慮這一點。

這是一種實現方法:

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

typedef struct
{
    int* values;
    int  count;
}
output_t;

output_t Read(char input[])
{
    int*  values = NULL;
    int   count  = 0;
    char* pch    = strtok(input,", ");

    while (pch != NULL)
    {
        values = realloc(values,(count+1)*sizeof(*values));
        values[count++] = atoi(pch);
        pch = strtok(NULL,", ");
    }

    return (output_t){values,count};
}

這是一個用法示例:

void Example()
{
    char input[] = "1 , 2 , 34, 12, 46, 100";
    output_t output = Read(input);
    for (int i=0; i<output.count; i++)
        printf("%d\n",output.values[i]);
    free(output.values);
}

這是僅進行一次通過的遞歸算法。 它在最深層進行分配,並在出口處填寫:

int *cvt(char *input, int *level)
{
    char *cp = strtok(input, ", ");
    if (cp == NULL) {
        /* No more separators */
        return (int *) malloc(sizeof(int) * *level);
    }

    int my_index = -1;
    int n;
    if (sscanf(cp, "%d", &n) == 1) {
        my_index = *level;
        *level += 1;
    } else {
        printf("Invalid integer token '%s'\n", cp);
    }
    int *array = cvt(NULL, level);
    if (my_index >= 0) {
        array[my_index] = n;
    }
    return array;
}

致電:

int main(int ac, char **av)
{
    char input[] = "1, 2, bogus, 4, 8, 22, 33, 55";
    int n_array = 0;
    int *array = cvt(input, &n_array);

    int i;
    printf("Got %d members:\n", n_array);
    for (i = 0; i < n_array; ++i)
        printf("%d ", array[i]);
    printf("\n");

    return 0;
}

我將戴上帽子,對數據進行一次傳遞。 我估計所需的數組大小是最壞的情況,其中每個數據的格式均為“ n”,因此每個數字兩個字節,然后調整大小。

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

typedef unsigned int uint32_t;

int main (void) {
    char input[] = "1 , 2 , 34, 12, 46, 100";
    uint32_t *output, *temp;
    char *tok;
    int elements = 0;
    int len = 1 + strlen(input) / 2;            // estimate max num of elements
    output = malloc(len * sizeof(*output));
    if (output == NULL)
        exit(-1);                               // memory alloc error

    tok = strtok(input, ", ");                  // parse the string
    while (tok != NULL) {
        if (elements >= len)
            exit(-2);                           // error in length assumption
        if (1 != sscanf(tok, "%u", output + elements))
            exit(-3);                           // error in string format
        elements++;
        tok = strtok(NULL, ", ");
    }

    temp = realloc(output, elements * sizeof(*output)); // resize the array
    if (temp == NULL)
        exit(-4);                               // error in reallocating memory
    output = temp;

    for (len=0; len<elements; len++)
        printf("%u ", output[len]);
    printf("\n");
    free(output);
    return 0;
}

程序輸出:

1 2 34 12 46 100

仔細閱讀該字符串,以了解如何調整數組大小:

uint32_t n = 1;
for (uint32_t idx = 0; idx < strlen(input); idx++) {
    if (input[idx] == ',') {
        n++;
    }
}

有另一種方法可以做到這一點,不需要讀取字符串,但是需要在引入新元素時調整目標數組的大小,這會使代碼更加復雜。 對於小字符串,一次讀取字符串很容易。

使目標數組:

uint32_t* output = NULL;
output = malloc(sizeof(*output) * n);
if (!output) {
    fprintf(stderr, "Error: Could not allocate space for output array!\n");
    exit(EXIT_FAILURE);
}

填充數組。 一種不破壞字符串的方法是在子字符串的開頭和結尾保持一對指針,該子字符串包含用逗號分隔的字符串中所需的數字元素,並循環遍歷字符串中的所有字符:

#define MAX_LEN 13
char* start = &input[0];
char* end = &input[0];
char entry[MAX_LEN];
uint32_t entry_idx = 0;
int finished = 0; // false
do {
    end = strchr(start, ',');
    if (!end) {
        end = input + strlen(input);
        finished = 1;
    }
    memcpy(entry, start, end - start);
    entry[end - start] = '\0';
    sscanf(entry, "%u", &output[entry_idx++]);
    start = end + 1;
} while (!finished);

MAX_LEN為13,因為uint32_t不太可能超過13位數字。 對於2100年以后生產的計算機,您可以將其設置得更長一些,以供將來使用。

完成后,請確保釋放數組:

free(output); 
output = NULL;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int getsize(char* str, char* delimiters) //give the size of the final uint32_t array[]
{
  int count = 0;
  char* st = strdup(str), *t = strtok(st, delimiters);
  while(t)
  {
    count++;
    t = strtok(NULL, delimiters);
  }
  free(st);
  return count;
}

uint32_t* Char_to_Array(char *data, char* delimiters, int *siz) //siz is a pointer to get the size of the array
{
  char* st = strdup(data), *t = NULL; //dup string, strtok mage change on the passed string
  *siz = getsize(data, delimiters);
  uint32_t* buf=(uint32_t *)malloc((*siz)*4);
  t = strtok(st, delimiters); //split string by " "
  int i = 0;
  while(t)
  {
    buf[i] = atoi(t);
    t = strtok(NULL, delimiters);
    i++;
  }
  free(st);
  return buf;
}

這是一個具有主要功能的測試

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

int main()
{
  int getsize(char* str, char* delimiters), siz = 0, i = 0;
  uint32_t* Char_to_Array(char *data, char* delimiters, int *x);
  uint32_t* t = Char_to_Array("123, 156, 4658,7878", " ,", &siz);
  while(i<siz)
  {
    printf("array[%d] = %d\n", i, t[i]);
    i++;
  }
  free(t);
  return 0;
}

2次通過方式:

1)計算逗號數並分配一個數組。

2)解析字符串-查找錯誤。

[晚於uint32逗號聚會]

#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>

typedef struct {
  uint32_t *u32;
  size_t count;
  bool error;
} CSV_32_T;

CSV_32_T CSV_to_int32_list(const char *csv) {
  CSV_32_T list = { NULL, 1, false };

  // 1st pass: Quickly go through list counting commas
  const char *p = csv;
  for (p = csv; *p; p++) {
    if (*p == ',') {
      list.count++;
    }
  }
  size_t i = 0;
  list.u32 = malloc(list.count * sizeof *list.u32);
  if (list.u32) {

    // 2nd pass: scan
    p = csv;
    for (i = 0; i < list.count; i++) {
      if (i > 0 && *p++ != ',') {
        break;
      }
      int n = 0;
      if (1 != sscanf(p, "%" SCNu32 " %n", &list.u32[i], &n)) {
        break;
      }
      p += n;
    }
  }
  if (i != list.count || *p) {
    free(list.u32);
    return (CSV_32_T ) { NULL, 0, true } ;
  }
  return list;
}

void testCSV(const char *csv) {
  CSV_32_T y = CSV_to_int32_list(csv);
  printf("%d %zu \"%s\"\n", y.error, y.count, csv);
}

int main(void) {
  testCSV("1 , 2 , 34, 12, 46, 100");
  testCSV("1  2 , 34, 12, 46, 100");
  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM