繁体   English   中英

如何使用 scanf_s 读取逗号分隔的数据集 - C 编程

[英]How to read comma separated data set using scanf_s - C Programming

我现在没有可以共享的工作代码,但基本上我想要实现的是读取用户输入或从以下格式的文件中读取:

1,2
2,5
3,4
4,5
etc...

或者

1,3 4,5 6,7 8,6 ... 所以逗号分隔的一对实数,我需要将它们分配给一个数组或二维数组并计算它们的均值、中位数、众数等...

我尝试了scanf_s("%d,",&n)东西,但到目前为止都没有解决。 我真的是 C 的新手并且来自 Java,所以一切都非常混乱。 如果有任何提示或只是一个例子,将不胜感激。 我知道你也可以使用 fgets、gets 或 sscanf,但我还没有学会这些。

这是另一个用户发送的代码:(但我不太明白,因为它给了我 src 可能是 0 错误)

#include <stdio.h>
#include <stdlib.h>
int main( void )
{
  char *src = (char*)malloc(sizeof(char) * 500);
  fgets(src, 500, stdin);
  int arr[500];
  int index = 0;
  int n;

  while ( sscanf ( src, "%d,%n", &arr[index], &n ) == 1 ) {  
    printf("%d\n", arr[index]);
    index++;
    src += n;
  }
  return 0;
}

scanf_s("%d,%d", &n1, &n2);

一次读取每行上的两个数字。 您不能将%d,用于第二个数字,因为它后面没有逗号。

scanf()返回已处理的输入数。 由于您一次读取两个数字,您应该检查它是否返回2 ,而不是1

int n1, n2;
while (scanf("%d , %d", &n1, &n2) == 2 ) { 
    printf("first number = %d, second number = %d\n", n1, n2);
}

如果输入格式可能真的不同(你的问题不是很确定), strtod()是你的主要武器。

char *P = MyLine, *NewP;   //MyLine is the input line
double Val[2];
do {
  Val[0]=strtod(P, &NewP);  //It reads the first value and shifts the pointer.
  if (NewP==P) return ERROR_EMPTY_STRING; //No values found! Sometimes maybe OK, if empty lines are allowed.
  P=NewP;
  while (*P == ' ') P++; //Omitting empty space between first value and comma.
  if (*P!=',') return ERROR_WRONG_FORMAT; //Wrong input: no comma between the values!
  Val[1]=strtod(P, &NewP);  //It reads the second value and shifts the pointer.
  if (NewP==P) return ERROR_WRONG_FORMAT; //No second value found! This is definitely not OK.
  P=NewP;
  while (*P == ' ') P++; //Omitting probable trailing spaces (we don't need it for strtod() because it does it by itself, but we need it for the endline check);
  ProcessSomehow(Val);   //Process the pair
} while (*P && *P != '\r' && *P != '\n' );
return LINE_ENDED_OK;

此代码将解析

1,2
3,4
5,6

1,2 3,4 5,6
7,8 9,10 11,12

甚至这个

 2, 4 1 , 5 6 ,8
1,3 4, 4
1,4 6 ,4    6, 8   2,7  2, 12  4, 8

任何东西,只要它们是逗号分隔的对,并且每一对至少用一个空格分隔。 您还可以轻松修改它以允许1,2; 4, 3; 2, 3 7, 2 1,2; 4, 3; 2, 3 7, 2 1,2; 4, 3; 2, 3 7, 2或任何其他额外的分隔符。

#define错误代码根据您自己的喜好(或使用任何其他错误处理,如果您愿意)。

有(至少)两个主要的解决方案。 一是继续单数读,这样你真的不会太在意有没有逗号; 另一种是成对读取数字。

选项 A 涉及对格式字符串从"%d,%n""%d %n"的细微调整,以便您找出数字的结尾(更准确地说,不是空格的第一个字符出现在数字之后的位置) , 并在循环中单独跳过逗号:

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

int main(void)
{
    char data[500];
    char *src = data;
    fgets(src, 500, stdin);
    int arr[500];
    int index = 0;
    int n;

    while (sscanf(src, "%d %n", &arr[index], &n) == 1)
    {
        printf("%d\n", arr[index++]);
        src += n;
        if (*src == ',')
        {
            putchar('=');
            src++;
        }
    }
    return 0;
}

putchar('=')让我看到逗号何时被跳过; 它不会出现在“生产”代码中。

示例输出(BashHere 字符串表示法):

$ read41 <<< '1,2  3,4   5,6   7, 8   9,10, 11 , 12xyz'
1
=2
3
=4
5
=6
7
=8
9
=10
=11
=12
$

小心—— scanf()格式中的尾随空白对于交互式输入来说是毁灭性的,但对sscanf()无害的。 请注意,数据中10后有一个杂散的逗号,但此版本的代码并不关心这一点。 它也不关心换行符成对出现的位置(或者如果它在while (fgets(data, sizeof(data), stdin) != 0) { char *src = data; … }上迭代, while (fgets(data, sizeof(data), stdin) != 0) { char *src = data; … }不会关心它)。

选项 B 涉及成对阅读数字。 由于您在循环中使用sscanf() ,因此您仍然需要%n转换规范。 格式字符串中的第二个空格(逗号之后)不是绝对必要的( %d也会跳过空格),但它是无害的和对称的。 这要求必须在同一行上的成对数字之间有一个逗号(但逗号周围允许有空格或没有空格),并且成对必须出现在同一行上。

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

int main(void)
{
    char data[500];
    int arr[500];
    int index = 0;

    while (fgets(data, sizeof(data), stdin) != 0)
    {
        int n;
        char *src = data;
        while (sscanf(src, "%d , %d %n", &arr[index + 0], &arr[index + 1], &n) == 2)
        {
            printf("(%d,%d)\n", arr[index + 0], arr[index + 1]);
            src += n;
            index += 2;
        }
    }
    return 0;
}

示例输出(也使用 Bash ANSI-C Quoting ):

$ read43 <<< $'1,2  3,4   5,6   7,8\n9,10 11 , 12xyz'
(1,2)
(3,4)
(5,6)
(7,8)
(9,10)
(11,12)
$

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM