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

时间:2019-01-23 22:16:20

标签: c string matrix

我正在编写一个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
#

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

有什么建议吗?

4 个答案:

答案 0 :(得分:3)

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

char ArrayOfString[10][5];

在上面的ArrayOfString中,105魔术数字。它们是硬编码的值,它将控制所有内容,从声明大小到必需的验证检查,以保护数组范围。如果您需要一个常数,则可以使用一个(或多个)值来代替对值进行硬编码,例如

#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循环来处理初始调用以及所有后续的{{ 1}}。

例如,您使用NULLstrtok分离为令牌并提供string返回的复制到size_t的令牌数量的函数可能类似于:

ArrayOfString

注意:如何在复制到{{1}之前通过用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; } 进行检查来保护数组边界以及如何用n < ROW保护每个行数组边界})

也请注意::如果不将来更改(len = strlen (s)) < COLArrayOfString[n++]的大小,那么不使用魔术数字的方式,常量需要更改,并且通过使用常量,该更改会自动并入整个代码中

您的示例程序将是:

ROW

使用/输出示例

COL

使用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] : '#' 代替strcspn

如评论中所述,使用strspn报告不包含定界符的连续字符数,从而可以确定每个字段的长度。然后,您需要跳过定界符(在许多情况下,定界符可以由多个定界符组成(例如strtok)。

尽管strcspn将多个顺序定界符视为一个定界符,但您将需要一种类似的方法来跳过中间的定界符,以定位自己的位置以读取下一个字段。 $, 0, 3, ...在使用相同的strtok时可以很好地工作,但是这次报告的字符数仅由strspn中的字符组成(允许您将其添加到delims和然后从delimslen进行下一次阅读)

使用lens的简短变化可能是:

strcspn

(输出相同)

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

答案 1 :(得分:1)

替换

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

使用

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

然后您可以使用打印第四个元素

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

答案 2 :(得分:0)

我已经了解了标准功能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]);
    }
}

感谢您的建议

答案 3 :(得分:0)

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

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++);