在C中将字符串输入存储到不同的数组中

时间:2017-09-24 20:50:29

标签: c arrays string char

你好C上的这个全新的菜鸟试图取3个字的字符串输入并将其存储在3个不同的阵列上,而不是2D或3D阵列。对于这个问题,我不允许使用任何字符串库函数。基本上我正在尝试实现sscanf功能。我创建了一个函数,将输入分解为三个单词,并将它们存储在指定的数组中。我的问题是当我尝试打印每个数组时,对于我的第二个数组,我无法打印出我试图存储在其中的单词。我可能没有存储任何东西,但我找不到我的错误。这就是我的......

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


void breakUp(char *, char *, char *, char *, int* );
int main()
{
 char line[80], comm[10], p1[10], p2[10];
 int len, n=0;

 printf("Please Enter a command: ");

 fgets(line, 80, stdin);

/* get rid of trailing newline character */
len = strlen(line) - 1;
if (line[len] == '\n')
    line[len] = '\0';

/* Break up the line */
breakUp(line, comm, p1, p2, &n);

printf ("%d things on this line\n", n);
printf ("command: %s\n", comm);
printf ("parameter 1: %s\n", p1);
printf ("parameter 2: %s\n", p2);

return 0;
}

/*
 This function takes a line and breaks it into words.
The orginal line is in the char array str, the first word
will go into the char array c, the second into p1, and the
the third into p2.  If there are no words, the corresponding
char arrays are empty.  At the end, n contains the number of
words read.
*/
void breakUp(char *str, char *c, char *p1, char *p2, int* n)
{
c[0] = p1[0] = p2[0] = '\0';
p1[0] = '\0';
int j = 0; // str array index
int i = 0; // index of rest of the arrays
n[0] = 0;

// stores first word in array c
while(str[j]!= ' '|| str[j] == '\0')
  {
      c[i]= str[j];
      i++;
      j++;
  }
// increases n count, moves j into next element
// and sets i back to index 0
if (str[j] == ' '|| str[j] == '\0')
  {
     c[i] = '\0';
      n[0]++;
      j++;
      i =0;
      if( str[j] == '\0')
          return;
  }

// stores second word in array p1
while(str[j]!= ' '|| str[j] == '\0')
{
    p1[i]= str[j];
    i++;
    j++;
}
// increases n count, moves j into next element
// and sets i back to index 0
if (str[j] == ' '|| str[j] == '\0')
{
    p1[i] = '\0';
    n[0]++;
    j++;
    i =0;
    if( str[j] == '\0')
        return;
}

// stores 3rd word in array p2
while(str[j] != ' ' || str[j] == '\0')
  {
      p2[i] = str[j];
      i++;
      j++;
  }
// increases n count, moves j into next element
// and sets i back to index 0
if(str[j] == ' ' || str[j] == '\0')
  {
      p2[i] = '\0';
      n[0]++;
      if( str[j] == '\0')
          return;

  }


}

如果有任何帮助,请高级谢谢

2 个答案:

答案 0 :(得分:0)

while(str[j]!= ' '|| str[j] == '\0')

应该是

while(str[j]!= ' '&& str[j]!= '\0')

if语句检查是否到达行尾。谢谢。

答案 1 :(得分:0)

除了评论和答案之外,还有一些方面可能会使您自己的事情变得比他们需要的更难。首先让我们看一下breakup的回归。你为什么使用void?如果您需要能够评估函数的成功/失败,请选择一个有意义的返回类型来提供该信息。这里只需返回int即可(并且还可以防止必须将指针传递给n进行更新 - 您只需返回n)您可以自由地传递指针n,请注意,在调用breakup 时,它不能用于提供成功/失败信息。返回n即可。

注意: breakup全部小写 - 将 camelCase 变量留给java和C ++,C传统上使用保留全部大写的所有小写变量和函数名称对于常量和宏)

其次,请避免在代码中使用幻数(例如8010等。)。如果需要常量,则在顶部#define,或使用enum定义全局常量。这样,您可以在文件顶部有一个方便的位置进行调整,如果需要更改数组大小等,则不必通过每个字符数组声明来更改幻数,例如,要定义单词数,命令数组长度和行缓冲区长度,你可以简单地做到:

#define NWRD 3      /* number of words */
#define CLEN 16     /* command length  */
#define LLEN 80     /* line buffer len */

或使用枚举:

enum { NWRD = 3, CLEN = 16, LLEN = 80 };    /* constants */

现在对于breakup的内容,您可以自由复制代码块以便分别读取每个单词3次,但您可以更聪明地了解它并意识到您已经将指针传递给3个字符数组到breakup,为什么不只是使用指针数组初始化为{ c, p1, p2 }然后只编写一个代码块来从str中挑选出每个单词?它可以说只是一种较短的 skinning-the-cat 方式。这样,您就可以简单地循环c, p1, p2arr[0], arr[1], arr[2],而不必引用arr[0] = c, arr[1] = p1, arr[2] = p2;

例如,您的新breakup声明为:

int breakup (char *str, char *c, char *p1, char *p2);

breakup内你可以按如下方式分配指针数组:

    char *arr[] = { c, p1, p2 };

然后,您只需将第一个单词中的所有字符添加到arr[0],将第二个字符中的所有字符添加到arr[1],依此类推,然后填充c, p1, p2。这看起来像是可以在一个很好的单循环中处理的东西......

现在你需要做的就是找出一种方法来为每个单词添加每个字符,检查空格(或多个空格和制表符),确保你 nul-terminate 每个单词,确保你只填写三个单词 - 而不是更多,最后返回你填写的单词数。

如果不对每个点进行说明,您可以将breakup缩短为以下内容:

int breakup (char *str, char *c, char *p1, char *p2)
{
    char *arr[] = { c, p1, p2 };            /* assign c, p1, p2 to arr */
    int cidx = 0, n = 0;                    /* character index & n */

    for (; n < NWRD; str++) {               /* loop each char while n < NWRD */
        if (*str == ' ' || *str == '\t') {  /* have space or tab? */
            if (*arr[n]) {                  /* have chars in arr[n]? */
                arr[n++][cidx] = 0;         /* nul-terminate arr[n] */
                cidx = 0;                   /* zero char index */
            }
        }
        else if (*str == '\n' || !*str) {   /* reached '\n' or end of str? */
            arr[n++][cidx] = 0;             /* nul-terminate arr[n] */
            break;                          /* bail */
        }
        else
            arr[n][cidx++] = *str;          /* assign char to arr[n] */
    }

    return n;
}

注意: breakup测试每个单词中的第一个字符,以确定您是否已开始填写单词(允许您跳过多个空格或标签),因此您需要确保您初始化main中的所有字符串,或者您也可以在breakup的顶部执行此操作。在main中,您可以在声明字符数组时简单地初始化它们,例如

    char line[LLEN] = "", comm[CLEN] = "", p1[CLEN] = "", p2[CLEN] = "";

注意:在声明它们时初始化所有变量是个好习惯。)

您可能还希望在阅读line时添加一些其他验证,以确保在将其传递给breakup之前不会为空。您只需在line读取fgets时添加验证就可以做到这一点,例如:

    printf ("please enter a command: ");    /* prompt & get line */
    if (!fgets (line, LLEN, stdin) || !*line || *line == '\n') {
        fprintf (stderr, "error: input empty or user canceled.\n");
        return 1;
    }

检查行中的第一个字符是不是 nul-character (空字符串)还是第一个字符是'\n'(空行)。

在一个简短的例子中,你可以做如下的事情:

#include <stdio.h>

enum { NWRD = 3, CLEN = 16, LLEN = 80 };    /* constants */

int breakup (char *str, char *c, char *p1, char *p2)
{
    char *arr[] = { c, p1, p2 };            /* assign c, p1, p2 to arr */
    int cidx = 0, n = 0;                    /* character index & n */

    for (; n < NWRD; str++) {               /* loop each char while n < NWRD */
        if (*str == ' ' || *str == '\t') {  /* have space or tab? */
            if (*arr[n]) {                  /* have chars in arr[n]? */
                arr[n++][cidx] = 0;         /* nul-terminate arr[n] */
                cidx = 0;                   /* zero char index */
            }
        }
        else if (*str == '\n' || !*str) {   /* reached '\n' or end of str? */
            arr[n++][cidx] = 0;             /* nul-terminate arr[n] */
            break;                          /* bail */
        }
        else
            arr[n][cidx++] = *str;          /* assign char to arr[n] */
    }

    return n;
}

int main (void) {

    char line[LLEN] = "", comm[CLEN] = "", p1[CLEN] = "", p2[CLEN] = "";
    int n = 0;

    printf ("please enter a command: ");    /* prompt & get line */
    if (!fgets (line, LLEN, stdin) || !*line || *line == '\n') {
        fprintf (stderr, "error: input empty or user canceled.\n");
        return 1;
    }

    if ((n = breakup (line, comm, p1, p2)) != NWRD) {   /* call breakup */
        fprintf (stderr, "error: %d words found\n", n);
        return 1;
    }

    printf ("command    : %s\nparameter 1: %s\nparameter 2: %s\n",
            comm, p1, p2);

    return 0;
}

示例使用/输出

$ ./bin/breakup
please enter a command: dogs have fleas
command    : dogs
parameter 1: have
parameter 2: fleas

$ ./bin/breakup
please enter a command: dogs have
error: 2 words found

$ ./bin/breakup
please enter a command: dogs have lots of fleas
command    : dogs
parameter 1: have
parameter 2: lots

$ ./bin/breakup
please enter a command: dogs    have       fleas   for    sale
command    : dogs
parameter 1: have
parameter 2: fleas

仔细检查并确保您了解正在发生的事情。是新的。 指针数组 char *arr[] = { c, p1, p2 };可能让你摸不着头脑,但它只是创建3个指针arr[0], arr[1], arr[2]并分配arr[0] = c; arr[1] = p1, arr[2] = p2;(就像你想的那样)使用任何指针,比如char *p = c,只有你使用arr[0]而不是p来允许自己遍历每个指针。

除此之外,它都是相当基本的。但是现在是时候提出问题,以确保你明白这一点。