繁体   English   中英

c - 如何在c中的字符串数组中排列逗号分隔的字符串?

[英]How to arrange comma separated string in Arrays of String in c?

我正在编写一个C程序,它将解析字符串数组中逗号分隔的字符串。

我已经尝试过打印逗号分隔字符串的源代码。 但我希望将这些字符串存储在一个字符串数组中。 以下代码使用strcspn并使用以下行

printf("%.*s\n", (int)field_len, s);

打印我无法理解的字符串。 如何在字符串数组中传输打印的字符串?

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

char ArrayOfString[10][5];

void vSeparateSringByComma(char* string)
  {
    const char delims[] = ",";
    const char *s = string;
    int i = 0, j;
    do 
      {
        size_t field_len = strcspn(s, delims);
        printf("%.*s\n", (int)field_len, s);
        s += field_len;
        i++;
      } 

    while (*s++);   
   }

int main() {
    char string[] = "$,0,3,307,183,18,5,119,1,#";
    vSeparateSringByComma(string);
}

我得到的输出是

$
0
3
307
183
18
5
119
1
#

(在每个字符串之后都有一个换行符)这很好。 我的问题是将这些字符串转移到我的字符串数组中。

有什么建议?

您有几个问题需要解决,以将您的函数从简单地将分离的字符串打印到stdout转换为将分离的字符串保存在ArrayOfString 在进行更改之前,让我们避免在代码中使用幻数

char ArrayOfString[10][5];

在上面的ArrayOfString105幻数 它们是硬编码的值,将控制从声明大小到所需的验证检查以保护数组边界的所有内容。 如果你需要一个常量,而不是硬编码值,定义一个(或多个),例如

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

#define ROW 10
#define COL  5

char ArrayOfString[ROW][COL];

现在将您的字符串分离成tokens C 库提供了一个专门用于将分隔字符串分离为标记的函数。 方便地命名为strtok 关于strtok的唯一警告是它会修改字符串,因此如果您需要保留原件,请先制作一个副本。

要使用strtok (string, delims)string分隔为delims标记,您对strtok的第一次调用将string作为第一个参数。 所有后续调用都使用NULL代替。 您可以对strtok进行初始调用,然后使用 while 循环来完成该过程,或者为处理初始调用以及所有后续调用而定制的for循环NULL

例如,您的函数利用strtokstring分成标记并提供复制到ArrayOfString的标记数量的size_t返回可能类似于:

char ArrayOfString[ROW][COL];

size_t vSeparateSringByComma (char* string)
{
    const char *delims = ",\n";
    char *s = string;
    size_t n = 0, len;

    for (s = strtok (s, delims); s && n < ROW; s = strtok (NULL, delims))
        if ((len = strlen (s)) < COL)
            strcpy (ArrayOfString[n++], s);
        else
            fprintf (stderr, "error: '%s' exceeds COL - 1 chars.\n", s);

    return n;
}

注意:在复制到ArrayOfString[n++]之前,您的数组边界如何通过n < ROW的检查得到保护,并且每个行数组边界都受到(len = strlen (s)) < COL保护)

另请注意:如何通过不使用幻数,如果您将来更改ROWCOL大小,仅需要更改常量,并且通过使用常量,更改会自动合并到您的代码中)

您的示例程序将是:

int main(void) {

    char string[] = "$,0,3,307,183,18,5,119,1,#";
    size_t n = vSeparateSringByComma (string);

    for (size_t i = 0; i < n; i++)
        printf ("ArrayOfString[%zu] : '%s'\n", i, ArrayOfString[i]);
}

示例使用/输出

$ ./bin/arrayofstrings
ArrayOfString[0] : '$'
ArrayOfString[1] : '0'
ArrayOfString[2] : '3'
ArrayOfString[3] : '307'
ArrayOfString[4] : '183'
ArrayOfString[5] : '18'
ArrayOfString[6] : '5'
ArrayOfString[7] : '119'
ArrayOfString[8] : '1'
ArrayOfString[9] : '#'

使用strcspnstrspn代替strtok

正如评论中所讨论的,使用strcspn报告不包含分隔符的连续字符数,允许您确定每个字段的长度。 然后您需要跳过分隔符(在许多情况下,分隔符可以由多个分隔符组成(例如$, 0, 3, ... )。

虽然strtok将多个连续分隔符视为单个分隔符,但您需要一种类似的方法来跳过中间的分隔符以定位自己以读取下一个字段。 strspn将使用相同的delims很好地工作,但这次报告仅由delims的字符组成的字符数(允许您将其添加到您的len然后将lens以定位自己以备下次阅读)

使用strcspnstrspn简短变体可能是:

size_t vSeperateSringByComma (char* string)
{
    const char *delims = ",\n";
    char *s = string;
    size_t n = 0, len;

    while ((len = strcspn (s, delims))) {   /* number of non-delim chars */
        if (len < COL) {                    /* validate it will fit */
            memcpy (ArrayOfString[n], s, len);  /* copy len chars */
            ArrayOfString[n++][len] = 0;    /* nul terminate at len */
        }
        else
            fprintf (stderr, "error: '%s' exceeds COL - 1 chars.\n", s);

        len += strspn (s + len, delims);    /* scan past delimiter(s) */
        s += len;               /* update s to beginning of next field */
    }

    return n;
}

(输出是一样的)

仔细检查一下,如果您还有其他问题,请告诉我。

代替

printf("%.*s\n", (int)field_len, s);

sprintf(ArrayOfString[i],"%.*s\n", (int)field_len, s);

然后你可以打印 4 个第一个元素

for( i=0 ; i<4 ; i++)
   printf("%s" , ArrayOfString[i] );

我已经了解了标准函数strtok()strcspn()并且我发布了解决方案的两个版本。

使用 strtok()

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

#define ROW  10
#define COL  30

char ArrayOfString[ROW][COL];

size_t vSeperateSringByComma_New(char* string, char *delims)
{
  char *p;
  p = strtok (string,delims);
  int i = 0,j;
  while (p!= NULL)
  {
    strcpy(ArrayOfString[++i], p);
    p = strtok (NULL, delims);
  }
  return i;
}

int main ()
{
  char string[] ="$,0,3,307,183,18,5,119,1,#";
  char delim[] = ",:";
  printf ("String  \"%s\" is split into tokens:\n",string);
  size_t len = vSeperateSringByComma_New (string, delim);
  int i;
  for (i = 0; i < len+1; i++)   {
    printf ("%s\n",ArrayOfString[i]);
  }
  return 0;
}

使用 strcspn()

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

#define ROW  10
#define COL  30

char ArrayOfString[ROW][COL];

size_t vSeperateSringByComma(char* string, char *delims)
{
    const char *s = string;
    int i = 0;
    do {
        size_t field_len = strcspn(s, delims);
        sprintf(ArrayOfString[++i],"%.*s", (int)field_len, s);
        s += field_len;
    } while (*s++); 
    return i; 
}

int main() {
    char string[] = "$,0,3,307,183,18,5,119,1,#";
    char delims[] = ",";
    printf ("String  \"%s\" is split into tokens:\n",string);
    int len = vSeperateSringByComma(string, delims);
    int i;
    for (i = 0; i < len+1; i++) {
        printf ("%s\n",ArrayOfString[i]);
    }
}

谢谢你的建议

使用 strncpy() 将您的值放入数组。 这个char *strncpy(char *dest, const char *src, size_t n)从 src 指向的字符串中复制最多 n 个字符到 dest。

do
{
    size_t field_len = strcspn(str, delims);
    printf("%.*s\n", (int)field_len, str);
    strncpy (ArrayOfString[cnt++], str, (int)field_len);
    str += field_len;
    i++;
} while (*str++);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM