【问题标题】:Scanf multiple lines until reach specific character扫描多行直到到达特定字符
【发布时间】:2019-10-18 10:12:42
【问题描述】:

我的输入如下:

Someting sth
example
 5  15   
3

我想scanf逐行输入以获取该行的全部内容。但是当达到第一个数字时(前面可能有空格/制表符),我想将其扫描为 int。

这就是我想出的,但它不能按预期工作 - 光标仍然不会停在数字字符处。

char person_name[1000];
int n;

while (scanf("%[^\n/D]%*c", person_name) > 0) {
    if (checkIfContainsNumber(person_name) == 0) {
      appendToLinkedList(&head_ref, person_name);
    } else {
      break;
    }
}

while (scanf("%d", &n) > 0) {
    printf("%d ", n);
}

【问题讨论】:

  • 您已经阅读数字字符。 scanf("%s", person_name); 然后if(isdigit(person_name[0])) { int num = atoi(person_name); }
  • 是的,但如果我使用scanf("%s", person_name);,那么我会逐字阅读,而不是逐行阅读。我需要区分同一行是否有更多的单词。
  • 哦,那么在" %[^\n]"前面放一个空格来过滤前导空格。
  • 我尝试稍微编辑一下正则表达式,所以我的最终正则表达式看起来像:scanf(" %[^\n^0-9]%*c", person_name) - % 前面的空格有帮助。非常感谢。
  • 所以你现在不必费心删除 trailing 换行符了。

标签: c scanf


【解决方案1】:

据我了解的问题,每一行都可以被视为 名称序列或整数序列。
所以我会尝试逐行读取文件并分析每个提取的行 作为一个或另一个序列(隐式消耗空格)。
这里的诀窍是使用"%n" 进一步分析同一行。

#include <stdio.h>

int
main(void)
{
  FILE *input=fopen("input.txt", "r");
  if(!input)
  {
    return 1;
  }
  char line[1024];
  while(fgets(line, sizeof(line), input))
  {
    int pos=0;
    int value, count;
    char name[256];
    if(sscanf(line+pos, "%d%n", &value, &count)==1)
    {
      pos+=count;
      printf("a line with values: <%d>", value);
      while(sscanf(line+pos, "%d%n", &value, &count)==1)
      {
        pos+=count;
        printf(" <%d>", value);
      }
      printf("\n");
    }
    else if(sscanf(line+pos, "%255s%n", name, &count)==1)
    {
      pos+=count;
      printf("a line with names: <%s>", name);
      while(sscanf(line+pos, "%255s%n", name, &count)==1)
      {
        pos+=count;
        printf(" <%s>", name);
      }
      printf("\n");
    }
  }
  fclose(input);
  return 0;
}

【讨论】:

    【解决方案2】:

    使用fgets 逐行读取输入并保持模式:TEXT 用于文本,NUMBER 用于数字,ERROR 用于错误条件。 (错误情况未描述。例如在NUMBER模式下遇到非数字数据时可能发生。)

    TEXT 开始。在以文本模式处理一行之前,通过一个简单的sscanf 来检查它是否可以是一个数字。如果您可以读取数字,请切换到数字模式,在该模式下扫描一行中的所有数字。

    char line[80];
    enum {TEXT, NUMBER, ERROR = -1} mode = TEXT;
    
    while (mode != ERROR && fgets(line, sizeof(line), stdin)) {
        if (mode == TEXT) {
            int n;
    
            if (sscanf(line, "%d", &n) > 0) mode = NUMBER;
        }
    
        if (mode == TEXT) {
            line[strcspn(line, "\n")] = '\0';
            process_string(line);
        } else if (mode == NUMBER) {
            char *p = line;
            char *end;
            int n = strtol(p, &end, 0);
    
            if (end == p) mode = ERROR;
    
            while (end > p) {
                process_number(n);
                p = end;
                n = strtol(p, &end, 0);
            }            
        }
    }
    

    (但是如果数字都在一个很长的范围内,这种方法会失败。fgets 会截断输入,这样就不会超过指定的大小。)

    【讨论】:

      【解决方案3】:

      考虑更改扫描策略 - 忽略所有非数字字符,然后从该数字向前读取整数

      if ( scanf("%*[^0-9]%d", &n) == 1 ) { ... }
      

      第一个字段 '%*[...]' 将跳过任何非数字的内容。请注意,在找到数字之前可能会到达 EOF - if 语句需要检查。

      【讨论】:

        猜你喜欢
        • 2016-03-24
        • 2015-08-04
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 2020-03-06
        • 1970-01-01
        相关资源
        最近更新 更多