如何从一行输入中获取元组形式?

时间:2017-08-23 12:34:13

标签: c split

我在下面得到了一个代码。 如果用户输入(12,34,56,78),(1,2,3)
它只会输出:12,34,56,78,1,2,3
但我需要输出(12,34,56,78) (1,2,3)
我该怎么办?

#include <string.h>
#include <stdio.h>

int main(){
    char enter[100];
    int a;

    printf("Enter a string:");    
    scanf("%s",enter);
    char *tuples=strtok(enter,"()");
    while(tuples!=NULL){
        printf("%s",tuples);
        tuples=strtok(NULL,"()");
    }

}

4 个答案:

答案 0 :(得分:2)

strchr() 是一个可以帮助您的其他解析工具。它提供了一种快速定位字符串中特定字符的方法,并返回指向该位置的指针。此功能以及 sprintf() 可用于重建没有中间“,”的字符串。以下是一个例子。

int main(void)
{
    char string[40] = {"(12,34,56,78),(1,2,3)"};
    char *ret;
    int len1,len2;
    char *first = strdup(string);//a 2nd copy is needed to preserve the 1st half of string.
    char last[20];

    len1 = strlen(string);

    //in your example, the ')' character is the closest unique char to the 
    //target ',', so select this unique character to get close...
    ret = strchr(string, ')');//brings pointer to first ')'
    ret += 2; //increment pointer past next occurring "," to get second half of string
    strcpy(last, ret);

    len2 = strlen(last);
    first[len1-(len2+1)] = 0;//use length information to get first half

    sprintf(string, "%s %s", first, last); 
    printf(string);                 
    free(first);

    return 0;
}

输出:

  

(12,34,56,78)(1,2,3)

关于用户输入的说明:
在我看来,对于这个看似简单的场景,合法的语法(你没有说明规则)很容易导致变化,这将使解析和字符串重构的一般解决方案变得困难。例如,输入可以是以下任何一种:

(12,34,56,78),(1,2,3)  
( 12 , 34 , 56 , 78 ) , ( 1 , 2 , 3 )  
(12,34,56,78)      ,       (1,2,3)  
(and many more)    

请记住,要构建处理用户输入的一般方法,处理输入所需的代码的复杂性将与输入的边界(规则)成反比。即,如果规则为零,则复杂性将是无限的。如果有许多规则来管理允许的输入,则代码的复杂性将按比例缩小。

无限输入的一个很好的例子就是人们说话的方式。人们选择传达思想的方式很少遵循惯例。 ( natural language 与用户输入的变体类似)一些示例说明了处理自然语言 are listed here 所需的复杂性。

(你的帖子中的输入规则没有明确说明,所以在这里尝试一个简单的解决方案,除了那些输入语法类似于你的例子之外,不会满足任何其他方法)

答案 1 :(得分:0)

您需要使用比strtok更高级的解析。 strtok,当您了解如果阅读手册页(man strtok)时,将在每个分隔字符的出现之间返回字符串,对于您而言"()"

要获得所需的结果,您需要以下代码:

  1. 查找左括号
  2. 收集所有数字,直到右括号
  3. 从1
  4. 重复

    这种解析可以通过调用strtokstrstr,其他字符串函数来完成,也可以通过解析char的字符串char来手动完成。

    当你有你的内容列表时,你可以用圆括号打印它们(如果你愿意,可以不用逗号)。

答案 2 :(得分:0)

如果输入格式被限制为两个元组,如示例所示,那么您可以使用简单的sscanf()构造来解析它。请注意,在下面的解决方案中,有效输入包括可能的前导空格,后跟一个(字符,后跟一个非空字符串,后跟一个)字符,可能后跟更多的空格或逗号。需要进一步的输入验证来验证括号之间的字符串是否确实是元组。

#include <stdio.h>

int main(void)
{
    char input[] = "(12, 34, 56, 78),(1, 2, 3)";

    char tuple1[100];
    char tuple2[100];

    if (sscanf(input, " (%[^)]) , (%[^)]", tuple1, tuple2) == 2) {
        printf("(%s) (%s)\n", tuple1, tuple2);
    }

    return 0;
}

节目输出:

(12, 34, 56, 78) (1, 2, 3)

但是,如果输入元组的数量未知(不能期望大量的元组,因为在示例代码中enter已被声明为char enter[100]),此方法可以通过使用%n scanf()指令。该指令将迄今为止读取的字符数存储在其参数中。可以通过将此偏移值添加到指向初始输入字符串的指针来形成指向要读取的输入字符串的下一段的指针。

下面的程序要求用逗号分隔元组,并且如果两个元组之间没有逗号,则会停止解析,否则会遇到格式错误的输入。需要注意处理这种情况,因为如果格式字符串的最后一个逗号不匹配,则不会分配给offset。这里,offset被初始化为零,并在每次循环迭代结束时重置为零。在重置之前,如果offset已经为零,则不进行任何分配,这意味着最终的逗号不匹配(表示输入结束),并且退出循环。

#include <stdio.h>

int main(void)
{
    char input[] = "(12, 34, 56, 78),(1, 2, 3), (4, 5, 6, 7)";

    char tuple[100];
    char *next = input;
    int offset = 0;
    int ret_val = 0;

    do {
        ret_val = sscanf(next, " (%[^)]) ,%n", tuple, &offset);
        if (ret_val == 1) {
            printf("(%s) ", tuple);
            next += offset;
        }

        if (offset) {
            offset = 0;
        } else {
            break;
        }

    } while (ret_val == 1);
    putchar('\n');

    return 0;
}

节目输出:

(12, 34, 56, 78) (1, 2, 3) (4, 5, 6, 7)

答案 3 :(得分:0)

如果元组不包含子数:

void printTuples(char *s)
{
    char *str;
    char *tmps = s;
    int flag = 0;

    while (1)
    {
        str = strtok(tmps, "()");
        tmps = NULL;
        if (str == NULL) break;
        if((flag = !flag)) printf("( %s )", str);
    }
}