【问题标题】:Reading Integers From A Buffer into an Array in C将整数从缓冲区读取到 C 中的数组中
【发布时间】:2016-03-16 01:23:12
【问题描述】:

所以我试图将从键盘读取的 int 值存储到 C 中的整数数组中。示例用户输入:

8 99 5 7 8

变量声明:

int k;
int size;
char buf[100];

以上是我的缓冲区和数组的其他变量。 下面是把整数读入缓冲区。

printf("Please enter in the numbers for the array:\n");
fgets(buf, 100, stdin);
buf[strlen(buf) - 1] = '\0';

size = (strlen(buf)/2)+1;

int *array = (int *)malloc(sizeof(int)*size);

这样才能正确分配我的数组。

int i, j;
for(i = 0, j = 0; i < size; i++, j = j+2)
{
    array[i] = buf[j] - '0';
}

上面的代码确实有效,但不适用于具有两位数的数字,仅适用于低于 10 和高于 0 的数字。如何修复我的代码以便正确读取整数? 我试图用sscanf 做一个for 循环,但这只会导致一个数组,所有元素中只输入第一个整​​数。

【问题讨论】:

  • 你可能想看看strtol()
  • @EOF 你的意思是strtok()
  • @MikeCAT:不,我指的是名为strtol()的“字符串到长”函数。
  • strtok() 可能还是有用的。

标签: c arrays buffer


【解决方案1】:

如何修复我的代码以便正确读取整数?

按照@EOF 的建议,使用strtol() 解析字符串。它在它停止的地方提供了一个结束指针。

long *array = malloc(sizeof *array * size);
if (array == NULL) Handle_OutOfMemory();

char *p = buf;
size_t i;
for(i = 0; i<size; i++) {
  // Cope with white space with nothing after it.
  while (isspace((unsigned char) *p)) p++;
  if (*p == '\0') break;

  char *end;
  errno = 0;
  long num = strtol(p, &end, 10);
  // If no conversion or out of range ...
  if (p == end || errno) {
    fprintf(stderr, "trouble converting `%s` into an integer.\n", p);
    break;
  }
  array[i] = num;
  p = end;
}

// Use array[0] ... array[i-1]

【讨论】:

    【解决方案2】:

    您可以使用sscanfstrtol 从输入字符串中提取数字。无论哪种情况,每次通话都会为您提供三条信息:

    • 发现有效号码的指示
    • 那个数字的值
    • 输入数组中将找到下一个数字的位置

    使用sscanf,返回值表示成功或失败。对于示例代码中的sscanf(见下文),返回值为 1 表示成功,否则为失败。如果成功,则将数字的值放置在指定的地址,例如示例代码中的&amp;temp

    这是棘手的部分:您需要数组中的位置来开始搜索下一个数字。 sscanf 有一个特殊的转换,%n 转换。 %n 的输出是执行转换时消耗的字符数。

    在下面的示例代码中,我使用了一个指针ptr,它最初指向输入字符串的开头。每次通过循环时,%nsscanf 中使用以更新变量n,这表明转换当前数字消耗了多少字符。通过在for 循环中将n 添加到ptr,指针前进到下一个数字。

    int *array = malloc(sizeof(int) * size);
    int n = 0;
    int i = 0;
    for ( char *ptr = buf; *ptr; ptr += n )
    {
        int temp;
        if ( sscanf(ptr, "%d %n", &temp, &n) != 1 ) {
            // error: not a number
            break;
        }
        array[i++] = temp;
    }
    

    正如@chux 在 cmets 中所提到的,在格式字符串"%d %n" 中添加一个空格将消耗每个数字后的尾随空格并相应地设置n 的值。因此,如果输入行仅包含数字,则循环将在 for 语句检测到 *ptr 已到达 NUL 终止符时结束。但是如果输入包含一个非数字,那么当sscanf 失败时循环将break。这可用于错误检查。

    【讨论】:

    • "%d %n" 带有空格可以很好地消耗尾随空格,例如'\n'。有助于区分 ptr 是否按预期完成。
    【解决方案3】:
    unsigned int len=0,tmp=0;
    char j,isnumber=0;
    for(char*i=buf;j=*i;i++)
    {
        if(j>='0'&&j<='9')
        {
            tmp=tmp*10+j-'0';
            isnumber=1;
        }
        else
        {
            if(isnumber)
                array[len++]=tmp;
            tmp=0;
            isnumber=0;
        }
    }
    

    另外,你不需要

    buf[strlen(buf) - 1] = '\0';
    
    size = (strlen(buf)/2)+1;
    

    【讨论】:

    • 你如何声明(并在需要时初始化)array
    • unsigned int array[50];
    • 空格不仅仅用于缩进。它们还极大地增强了标记之间的可读性。而且 - 除非有充分的理由不 - 应该使用标准库的函数。
    【解决方案4】:

    如果数字来自stdin,则将它们作为字符串读入并自己进行转换比让标准库为你做更多的努力。在这里,我硬编码了最多 100 个整数。循环结束后,i 将代表array 中有效整数的个数。

    int array[100] = {0};
    int i = 0;
    
    while (i < 100)
    {
        int input;
        int scanresult = scanf("%d", &input);
    
        if (scanresult == 1)
        {
            // 1 item was successfully scanned
            array[i] = input;
            i++;
        }
        else
        {
            // either EOF was reached or the input was not scannable as an integer
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多