【问题标题】:Scanf for reading string and int array in bracketsScanf 用于读取括号中的字符串和 int 数组
【发布时间】:2016-12-07 13:52:13
【问题描述】:

我一直在尝试提出解决方案来读取包含字符串的输入,然后是带有数字数组的括号(我不知道将输入多少个数字。

输入可能如下所示:

sacrifice (1, 2, 4, 2)

我想知道是否可以使用 scanf 来实现。我一直在寻找不同的函数,例如 getline、sscanf、fgets 等。但我想不出解决办法。

我的代码如下所示:

    scanf("%[^(]", command);
    while ( ( c = getchar() ) != ')' )
    {
        scanf("%d", weights[pos]);
        pos++;
    }

在找到括号之前应该读取字符串,然后我尝试加载数组中的数字,只要它没有到达')'。但它似乎不起作用。

scanf 是否可行?如果不是请谁能给我指出更好的方向?

【问题讨论】:

  • 当您使用getchar 搜索结束括号时,您提取输入缓冲区中的字符并丢失它们。还要记住scanf 的参数必须是指针
  • 所以如果我问如果 c = getchar() 不是 ')' 之后我就不能再扫描它了吗?
  • 您正在因为使用getchar 而丢失字符。您必须使用 c (变量),在 while 正文中包含 getchar()-ed。
  • 当我尝试这样做时,它给了我分段错误。有没有办法以某种方式存储这些数字,然后根据我拥有的数字创建动态分配的数组?

标签: c arrays string scanf


【解决方案1】:

我认为从标准输入读取完整行然后使用strtokstrcspn 手动解析它会更简单。可以做类似下面的事情。

免责声明:这只是一些示例代码,并不能处理所有可能的输入,并且会因输入无效而崩溃,它只是为了让您了解如何操作。如果你想这样做,你将不得不处理各种错误情况,例如:

  • 检查malloc/getline/realloc的返回值
  • 而不是 atoi 使用更好的函数,如 strtol(允许错误检查),
  • 处理输入中的空白和
  • 处理不包含任何括号的输入

这些是您必须考虑的许多事情中的一部分。

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

static int *parse_numbers(char *numstr, size_t *size)
{
    char *p;
    char *s = numstr;
    char *last;
    size_t array_size = 10;
    int *numbers = malloc(sizeof(int) * array_size);
    size_t offset = 0;
    for (p = strtok_r(s, ",", &last); p; p = strtok_r(NULL, ",", &last)) {
        if (offset == array_size) {
            array_size *= 2;
            numbers = realloc(numbers, sizeof(int) * array_size);
            //TODO do error check
        }
        numbers[offset++] = atoi(p); //strtol would be a better choice
    }
    *size = offset;
    return numbers;
}

int main()
{
    char *s = NULL;
    char *p;
    char *last;
    int i = 0;
    int *numbers;
    size_t size;
    size_t linesize = 0;

    getline(&s, &linesize, stdin);
    for (p = strtok_r(s, "(", &last); p; p = strtok_r(NULL, "(", &last)) {
        if (i++ == 0) {
            //This is the part of the string before '('
            cmd = p;
        } else {
            // This is the part of the string after '('
            numbers = parse_numbers(p, &size);
        }
    }
    for (i = 0; i < size; i++) {
        printf("%d\n", numbers[i]);
    }
    free(numbers);
    free(s);
    return 0;
}

【讨论】:

    【解决方案2】:

    将输入与解析分开。处理命令处理的各种问题要容易得多。关于“不知道会输入多少数字”,IMO应该建立一个合理的上限。其他代码很容易因用户输入而占用大量内存资源 - 黑客利用。

    char command[1000];
    while (fgets(command, sizeof command, stdin)) {
    

    现在使用sscanf()strtok() 或您自己的代码处理命令。最好的方法可能取决于 OP 未发布的内容,尤其是错误处理。

        int cmd_start;
        int cmd_end;
        int n = 0;
        // sacrifice (1, 2, 4, 2, ...)
        //               +----------------- skip optional white space
        //               |+---------------- record scan position 
        //               || +-------------- scan, but not save, lower case letters
        //               || |      +------- record scan position 
        //               || |      | +----- skip optional white space
        //               || |      | |+---- scan (
        //               || |      | ||+--- skip optional white space
        //               || |      | |||+-- record scan position 
        sscanf(command, " %n%*[a-z]%n ( %n", &cmd_start, &cmd_end, &n);
        if (n == 0) {
          printf("Invalid command '%s'\n", command);
          continue;
        }
        int x[sizeof command / 2];
        int x_count = 0;
        char *p = &command[n];  // pick up where previous scan ended.
    
        char sep[2] = {0};
        while (sscanf(p, "%d %1[,)] %n", &x[x_count], sep, &n) == 2) {
          x_count++;
          p += n;
          if (sep[0] == ')') break;
        }
    
        if (*p || sep[0] != ')') {
          printf("Invalid separator '%s'\n", command);
          continue;
        }
    
        // Use command 
        command[cmd_end] = '\0';
        Process_Command(&command[cmd_start], x, x_count);
      }
    

    【讨论】:

      【解决方案3】:

      scanf("%d", weights[pos]); --> scanf("%d", &amp;weights[pos]); – BLUEPIXY

      这确实足以使代码工作,提供足够尺寸的weights 数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多