Is it possible to read lines of text with scanf() - excluding \n
and break on special(chosen) character, but include that character
This is my current expression: while(scanf("%49[^:\n]%*c", x)==1)
but this one excludes :
.
Is it possible to break reading on :
but read that character too?
Ok I am using Johannes-Schaub-litb's code.
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;
}
Still I use this code ...and it works fine.
The code will be modified a bit more later.
I have done this in a little different way. Maybe this can crash on windows. But, anyways here it is. Hope it helps. Merry Christmas.
#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');
}
}
EDIT:- I have used dot as a terminating character.
Is it possible to read lines of text with scanf() - excluding \n and break on special(chosen) character, but include that character(?)
Yes. But scanf()
is notorious for being used wrong and difficult to use right. Certainly the scanf()
approach will work for most user input. Only a rare implementation will completely meet OP's goal without missing corner cases. IMO, it is not worth it.
Alternatively, let us try the direct approach, repeatedly use fgetc()
. Some untested code:
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;
}
Sample usage
char buffer[50];
while (luvatar_readline(buffer, sizeof buffer_t, ':')) {
puts(buffer);
}
Corner cases TBD: Unclear what OP wants if special
is '\n'
or '\0'
.
OP's while(scanf("%49[^:\n]%*c", x)==1)
has many problems.
Does not cope with input the begins with :
or '\n'
, leaving x
unset.
Does not know if the character after the non-:
, non-'\n'
input was a :
, '\n'
, EOF.
Does not consume extra input past 49.
Uses a fixed spacial character ':'
, rather than a general one.
I think that you want to do that:
#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);
}