【问题标题】:Scanf and two stringsScanf 和两个字符串
【发布时间】:2012-04-26 23:54:27
【问题描述】:

我的任务是读取两个数字字符串并将它们保存在不同的数组中。 我决定使用 scanf 函数,但程序只能读取第一个字符串。 这是我的错误代码。

int main()
{

    int firstArray[50], secondArray[50], i, j;

    /* fill an array with 0 */
    for(i=0; i<50; ++i)
    {
        firstArray[i]=secondArray[i]=0;
    }

    i=j=0;

    while((scanf("%d", &firstArray[i]))== 1) { ++i; }
    while((scanf("%d", &secondArray[j]))== 1) { ++j; }

    /* Print this. */
    for(i = 0; i < 20; ++i)
    {
        printf("%d ", firstArray[i]);
    }
    putchar('\n');

    for(j = 0; j < 20; ++j)
    {
        printf("%d ", secondArray[j]);
    }

    return 0;
}

我只是不明白 scanf 函数是如何工作的。谁能解释一下?

【问题讨论】:

  • scanf 的输入是什么样的?
  • #first line 123 54 34 54 3455 [行尾;或\n]。而#second 行也是一样的/
  • @user1334306 现在才阅读此评论,将更新我的答案!

标签: c input


【解决方案1】:

其实C的数组有一个特殊点。

虽然你声明了一个数组的大小。比如int arr[5]; 你可以存储超过5大小的值。它不会显示任何错误,但会导致未定义的行为(可能会覆盖其他变量)。

请参考这个问题:Array size less than the no. of elements stored in it

在你的情况下,那是你的问题。编译器从未超过第一个 while 语句。因此,您没有得到任何输出。事实上,它甚至还没有编译整个代码!

while((scanf("%d", &amp;firstArray[i]))== 1) { ++i; }

所以,你可以这样写这个while语句:

while(  scanf("%d", &firstArray[i]) ==1 && i<50 )  
    i++;

否则:

while(i<50 )
{
        scanf("%d", &firstArray[i]);             
        i++;
}

否则:

for (i=0; i<50; i++)
    scanf("%d", &firstArray[i]);

【讨论】:

  • 你的例子是错误的。您将数组的指针与1 进行比较。此外,即使没有读取数字,您也会增加 i。如果阅读项目!= 1,您的第二个和第三个示例永远不会中断。
  • @Rune 现在看看他们!实际上,我只是从他写的内容中复制并忘记删除那些..
  • 更好,但是在最后两个示例中,您没有验证读取,并且如果有其他内容,则模式不会改变,然后是空白(空格,制表符,换行符),您继续尝试阅读但永远不要走得更远。即,如果您输入了1 4 8; 3 6 5,您将在 firstArray[0]、[1] 和 [2] 中读取 1,4 和 8 - 然后尝试读取下一个数字,直到 i 为 50 - 但下一个字符是 ;你永远不会进步。
【解决方案2】:

您不能使用scanf 来执行此操作。

阅读documentation

观察:

  1. scanf 如果您输入一个数字,您的循环将永远运行
  2. 没有检查数组的大小限制为 50
  3. 如果您按return,则它会忽略该行,因为与您的模式不匹配
  4. 如果您输入一个字母,则模式不匹配并且循环中断

所以使用其他函数,可能是getsatoistrtol。并记得检查数组的大小限制为 50。

【讨论】:

  • 如果输入数字,scanf 将不会永远运行,他将读取该数字,如果下一次读取的不是数字或空白,则中断 while 循环。一封信不会导致异常。它根本不会被读取,并且两个 while 循环都将终止。
  • 如果不是数字,你有一个错误,如果你输入空白,它会跳过该行并继续循环。试试看。
  • 如果它是不是数字不是空白,它会中断while循环。如果它不是一个数字,它将 not 是一个错误。他检查 scanf 是否导致 1 个读取项。因此,如果存在非空白或非数字,则 scanf 将返回 0 并且 while 循环中断。不是异常或错误。
  • @Rune sorry with error 我的意思是 scanf 失败,并且永远运行我的意思是如果他输入一个数字,他的循环条件总是正确的,在 50 个元素之后也是如此。
【解决方案3】:

你说一串数字,你读到%d。该格式扫描输入以查找表示整数(有符号)值的最长序列。第一个 while 循环消耗了两个“数字字符串”。

编辑你应该说“整数字符串”而不是“数字字符串”。在这种情况下,它有点微妙,因为第一个 while 可以消耗所有整数,除非它们被不是可能的整数(例如;)分隔。

因此,要使以下内容起作用,您必须将两个“行”与不能被解析为整数 的东西分开,这不被视为“白色字符”。不是更好的解决方案,而是一种可能的解决方案。

#include <stdio.h>
#include <ctype.h>

int main()
{

  int firstArray[50] = {0};
  int secondArray[50] = {0};
  int i, j, l1, l2;
  int tmp;

  i = j = 0;

  // read integers, but not more than size of array
  while( scanf("%d", &firstArray[i]) == 1 && i < sizeof(firstArray) ) { 
    ++i; 
  }

  // consume non digits
  for(tmp = getchar(); tmp != EOF && !isdigit(tmp); tmp = getchar());
  // on EOF you should exit and stop processing;
  // we read one more char, push it back if it was a digit
  if (isdigit(tmp)) ungetc(tmp, stdin);

  while( scanf("%d", &secondArray[j]) == 1 && j < sizeof(secondArray) ) { 
    ++j; 
  }

  l1 = i; // preserve how many ints were read
  l2 = j;

/* Print this. */
  for(i = 0; i < l1; ++i)
  {
    printf("%d ", firstArray[i]);
  }
  putchar('\n');

  for(j=0; j < l2; ++j)
  {
    printf("%d ", secondArray[j]);
  }

  return 0;
}

编辑可能更适合您需要的解决方案是将行(每次一个)读入缓冲区并扫描缓冲区。

【讨论】:

    【解决方案4】:

    scanf 忽略空白字符(包括换行符)。因此,如果您没有“非空白”分隔符,您的扫描会将整个输入读入firstArray

    如果文件/数据在第一行末尾有;,它将停止对firstArray 的读取,并且永远不会将任何内容读入secondArray - 因为您永远不会使用;

    /* This will never be 1 as ; is blocking */
    while((scanf("%d", &secondArray[i])) == 1) { 
    

    所以:如果您与 ; 分开,您必须在读入 secondArray 之前阅读/检查此内容。

    您还可以添加类似的内容:

    char c;
    
    /* this can be done more tidy, but only as concept */
    while((scanf("%d", &firstArray[i])) == 1 && i < max) {
        ++i;
        if ((c = getchar()) == '\n' || c == ';')
            break;
    }
    

    你也可以说:

    int firstArray[50] = {0}; /* This set every item to 0 */
    

    还要注意确保不要超过 50 的限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      相关资源
      最近更新 更多