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

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

这是我当前的表达式: while(scanf("%49[^:\n]%*c", x)==1)但是这个不包括: 。 有可能打破阅读:但也读这个角色?

好的我正在使用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; } 

我仍然使用这个代码…它工作正常。 代码将稍后修改。

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

 #include  #include  #include  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'); } } 

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

是否可以使用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); } 

角落案例TBD:如果special'\n''\0'则不清楚OP想要什么。


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

  1. 不处理输入的开头:'\n' ,留下x设置。

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

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

  4. 使用固定的空间字符':' ,而不是一般的字符。

我想你想这样做:

 #include  #include  #include  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); }