使用scanf读取行或打破特殊字符

时间:2016-12-24 17:12:07

标签: c scanf

是否可以使用scanf()读取文本行 - 排除\n并打破特殊(选定)字符,但包含该字符

这是我目前的表达:while(scanf("%49[^:\n]%*c", x)==1) 但是这个被排除在:之外。 是否有可能打破:上的阅读但是也读过这个角色?

4 个答案:

答案 0 :(得分:4)

好的我正在使用 Johannes-Schaub-litb的代码。

char * getline(char cp) {
    char * line = malloc(100), * linep = line;
    size_t lenmax = 100, len = lenmax;
    int c;


    if(line == NULL)
        return NULL;

    for(;;) {
        c = fgetc(stdin);
        if(c == EOF)
            break;

        if(--len == 0) {
            len = lenmax;
            intptr_t diff = line - linep;
            char * linen = realloc(linep, lenmax *= 2);

            if(linen == NULL) {
                free(linep);
                return NULL;
            }
            line = linen + diff;
            linep = linen;
        }

        if((*line++ = c) == cp)
            break;
    }
    *line = '\0';
    return linep;
}

我仍然使用此代码......它运行正常。 稍后会对代码进行修改。

答案 1 :(得分:0)

我以一种不同的方式做到了这一点。也许这会在Windows上崩溃。但是,无论如何它在这里。希望能帮助到你。圣诞节快乐。

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

int main() {
    char *input_str;

    /**
     * Dynamic memory allocation.
     * Might crash on windows.
     */
    int status = scanf("%m[^.]", &input_str);

    /**
     * If the first character is the 
     * terminating character then scanf scans nothing
     * and returns 0.
     */
    if (status > 0) {
        /**
         * Calculate the length of the string.
         */
        size_t len = strlen(input_str);

        /**
         * While allocating memory provide
         * two extra cell. One for the character 
         * you want to include.
         * One for the NULL character.
         */
        char *new_str = (char*) calloc (len + 2, sizeof(char));

        /**
         * Check for memory allocation.
         */
        if(new_str == NULL) {
            printf("Memory Allocation failed\n");
            exit(1);
        }

        /**
         * Copy the string.
         */
        strcpy(new_str, input_str, len);

        /**
         * get your desired terminating character 
         * from buffer
         */
        new_str[len++] = getc(stdin);

        /**
         * Append the NULL character
         */
        new_str[len++] = '\0';

        /**
         * eat other characters
         * from buffer.
         */
        while(getc(stdin) != '\n');

        /**
         * Free the memory used in
         * dynamic memory allocation
         * in scanf. Which is a must
         * according to the scanf man page.
         */
        free(input_str);
    } else {
        char new_str[2] = ".\0";
        /**
         * eat other characters
         * from buffer.
         */
        while(getc(stdin) != '\n');
    }
}

编辑: - 我使用点作为终止字符。

答案 2 :(得分:0)

  

是否可以使用scanf()读取文本行 - 排除\ n并打破特殊(选定)字符,但包含该字符(?)

是。但scanf()因使用错误而难以正确使用而臭名昭着。当然,scanf()方法适用于大多数用户输入。只有罕见的实施才能完全达到OP的目标,而不会遗漏角落案例。 IMO,这不值得。

或者,让我们尝试直接方法,重复使用fgetc()。一些未经测试的代码:

char *luvatar_readline(char *destination, size_t size, char special) {
  assert(size > 0);
  char *p = destitution;

  int ch;
  while (((ch = fgetc(stdin)) != EOF) && (ch != '\n')) {
    if (size > 1) {
      size--;  
      *p++ = ch; 
    } else {
      // Ignore extra input or 
      // TBD what should be done if no room left
    }
    if (ch == (unsigned char) special) {
      break;
    }
  }
  *p = '\0';

  if (ch == EOF) {
    // If rare input error
    if (ferror(stdin)) {
      return NULL;
    }
    // If nothing read and end-of-file  
    if ((p == destination) && feof(stdin)) {
      return NULL;
    }
  }
  return destination;
}      

样本用法

char buffer[50];
while (luvatar_readline(buffer, sizeof buffer_t, ':')) { 
  puts(buffer);
}

角落案件待定:如果special'\n''\0',则不清楚OP需要什么。

OP while(scanf("%49[^:\n]%*c", x)==1)有很多问题。

  1. 无法处理开始:'\n'的输入,而x未设置。

  2. 不知道非:,非'\n'输入后的字符是:'\n',EOF。

  3. 不会消耗超过49的额外输入。

  4. 使用固定的空格字符':',而非普通字符。

答案 3 :(得分:0)

我认为你想这样做:

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

int main(void) {
  char *line = NULL;
  size_t len = 0;
  ssize_t read;
  while ((read = getline(&line, &len, stdin)) != -1) {
    if (read > 0 && line[read - 1] == '\n') {
      if (read > 1 && line[read - 2] == '\r') {
        line[read - 2] = '\0'; // we can remove the carriage return
      }
      else {
        line[read - 1] = '\0'; // we can remove the new line
      }
    }

    char const *delim = ":";
    printf("parsing line :\n");
    char *token = strtok(line, delim);

    while (token != NULL) {
      printf("token: %s\n", token);
      token = strtok(NULL, delim);
    }
  }
  free(line);
}