将多个字符串作为输入时,不必要的新行字符

时间:2016-11-28 04:29:29

标签: c string malloc newline

我编写了一个小代码,可以将多个字符串作为用户的输入。在此之前,我要求用户输入要作为输入的字符串数。在将字符串作为输入时,新行字符会自动占据第一个字符串的位置。我不知道发生了什么:(这是我的代码:

#include<stdio.h>
#include<string.h>
void main()
{
    char *arr[20],str[40];
    int n;
    printf("enter the number of strings\n");
    scanf("%d",&n);
    int i;
    printf("Enter the strings\n");[It isn't taking 3 strings as input,as a newline character is already occupying first place][1]
    for(i=0;i<n;i++)
    {
        gets(str);
        arr[i]=(char *)malloc(sizeof str);
        strcpy(arr[i],str);
    }
    printf("The Strings are:\n");
    for(i=0;i<n;i++)
    {
        printf(arr[i]);
        printf("\n");
    }
}

3 个答案:

答案 0 :(得分:1)

在评论之后,您的代码中存在许多问题。首先gets,不要使用它,这是一个“悬挂”的进攻 - 足够说。

接下来,验证所有用户输入。如你所知,一只猫可能正踩在键盘上。确保测试您收到的输入内容,并将其与您期望的内容相匹配。

scanf面向行的输入混合(例如fgetsgetline可能会给新用户带来问题。为什么?scanf家庭函数不会删除'\n'而是将其留在输入缓冲区中(例如stdin)。然后当您尝试使用fgets读取它在stdin中看到的第一个字符时是什么?一个'\n',它读取并考虑整行。如果您打算使用scanf来读取字符串的数量,则由您删除{{1} } '\n'留在scanf

这并不难,您实际上只需在格式字符串中使用stdin提供的赋值抑制运算符。 E.g:

scanf

scanf ("%d%*c", &n); 是分配抑制运算符,当与*一起使用时,只需告诉%*c 读取并丢弃下一个字符而不添加到 scanf(例如match count返回的内容。)

填充数组时,您需要使用scanf循环而不是while循环(或使用独立索引)。为什么?如果用户使用 ctrl + d (或在windoze上 ctrl + z )取消输入,该怎么办?如果您正在迭代到for而不管用户做了什么,您可以轻松地尝试索引尚未分配的数组元素,或者为未输入的字符串分配。

完全放弃,你可以这样做:

n

示例使用/输出

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

enum { MAXA = 20, MAXS = 40 }; /* max ptrs and str */

int main (void) {

    char *arr[MAXA] = {NULL}, str[MAXS] = "";
    int i = 0, n = 0, ndx = 0;   /* initialize all variables */

    printf ("enter the number of strings: ");
    /* use assignment suppression %*c to discard the \n */
    if (scanf ("%d%*c", &n) != 1) { /* always validate input */
        fprintf (stderr, "error: invalid integer input.\n");
        return 1;
    }

    if (n > MAXA) { /* validate the value of n */
        fprintf (stderr, "warning: n > %d, using %d as limit.\n",
                MAXA, MAXA);
        n = MAXA;
    }

    printf("Enter the strings\n");
    while (ndx < n && fgets (str, sizeof str, stdin)) { /* validate input */
        size_t len = strlen (str); /* get the length */
        if (str[len - 1] == '\n')  /* check for '\n' */
            str[--len] = 0;        /* overwrite with nul-terminator */
        if (!(arr[ndx] = malloc (len + 1))) { /* validate allocation */
            fprintf (stderr, "error: virtual memory exhausted.\n");
            break;
        }
        strcpy (arr[ndx], str);   /* copy to array */
        ndx++;                    /* increment index */
    }

    printf("\nThe Strings are:\n");

    for (i = 0; i < ndx; i++) {  /* you have ndx strings not n */
        printf (" arr[%2d] : %s\n", i, arr[i]);
        free (arr[i]);  /* free memory when no longer needed */
    }

    return 0;
}

现在尝试相同的事情并按 ctrl + d 而不是输入$ ./bin/nogets enter the number of strings: 3 Enter the strings My dog has a lot of fleas. The Strings are: arr[ 0] : My dog arr[ 1] : has a lot arr[ 2] : of fleas. (你被覆盖)。

最后,在您动态分配内存的任何代码中,对于分配的任何内存块,您有2个职责:(1)始终保留指向起始地址的指针对于内存块,(2)当不再需要时,它可以释放。养成跟踪你分配的内存的习惯,并"of fleas."而不是依赖于free上的内存。随着您的计划变得更加复杂,这将对您有所帮助。

查看代码,确保您了解正在发生的事情。如果您有任何问题,请告诉我。

答案 1 :(得分:0)

当您使用scanf读取位数时,它只处理输入的数字,而不是输入数字后输入的数字。

可能值得同时刷新其余输入,例如 How to clear input buffer in C?

答案 2 :(得分:0)

gets()函数必须将标准输入流stdin中的字节读入s指向的数组,直到读取<newline>或遇到文件结束条件。

所以每当你进入

之后
  

输入字符串数

     

5

因此,如果按Enter键,则gets被调用,它将新行作为第一个输入。

如果您没有输入输入并按下5abc然后输入那么它会将abc视为第一个字符串。

您需要在gets之前清除缓冲区。

您的正确程序是

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
{
        char *arr[20],str[40];
        int n;
        int ch;
        printf("enter the number of strings\n");
        scanf("%d",&n);
        int i;
        printf("Enter the strings\n");
        //flush the input stream
        while ((ch = getchar()) != '\n' && ch != EOF);
        for(i=0;i<n;i++)
        {
                gets(str);
                arr[i]=(char *)malloc(sizeof str);
                strcpy(arr[i],str);
        }
        printf("The Strings are:\n");
        for(i=0;i<n;i++)
        {
                printf("%s",arr[i]);
                printf("\n");
        }
}