I have to take three inputs in a single string.
The code to take the input is:
char msg_send[1000];
gets(msg_send);
The input is like
GET /api HTTP/1.1
id=1&name=phoenix&mail=bringchills@ppks.com
That means there is a newline after the fist line GET /api HTTP/1.1
. The next line is an empty newline. The input taking function should terminate after taking the 3rd newline.
Also, I have to terminate the input after the first line GET /something HTTP/1.1
if the line doesn't have a /api
word at the place of /something
word.
But when I'm using gets(), it terminates the string after taking GET /api HTTP/1.1
part of the input. When using scanf, it terminates after taking only the first GET
word. Is there any way to take the input as a single string?
In cases like these, you should just use getchar in a loop:
#define MAX_MSG_BUF 1000
char char msg_send[MAX_MSG_BUF];
// you should wrap the below code in a function, like get3lines(buf, buf_size)
unsigned index = 0;
unsigned line_count = 0;
const unsigned buf_size = MAX_MSG_BUF;
do {
int tmp = getchar();
if (tmp < 0) break; // end of file or error
msg_send[index++] = tmp;
if (tmp == '\n') {
++line_count;
if (line_count == 1) {
// check that first line contains /api
if (!first_line_valid(msg_send, index)) break;
}
}
} while (index < (MAX_MSG_BUF-1) && line_count < 3;
msg_send[index] = '\0';
// print error if line_count < 3 ?
The first_line_valid
function might look like this (note: needs #include <stdbool.h>
for bool type):
bool starts_with(const char *str, size_t length, const char *prefix) {
size_t i = 0;
for(;;) {
if (i == length || prefix[i] == '\0') return true;
if (str[i] != prefix[i]) return false; // does catch end of str
++i;
}
}
bool first_line_valid(const char *buf, size_t buf_size) {
// note: buf might not be NUL-terminated so use buf_size
if (starts_with(buf, buf_size, "GET /api ")) return true;
if (starts_with(buf, buf_size, "GET /api/")) return true;
return false;
}