在C中写入字符串数组中的值

时间:2017-10-27 05:41:03

标签: c arrays

#include <string.h>
#include <stdio.h>
int main(void) 
{
    char a[1000][30];
    int nr = 0;
    char temp[30];

    printf ("Nr  magaz: ");
    scanf ("%d", &nr);

    for(int i = 0; i < nr; i++)
    {
        printf("Magazin nr: %d", &i);
        do {
            scanf("%[^\n]s", temp);
        }
        while (temp == !"\0");
        printf("\n");
        strcpy(a[i],temp);
    }
    printf("%s",a[0]);
    return 1;
}

https://onlinegdb.com/BkHXPSlCZ

我想在矩阵中存储一些值并打印它们,但输出中的值有错误 首先,输入保留矩阵的值,然后分别输入每个值。
 但在第2部分中,不可能引入这些值并且程序打印随机数

3 个答案:

答案 0 :(得分:1)

您有许多问题导致未定义的行为,而您的有趣数字来自于尝试将i的地址(例如&i)打印为十进制整数值为"%d"

在进行更正之前,让我们从一些基础知识开始。如果您需要常量(例如301000),则#declare MAXC 30表示最大字符,并对最大行执行相同的#declare MAXL 1000或使用enum进行操作一次性,例如

enum { MAXC = 30, MAXL = 1000 };    /* declare constants */

这样一来,如果你需要调整这些值,你可以在你的源代码顶部找到一个方便的位置 - 而不需要选择所有声明,循环变量等来进行更改。

初始化您打算用于存储字符串的数组也是一个好主意,以避免无意中失败 nul-terminate ,例如

    char a[MAXL][MAXC] = {""};
    char temp[MAXC] = "";

(初始化所有变量是个好主意)

接下来,您可以做的最重要的事情是 验证所有用户输入 (实际所有输入) 。如果您没有验证您实际收到了您期望的输入,并且收到的值在您的程序可用的范围内,您可以不相信您将不会在使用该输入的下一个语句上调用未定义的行为(据你所知,猫可能会踩到键盘上)。要验证输入,请始终检查输入函数的 return ,然后验证该值是否在所需范围内,例如

    printf ("Introdu nr. magazine vizitate (1-1000): ");
    if (scanf ("%d", &nr) != 1) {   /* validate ALL user input */
        fprintf (stderr, "error: invalid input.\n");
        return 1;   /* returning 1 to shell indicates EXIT_FAILURE */
    }
    if (nr < 1 || nr > 1000) {   /* validate nr in range */
        fprintf (stderr, "error: value out of range.\n");
        return 1;
    }

do ... while (...)之外,您不需要for来接受输入并填充a。您可以使用for循环完成所有操作,例如

    /* prompt, get input, validate, copy temp to 'a' */
    for (int i = 0; i < nr; i++) {
        printf ("Magazin nr [%2d]: ", i);
        /* protect against buffer overrun with field-width */
        if (scanf(" %29[^\n]", temp) != 1) {  /* catch EOF */
            fprintf (stderr, "error: user canceled input.\n");
            return 1;
        }
        strcpy (a[i],temp);
    }

(在复制到您的阵列之前,您确实在阅读temp时作出了明智的决定,以便在复制之前进行单独验证。)

注意:在space使用前导空格之前%如何消失(例如,按 Enter <{1}} '\n'条目的kbd>以及 field-width 修饰符到nr格式说明符的用法如何将输入限制为不超过%[..]个字符(为 nul-terminated 字符节省空间)以确保您的输入实际上适合29,例如

a[i]

现在所有值都安全地存储在 scanf(" %29[^\n]", temp) 中,您可以随意使用它们,或者只是输出它们:

a

完全放弃,你可以做类似的事情:

    /* output stored strings in 'a' */
    for (int i = 0; i < nr; i++)
        printf ("a[%2d] : '%s'\n", i, a[i]);

示例使用/输出

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

enum { MAXC = 30, MAXL = 1000 };    /* declare constants */

int main (void) 
{
    char a[MAXL][MAXC] = {""};
    char temp[MAXC] = "";
    int nr = 0;

    printf ("Introdu nr. magazine vizitate (1-1000): ");
    if (scanf ("%d", &nr) != 1) {   /* validate ALL user input */
        fprintf (stderr, "error: invalid input.\n");
        return 1;   /* returning 1 to shell indicates EXIT_FAILURE */
    }
    if (nr < 1 || nr > 1000) {   /* validate nr in range */
        fprintf (stderr, "error: value out of range.\n");
        return 1;
    }

    /* prompt, get input, validate, copy temp to 'a' */
    for (int i = 0; i < nr; i++) {
        printf ("Magazin nr [%2d]: ", i);
        /* protect against buffer overrun with field-width */
        if (scanf(" %29[^\n]", temp) != 1) {  /* catch EOF */
            fprintf (stderr, "error: user canceled input.\n");
            return 1;
        }
        strcpy (a[i],temp);
    }

    /* output stored strings in 'a' */
    for (int i = 0; i < nr; i++)
        printf ("a[%2d] : '%s'\n", i, a[i]);

    return 0;   /* returning 0 indicates EXIT_SUCCESS */
}

处理错误:

$ ./bin/scanfstring
Introdu nr. magazine vizitate (1-1000): 5
Magazin nr [ 0]: My favorite
Magazin nr [ 1]: magazine is
Magazin nr [ 2]: one with good
Magazin nr [ 3]: articles and
Magazin nr [ 4]: commentary.
a[ 0] : 'My favorite'
a[ 1] : 'magazine is'
a[ 2] : 'one with good'
a[ 3] : 'articles and'
a[ 4] : 'commentary.'

那就是说,$ ./bin/scanfstring Introdu nr. magazine vizitate (1-1000): ten error: invalid input. $ ./bin/scanfstring Introdu nr. magazine vizitate (1-1000): 1001 error: value out of range. 包含许多陷阱,等待陷入新的(而不是那么新的)C程序员。在获取用户输入时,面向行的函数(如scanf或POSIX fgets)更不容易导致细微错误(您只需要记住修剪尾随{{1每个人都填入缓冲区中。)

您还有一个额外的情况需要防范。如果用户输入的字符串超过getline个字符,该怎么办?实际上,'\n'将读取29并将其余内容保留在输入缓冲区scanf)中。结果是剩余的字符将作为下一个输入的一部分被读取。如果下一个输入是整数或浮点值,则可能导致匹配失败。为了防止用户输入超过适合的值,您需要一种方法来检查您是否已读取整个字符串。

使用29,您无法轻松确认已阅读整行输入。您始终可以放弃使用stdin阅读的任何剩余字符,直到达到scanfgetchar(),但这也有问题。使用'\n'EOF,您只需检查最终字符读取是fgets。如果不是,您知道其他字符仍然未读。这只是使用面向行的输入函数的优势之一。

仔细看看,如果您有其他问题,请告诉我。

答案 1 :(得分:0)

设定库存的数量:ok
分别输入每个velue:ok
那是你想做的吗?

 int main (void)
{
  char a[1000][30];
  int nr = 0;
  char temp[30];

  printf ("Introdu nr. magazine vizitate: ");
  scanf ("%d", &nr);

  for (int i = 0; i < nr; i++)
    {
      printf ("Magazin nr: %d\n", i);
      scanf ("%s", &temp); //fill a temporary array
      strcpy (a[i], temp); //copy the content of the array into the tab of array
      printf ("temp:%s ||| a[i]:%s\n", temp, a[i]);
    }
  printf ("%s\n", a[0]);
  return (0);
}

我尝试修改您的实际代码的可能性越小。

答案 2 :(得分:0)

您的计划中几乎没有问题。

首先:

printf("Magazin nr: %d", &i);

printf不需要&变量。将其更改为:

printf("Magazin nr: %d", i);

第二

while (temp == !"\0");

您不需要循环来使用scanf将字符串作为输入。

第三

scanf("%[^\n]s", temp);

由于之前的scanf,此scanf将使用输入缓冲区中留下的换行符。将其更改为:

scanf("% [^\n]s", temp);

通过这些更改,程序将如下所示:

#include <string.h>
#include <stdio.h>
int main(void)
{
    char a[1000][30];
    int nr = 0;
    char temp[30];

    printf ("Introdu nr. magazine vizitate: ");
    scanf ("%d", &nr);

    for(int i = 0; i < nr; i++)
    {
        scanf(" %[^\n]s", temp);
        printf("Magazin nr: %d\n", i);
        strcpy(a[i],temp);
    }
    //printing strings
    for (int i = 0; i < nr; i++)
    {
        printf("%s\n",a[i]);
    }
    return 0;
}

一个建议 - 最好使用fgets代替scanf进行字符串输入。