我正在使用一个名为objective的结构,它由一个最多8000个字符的char名称组成(大部分时间会小得多),一个int id,一个int持续时间和一个名为deps的int数组可以有0到9000个元素。 这是:
typedef struct {
unsigned long id, duration, dep [9000];
char name [MAXNAME];
}Objective
我有一些函数可以使用这个结构,我可以添加一个,可以删除,可以打印等。 我需要使用终端来指定我想要做的事情,例如添加一个目标,我需要在终端上写“add id”名称“duration deps”。 所以这是我的问题开始的地方,在目标的名称,它必须在“”之间,如果不是命令无效。我也遇到了deps数组的问题,它可以有0到9000个元素,所以我永远不知道有多少,我必须将它们放入一个将成为目标的数组。我也不能在参数之间放两个空格。 输入行的一些示例:
“add 1”objective1“20 2 3 4 5” - 这会添加一个id为1的物镜,名称为“objective1”,持续时间为20,deps 2,3,4和5
“add 1 objective1 20 2 3 4 5” - 这是无效的,因为名称不在“”
之间“add 1”objective1“20” - 这会添加一个id为1的物镜,名称为“objective1”,持续时间为20且没有deps
“删除1” - 删除ID为1的目标
我在之前使用fgets的工作中得到了这个:
char input[82], col [6], na [80]; unsigned long a, b;
double c;
while(input[0] != 'q'){
if(fgets(input, sizeof(input), stdin)){
if(input[0] == 'p' && input[1] == '\n' && input[2] == '\0'){
list(matrix);
}
else if(input[0] == 'i' && input[1] == '\n' && input[2] == '\0'){
carac(matrix);
}
else if((sscanf(input, "%c %lu %lu %lf\n", &input[0],
&a, &b ,&c) == 4)){
adds(a, b, c, matrix);
}
else if(input[0] == 'l' && (sscanf(input, "%*c %lu\n", &a) == 1)){
printLine(a , matrix);
}
else if(input[0] == 'c' && (sscanf(input, "%*c %lu\n", &a) == 1)){
printColumn(a , matrix);
}
else if(input[0] == 'z' && (sscanf(input, "%*c %lf\n", &c) == 1)){
zero(c , matrix);
}
else if(input[0] == 'o' && input[1] == '\n' && input[2] == '\0'){
sortLine(matrix);
}
else if(input[0] == 'o' && (sscanf(input, "%*c %s\n", col) == 1) && strcmp(col, "column") == 0){
sortColumn(matrix);
}
else if(input[0] == 'w' && input[1] == '\n' && input[2] == '\0'){
file(matrix);
}
else if(input[0] == 'w' && (sscanf(input, "%*c %s\n", na) == 1) ){
newFile(na, matrix);
}
}
}
但是在这种情况下它必须有很大的不同,“”之间的名称,未知数量的deps元素和参数之间的空格使得这对我来说真的很难,有没有人对如何做到这一点或如何做一些建议我可以解决上面列出的一个问题吗?
答案 0 :(得分:0)
首先,关于用户输入的说明:我同意@ryyker,尝试提出一种易于解析的用户输入格式。尝试从一开始就使输入过于灵活会妨碍你,同时你应该专注于程序的逻辑。 但也许你不是那个选择格式的人,所以,继续......
您选择定义结构并使用fgets()也不错。 但是你把所有东西都放在一个while()结构中,这对你的代码没有帮助。我不会给你一个完整的代码,但只是指示你如何组织它。
我建议你分开:
第1部分: scanf()不好,因为你不知道这条线的长度。 继续在相当长的缓冲区上使用fgets,例如:
char buf[1024];
// ...
/* Maybe you'll want to use something else than fgets()
* later on. Encapsulate "reading from user" in a function. */
void read_user_input(char **buf, int size) {
*buf = fgets(*buf, size, stdin);
}
第2部分& 3: 编写小函数从缓冲区中提取标记, 并检查,例如他们每个人都被一个空间隔开, 或者用户在“名称”周围使用了引号。
/* Return the index of the first character of the next token
* in a string. Start searching from "idx".
* Tokens are separated by spaces. */
int next_token(char *buf, int idx, const int size) {
while (idx < size && is_whitespace(buf[idx])) {
++idx;
}
if (idx == size) {
return -1; // no token here
}
else {
return idx;
}
}
// ...
int check_spacing(char *buf, int size) {
/* Extract tokens, maybe fill struct Objective along
* the way. */
int idx = 0;
while (idx < size) {
int next_token_idx = next_token(buf, idx, size);
if (next_token_idx - idx > 1) {
// More than 1 space, not good!
}
}
}
第4部分: 你已经完成了这项工作:adds(),printLine(),printColumn()......
一旦你切入整齐的小函数,编写主循环就会容易得多:
main(int argc, char *argv[]) {
const int size = 1024;
char buf[size];
Objective obj = null;
// Read as long as the line is not finished.
do {
read_user_input(buf, size);
// Check that tokens are valid
// Build a struct Objective along the way
// obj = ... ;
// Also fetch the command: "add", "remove"...
} while (! contains_newline(buf));
// Now that you're confident user input is OK,
// you can execute command happily
if (strcmp(command, "add") == 0) {
// Add an objective
}
else if (strcmp(command, "remove") {
// Remove an objective
}
else if (strcmp(command, "i") {
carac(matrix);
}
// etc.
}