I am working on a project that will have a driver program redirect its output into the standard input of my program, how would I be able to scan what this program is feeding into my program and have my program respond accordingly. I was thinking of using scanf
, would that work?
Additional info: In the first line of the input (out of many lines), the driver gives a number ending in a new line character (\n). Depending on that number, my program will parse the rest of the lines in the input and output a response. Each line will be a string of random letters and my program will need to dynamically allocate memory for each string. These strings will be part of a struct in a linked list.
CodePudding user response:
You can treat the input just like regular console input, all the console stdio input calls will work. Just dont try to have a conversation with it - ie dont go
Enter foodle count : dd
Invalid number
Enter Foodle count :
becuase there is nobody on the other end
CodePudding user response:
It is generally recommended to use a more robust method than scanf
, as it is full of edge cases, and offers little in the way of recovering from bad input.
A beginners' guide away from scanf()
is a decent read, although I would offer stricter advice: forget scanf
exists.
Given the requirement of
Each line will be a string of random letters and my program will need to dynamically allocate memory for each string. These strings will be part of a struct in a linked list.
POSIX getline
(or getdelim
) is a solid choice, if available. This function handles reading input from a file, and will dynamically allocate memory if requested.
Here is an example skeleton program, with functionality vaguely similar to what you have described.
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
char *input(FILE *file) {
char *line = NULL;
size_t n;
if (-1 == getline(&line, &n, file))
return NULL;
return line;
}
size_t parse_header(char *header) {
return 42;
}
void use_data(char *data) {
free(data);
}
int main(void) {
char *header = input(stdin);
char *data;
if (!header)
return EXIT_FAILURE;
size_t lines_expected = parse_header(header);
size_t lines_read = 0;
free(header);
while ((data = input(stdin))) {
lines_read ;
use_data(data);
}
if (lines_read != lines_expected)
fprintf(stderr, "Mismatched lines.\n");
}
If POSIX is not available on your system, or you just want to explore alternatives, one of the better methods the standard library offers for reading input is fgets
. Combined with malloc
, strlen
, and strcpy
, you have will have roughly implemented getline
, but do note the caveats in the provided fgets
manual.
While scanf
is a poor choice for both reading and parsing input, sscanf
remains useful for parsing strings, as you have greater control over the state of your data.
The strtol
/strtod
family of functions are usually preferred over atoi
style functions for parsing numbers, though they can be difficult to use properly.